diff --git a/mitmproxy/web/app.py b/mitmproxy/web/app.py index 18745f5b2..da70c57fd 100644 --- a/mitmproxy/web/app.py +++ b/mitmproxy/web/app.py @@ -345,24 +345,6 @@ class FlowContentView(RequestHandler): def get(self, flow_id, message, content_view): message = getattr(self.flow, message) - original_cd = message.headers.get("Content-Disposition", None) - filename = None - if original_cd: - filename = re.search("filename=([\w\" \.\-\(\)]+)", original_cd) - if filename: - filename = filename.group(1) - if not filename: - filename = self.flow.request.path.split("?")[0].split("/")[-1] - - filename = re.sub(r"[^\w\" \.\-\(\)]", "", filename) - cd = "attachment; filename={}".format(filename) - self.set_header("Content-Disposition", cd) - self.set_header("Content-Type", "application/json") - self.set_header("X-Content-Type-Options", "nosniff") - self.set_header("X-Frame-Options", "DENY") - - self.set_header("Content-Encoding", "") - description, lines, error = contentviews.get_message_content_view( contentviews.get(content_view.replace('_', ' ')), message ) diff --git a/mitmproxy/web/static/app.js b/mitmproxy/web/static/app.js index f2c128665..d376b5e3e 100644 --- a/mitmproxy/web/static/app.js +++ b/mitmproxy/web/static/app.js @@ -1,166 +1,9129 @@ (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;o1048576*(ContentViews.ViewImage.matches(e)?10:.2)},exports.default=(0,_reactRedux.connect)(function(e){return{contentView:e.ui.contentView,displayLarge:e.ui.displayLarge}},{selectView:_ui.setContentView,setDisplayLarge:_ui.setDisplayLarge})(ContentView); +var cachedSetTimeout; +var cachedClearTimeout; -},{"../ducks/ui":48,"../flow/utils.js":53,"./ContentView/ContentLoader":4,"./ContentView/ContentViews":5,"./ContentView/MetaViews":6,"./ContentView/ViewSelector":7,"react":"react","react-redux":"react-redux"}],4:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var n=0;n 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; -},{"../ducks/eventLog":42,"./EventLog/EventList":9,"./common/ToggleButton":36,"react":"react","react-redux":"react-redux"}],9:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function LogIcon(e){var t=e.event,r={web:"html5",debug:"bug"}[t.level]||"info";return _react2.default.createElement("i",{className:"fa fa-fw fa-"+r})}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;rc+s&&(l.scrollTop=u-s)}}},{key:"componentWillReceiveProps",value:function(e){e.selected&&e.selected!==this.props.selected&&(this.shouldScrollIntoView=!0)}},{key:"onViewportUpdate",value:function(){var e=_reactDom2.default.findDOMNode(this),t=e.scrollTop,o=(0,_VirtualScroll.calcVScroll)({viewportTop:t,viewportHeight:e.offsetHeight,itemCount:this.props.flows.length,rowHeight:this.props.rowHeight});this.state.viewportTop===t&&(0,_shallowequal2.default)(this.state.vScroll,o)||this.setState({vScroll:o,viewportTop:t})}},{key:"render",value:function(){var e=this,t=this.state,o=t.vScroll,r=t.viewportTop,l=this.props,a=l.flows,i=l.selected,n=l.highlight,u=n?_filt2.default.parse(n):function(){return!1};return _react2.default.createElement("div",{className:"flow-table",onScroll:this.onViewportUpdate},_react2.default.createElement("table",null,_react2.default.createElement("thead",{ref:"head",style:{transform:"translateY("+r+"px)"}},_react2.default.createElement(_FlowTableHead2.default,null)),_react2.default.createElement("tbody",null,_react2.default.createElement("tr",{style:{height:o.paddingTop}}),a.slice(o.start,o.end).map(function(t){return _react2.default.createElement(_FlowRow2.default,{key:t.id,flow:t,selected:t===i,highlighted:u(t),onSelect:e.props.onSelect})}),_react2.default.createElement("tr",{style:{height:o.paddingBottom}}))))}}]),t}(_react2.default.Component);FlowTable.propTypes={onSelect:_react.PropTypes.func.isRequired,flows:_react.PropTypes.array.isRequired,rowHeight:_react.PropTypes.number,highlight:_react.PropTypes.string,selected:_react.PropTypes.object},FlowTable.defaultProps={rowHeight:32},exports.default=(0,_AutoScroll2.default)(FlowTable); +function noop() {} -},{"../filt/filt":52,"./FlowTable/FlowRow":12,"./FlowTable/FlowTableHead":13,"./helpers/AutoScroll":38,"./helpers/VirtualScroll":39,"react":"react","react-dom":"react-dom","shallowequal":"shallowequal"}],11:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function TLSColumn(e){var t=e.flow;return _react2.default.createElement("td",{className:(0,_classnames2.default)("col-tls","https"===t.request.scheme?"col-tls-https":"col-tls-http")})}function IconColumn(e){var t=e.flow;return _react2.default.createElement("td",{className:"col-icon"},_react2.default.createElement("div",{className:(0,_classnames2.default)("resource-icon",IconColumn.getIcon(t))}))}function PathColumn(e){var t=e.flow;return _react2.default.createElement("td",{className:"col-path"},t.request.is_replay&&_react2.default.createElement("i",{className:"fa fa-fw fa-repeat pull-right"}),t.intercepted&&_react2.default.createElement("i",{className:"fa fa-fw fa-pause pull-right"}),_utils.RequestUtils.pretty_url(t.request))}function MethodColumn(e){var t=e.flow;return _react2.default.createElement("td",{className:"col-method"},t.request.method)}function StatusColumn(e){var t=e.flow;return _react2.default.createElement("td",{className:"col-status"},t.response&&t.response.status_code)}function SizeColumn(e){var t=e.flow;return _react2.default.createElement("td",{className:"col-size"},(0,_utils2.formatSize)(SizeColumn.getTotalSize(t)))}function TimeColumn(e){var t=e.flow;return _react2.default.createElement("td",{className:"col-time"},t.response?(0,_utils2.formatTimeDelta)(1e3*(t.response.timestamp_end-t.request.timestamp_start)):"...")}Object.defineProperty(exports,"__esModule",{value:!0}),exports.TLSColumn=TLSColumn,exports.IconColumn=IconColumn,exports.PathColumn=PathColumn,exports.MethodColumn=MethodColumn,exports.StatusColumn=StatusColumn,exports.SizeColumn=SizeColumn,exports.TimeColumn=TimeColumn;var _react=require("react"),_react2=_interopRequireDefault(_react),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_utils=require("../../flow/utils.js"),_utils2=require("../../utils.js");TLSColumn.headerClass="col-tls",TLSColumn.headerName="",IconColumn.headerClass="col-icon",IconColumn.headerName="",IconColumn.getIcon=function(e){if(!e.response)return"resource-icon-plain";var t=_utils.ResponseUtils.getContentType(e.response)||"";return 304===e.response.status_code?"resource-icon-not-modified":300<=e.response.status_code&&e.response.status_code<400?"resource-icon-redirect":t.indexOf("image")>=0?"resource-icon-image":t.indexOf("javascript")>=0?"resource-icon-js":t.indexOf("css")>=0?"resource-icon-css":t.indexOf("html")>=0?"resource-icon-document":"resource-icon-plain"},PathColumn.headerClass="col-path",PathColumn.headerName="Path",MethodColumn.headerClass="col-method",MethodColumn.headerName="Method",StatusColumn.headerClass="col-status",StatusColumn.headerName="Status",SizeColumn.getTotalSize=function(e){var t=e.request.contentLength;return e.response&&(t+=e.response.contentLength||0),t},SizeColumn.headerClass="col-size",SizeColumn.headerName="Size",TimeColumn.headerClass="col-time",TimeColumn.headerName="Time",exports.default=[TLSColumn,IconColumn,PathColumn,MethodColumn,StatusColumn,SizeColumn,TimeColumn]; +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; -},{"../../flow/utils.js":53,"../../utils.js":54,"classnames":"classnames","react":"react"}],12:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function FlowRow(e){var t=e.flow,r=e.selected,l=e.highlighted,o=e.onSelect,s=(0,_classnames2.default)({selected:r,highlighted:l,intercepted:t.intercepted,"has-request":t.request,"has-response":t.response});return _react2.default.createElement("tr",{className:s,onClick:function(){return o(t)}},_FlowColumns2.default.map(function(e){return _react2.default.createElement(e,{key:e.name,flow:t})}))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=FlowRow;var _react=require("react"),_react2=_interopRequireDefault(_react),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_FlowColumns=require("./FlowColumns"),_FlowColumns2=_interopRequireDefault(_FlowColumns);FlowRow.propTypes={onSelect:_react.PropTypes.func.isRequired,flow:_react.PropTypes.object.isRequired,highlighted:_react.PropTypes.bool,selected:_react.PropTypes.bool}; +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; -},{"./FlowColumns":11,"classnames":"classnames","react":"react"}],13:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function FlowTableHead(e){var r=e.sortColumn,t=e.sortDesc,a=e.updateSort,o=t?"sort-desc":"sort-asc";return _react2.default.createElement("tr",null,_FlowColumns2.default.map(function(e){return _react2.default.createElement("th",{className:(0,_classnames2.default)(e.headerClass,r===e.name&&o),key:e.name,onClick:function(){return a(e.name,e.name===r&&!t)}},e.headerName)}))}Object.defineProperty(exports,"__esModule",{value:!0});var _react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_FlowColumns=require("./FlowColumns"),_FlowColumns2=_interopRequireDefault(_FlowColumns),_flowView=require("../../ducks/flowView");FlowTableHead.propTypes={updateSort:_react.PropTypes.func.isRequired,sortDesc:_react2.default.PropTypes.bool.isRequired,sortColumn:_react2.default.PropTypes.string},exports.default=(0,_reactRedux.connect)(function(e){return{sortDesc:e.flowView.sort.desc,sortColumn:e.flowView.sort.column}},{updateSort:_flowView.updateSort})(FlowTableHead); +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; -},{"../../ducks/flowView":43,"./FlowColumns":11,"classnames":"classnames","react":"react","react-redux":"react-redux"}],14:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r0&&(r.preventDefault(),this.refs[e-1+"-value"].focus())}},{key:"render",value:function(){var e=this,t=this.props.message;return _react2.default.createElement("table",{className:"header-table"},_react2.default.createElement("tbody",null,t.headers.map(function(t,r){return _react2.default.createElement("tr",{key:r},_react2.default.createElement("td",{className:"header-name"},_react2.default.createElement(HeaderEditor,{ref:r+"-key",content:t[0],onDone:function(t){return e.onChange(r,0,t)},onRemove:function(t){return e.onRemove(r,0,t)},onTab:function(t){return e.onTab(r,0,t)}}),":"),_react2.default.createElement("td",{className:"header-value"},_react2.default.createElement(HeaderEditor,{ref:r+"-value",content:t[1],onDone:function(t){return e.onChange(r,1,t)},onRemove:function(t){return e.onRemove(r,1,t)},onTab:function(t){return e.onTab(r,1,t)}})))})))}}]),t}(_react.Component);Headers.propTypes={onChange:_react.PropTypes.func.isRequired,message:_react.PropTypes.object.isRequired},exports.default=Headers; +var _dispatcher = require("./dispatcher.js"); -},{"../../utils.js":54,"../ValueEditor":31,"react":"react","react-dom":"react-dom"}],17:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function ErrorView(e){var t=e.flow;return _react2.default.createElement("section",null,_react2.default.createElement("div",{className:"alert alert-warning"},t.error.msg,_react2.default.createElement("div",null,_react2.default.createElement("small",null,(0,_utils2.formatTimeStamp)(t.error.timestamp)))))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.Response=exports.Request=void 0;var _createClass=function(){function e(e,t){for(var r=0;r0&&(this.props.loadFlows(e.target.files[0]),this.fileInput.value="")}},{key:"onSaveClick",value:function(e){e.preventDefault(),this.props.saveFlows()}},{key:"render",value:function(){var e=this;return _react2.default.createElement("div",{className:(0,_classnames2.default)("dropdown pull-left",{open:this.state.show})},_react2.default.createElement("a",{href:"#",className:"special",onClick:this.onFileClick},"mitmproxy"),_react2.default.createElement("ul",{className:"dropdown-menu",role:"menu"},_react2.default.createElement("li",null,_react2.default.createElement("a",{href:"#",onClick:this.onNewClick},_react2.default.createElement("i",{className:"fa fa-fw fa-file"}),"New")),_react2.default.createElement("li",null,_react2.default.createElement("a",{href:"#",onClick:this.onOpenClick},_react2.default.createElement("i",{className:"fa fa-fw fa-folder-open"}),"Open..."),_react2.default.createElement("input",{ref:function(t){return e.fileInput=t},className:"hidden",type:"file",onChange:this.onOpenFile})),_react2.default.createElement("li",null,_react2.default.createElement("a",{href:"#",onClick:this.onSaveClick},_react2.default.createElement("i",{className:"fa fa-fw fa-floppy-o"}),"Save...")),_react2.default.createElement("li",{role:"presentation",className:"divider"}),_react2.default.createElement("li",null,_react2.default.createElement("a",{href:"http://mitm.it/",target:"_blank"},_react2.default.createElement("i",{className:"fa fa-fw fa-external-link"}),"Install Certificates..."))))}}]),t}(_react.Component);exports.default=(0,_reactRedux.connect)(null,{clearFlows:flowsActions.clear,loadFlows:flowsActions.upload,saveFlows:flowsActions.download})(FileMenu); +var Query = exports.Query = { + SEARCH: "s", + HIGHLIGHT: "h", + SHOW_EVENTLOG: "e" +}; -},{"../../ducks/flows":44,"classnames":"classnames","react":"react","react-redux":"react-redux"}],22:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r0&&t(l[0]);)l=l.substr(1);s={text:s,key:l[0]}}if(!s.text||!s.key||t(s.key))throw"invalid options";i.push(s)}return _react2.default.createElement("div",{tabIndex:"0",onKeyDown:r,className:"prompt-dialog"},_react2.default.createElement("div",{className:"prompt-content"},a||_react2.default.createElement("strong",null,"Select: "),i.map(function(e){function t(t){o(e.key),t.stopPropagation()}var r=e.text.indexOf(e.key);return _react2.default.createElement("span",{key:e.key,className:"option",onClick:t},r!==-1?e.text.substring(0,r):e.text+"(",_react2.default.createElement("strong",{className:"text-primary"},e.key),r!==-1?e.text.substring(r+1):")")})))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=Prompt;var _react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),_utils=require("../utils.js");Prompt.propTypes={options:_react.PropTypes.array.isRequired,done:_react.PropTypes.func.isRequired,prompt:_react.PropTypes.string}; +var _reduxThunk2 = _interopRequireDefault(_reduxThunk); -},{"../utils.js":54,"lodash":"lodash","react":"react","react-dom":"react-dom"}],30:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r0)o=n.getRangeAt(0);else if(document.caretPositionFromPoint&&e.clientX&&e.clientY){var s=document.caretPositionFromPoint(e.clientX,e.clientY);o=document.createRange(),o.setStart(s.offsetNode,s.offset)}else document.caretRangeFromPoint&&e.clientX&&e.clientY?o=document.caretRangeFromPoint(e.clientX,e.clientY):(o=document.createRange(),o.selectNodeContents(_reactDom2.default.findDOMNode(this)));this._ignore_events=!0,this.setState({editable:!0},function(){var e=_reactDom2.default.findDOMNode(t);e.blur(),e.focus(),t._ignore_events=!1})}}},{key:"onBlur",value:function(e){this._ignore_events||(window.getSelection().removeAllRanges(),this.setState({editable:!1}),this.props.onDone(this.props.nodeToContent(_reactDom2.default.findDOMNode(this))),this.props.onBlur(e))}},{key:"reset",value:function(){_reactDom2.default.findDOMNode(this).innerHTML=this.props.contentToHtml(this.props.content)}},{key:"onKeyDown",value:function(e){switch(e.stopPropagation(),e.keyCode){case _utils.Key.ESC:e.preventDefault(),this.reset(),this.stop();break;case _utils.Key.ENTER:this.props.submitOnEnter&&!e.shiftKey&&(e.preventDefault(),this.stop())}}},{key:"onInput",value:function(){this.props.onInput(this.props.nodeToContent(_reactDom2.default.findDOMNode(this)))}}]),t}(_react.Component);EditorBase.propTypes={content:_react.PropTypes.string.isRequired,onDone:_react.PropTypes.func.isRequired,contentToHtml:_react.PropTypes.func,nodeToContent:_react.PropTypes.func,onStop:_react.PropTypes.func,submitOnEnter:_react.PropTypes.bool,className:_react.PropTypes.string,tag:_react.PropTypes.string},EditorBase.defaultProps={contentToHtml:function(e){return _.escape(e)},nodeToContent:function(e){return e.textContent},submitOnEnter:!0,className:"",tag:"div",onStop:_.noop,onMouseDown:_.noop,onBlur:_.noop,onInput:_.noop},exports.default=EditorBase; +var _ProxyApp2 = _interopRequireDefault(_ProxyApp); -},{"../../utils.js":54,"react":"react","react-dom":"react-dom"}],33:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(e){for(var t=1;to?r?-1:1:n=a;o--)i[d[o].id]=o;return _extends({},e,{data:d,indexOf:i,byId:_extends({},e.byId,_defineProperty({},t.id,null))});case RECEIVE:return _extends({},e,{data:t.list,byId:_lodash2.default.fromPairs(t.list.map(function(e){return[e.id,e]})),indexOf:_lodash2.default.fromPairs(t.list.map(function(e,t){return[e.id,t]}))});default:return e}}function add(e){return{type:ADD,item:e}}function update(e){return{type:UPDATE,item:e}}function remove(e){return{type:REMOVE,id:e}}function receive(e){return{type:RECEIVE,list:e}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RECEIVE=exports.REMOVE=exports.UPDATE=exports.ADD=void 0;var _extends=Object.assign||function(e){for(var t=1;t=n;d--)a[o[d].id]=d;return{data:o,indexOf:a}}function sortedRemove(e,t){var r=e.indexOf[t],n=[].concat(_toConsumableArray(e.data)),o=_extends({},e.indexOf,_defineProperty({},t,null));n.splice(r,1);for(var a=n.length-1;a>=r;a--)o[n[a].id]=a;return{data:n,indexOf:o}}function sortedIndex(e,t,r){for(var n=0,o=e.length;n>>1;r(t,e[a])>=0?n=a+1:o=a}return n}function defaultFilter(){return!0}function defaultSort(e,t){return 0}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RECEIVE=exports.REMOVE=exports.UPDATE=exports.ADD=exports.UPDATE_SORT=exports.UPDATE_FILTER=void 0;var _extends=Object.assign||function(e){for(var t=1;tPt&&(Pt=Mt,Qt=[]),Qt.push(e))}function s(e,r,n,i){function s(e){var t=1;for(e.sort(function(e,t){return e.descriptiont.description?1:0});t1?u.slice(0,-1).join(", ")+" or "+u[e.length-1]:u[0],i=t?'"'+r(t)+'"':"end of input","Expected "+n+" but "+i+" found."}return null!==r&&s(r),new t(null!==e?e:u(r,n),r,n,i)}function u(){var e,t,r,n;return Vt++,e=Mt,t=a(),t!==P?(r=l(),r!==P?(n=a(),n!==P?(Nt=e,t=X(r),e=t):(Mt=e,e=P)):(Mt=e,e=P)):(Mt=e,e=P),Vt--,e===P&&(t=P,0===Vt&&i(W)),e}function c(){var t,r;return Vt++,Z.test(e.charAt(Mt))?(t=e.charAt(Mt),Mt++):(t=P,0===Vt&&i($)),Vt--,t===P&&(r=P,0===Vt&&i(Y)),t}function o(){var t,r;return Vt++,te.test(e.charAt(Mt))?(t=e.charAt(Mt),Mt++):(t=P,0===Vt&&i(re)),Vt--,t===P&&(r=P,0===Vt&&i(ee)),t}function a(){var e,t;for(Vt++,e=[],t=c();t!==P;)e.push(t),t=c();return Vt--,e===P&&(t=P,0===Vt&&i(ne)),e}function l(){var t,r,n,s,u,c;return t=Mt,r=p(),r!==P?(n=a(),n!==P?(124===e.charCodeAt(Mt)?(s=ie,Mt++):(s=P,0===Vt&&i(se)),s!==P?(u=a(),u!==P?(c=l(),c!==P?(Nt=t,r=ue(r,c),t=r):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=p()),t}function p(){var t,r,n,s,u,o;if(t=Mt,r=f(),r!==P?(n=a(),n!==P?(38===e.charCodeAt(Mt)?(s=ce,Mt++):(s=P,0===Vt&&i(oe)),s!==P?(u=a(),u!==P?(o=p(),o!==P?(Nt=t,r=ae(r,o),t=r):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P),t===P){if(t=Mt,r=f(),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=p(),s!==P?(Nt=t,r=ae(r,s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;t===P&&(t=f())}return t}function f(){var t,r,n,s;return t=Mt,33===e.charCodeAt(Mt)?(r=le,Mt++):(r=P,0===Vt&&i(pe)),r!==P?(n=a(),n!==P?(s=f(),s!==P?(Nt=t,r=fe(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=h()),t}function h(){var t,r,n,s,u,c;return t=Mt,40===e.charCodeAt(Mt)?(r=he,Mt++):(r=P,0===Vt&&i(de)),r!==P?(n=a(),n!==P?(s=l(),s!==P?(u=a(),u!==P?(41===e.charCodeAt(Mt)?(c=ve,Mt++):(c=P,0===Vt&&i(ye)),c!==P?(Nt=t,r=ge(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=d()),t}function d(){var e;return e=v(),e===P&&(e=g()),e}function v(){var t,r;return t=y(),t===P&&(t=Mt,e.substr(Mt,2)===Ae?(r=Ae,Mt+=2):(r=P,0===Vt&&i(xe)),r!==P&&(Nt=t,r=Re()),t=r,t===P&&(t=Mt,e.substr(Mt,2)===me?(r=me,Mt+=2):(r=P,0===Vt&&i(qe)),r!==P&&(Nt=t,r=Ce()),t=r,t===P&&(t=Mt,e.substr(Mt,2)===we?(r=we,Mt+=2):(r=P,0===Vt&&i(Ee)),r!==P&&(Nt=t,r=be()),t=r,t===P&&(t=Mt,e.substr(Mt,2)===Fe?(r=Fe,Mt+=2):(r=P,0===Vt&&i(Ue)),r!==P&&(Nt=t,r=je()),t=r)))),t}function y(){var t,r;return t=Mt,e.substr(Mt,4)===Te?(r=Te,Mt+=4):(r=P,0===Vt&&i(_e)),r!==P&&(Nt=t,r=Se()),t=r,t===P&&(t=Mt,e.substr(Mt,5)===ke?(r=ke,Mt+=5):(r=P,0===Vt&&i(Be)),r!==P&&(Nt=t,r=Ie()),t=r),t}function g(){var t,r,n,s;if(t=Mt,e.substr(Mt,2)===ze?(r=ze,Mt+=2):(r=P,0===Vt&&i(De)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=A(),s!==P?(Nt=t,r=Ge(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===He?(r=He,Mt+=2):(r=P,0===Vt&&i(Je)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=Ke(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===Le?(r=Le,Mt+=2):(r=P,0===Vt&&i(Me)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=Ne(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,3)===Oe?(r=Oe,Mt+=3):(r=P,0===Vt&&i(Pe)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=Qe(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,3)===Ve?(r=Ve,Mt+=3):(r=P,0===Vt&&i(We)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=Xe(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===Ye?(r=Ye,Mt+=2):(r=P,0===Vt&&i(Ze)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=$e(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===et?(r=et,Mt+=2):(r=P,0===Vt&&i(tt)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=rt(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,3)===nt?(r=nt,Mt+=3):(r=P,0===Vt&&i(it)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=st(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,3)===ut?(r=ut,Mt+=3):(r=P,0===Vt&&i(ct)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=ot(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===at?(r=at,Mt+=2):(r=P,0===Vt&&i(lt)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=pt(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;t===P&&(t=Mt,r=x(),r!==P&&(Nt=t,r=pt(r)),t=r)}}}}}}}}}return t}function A(){var t,r,n,s;if(Vt++,t=Mt,ht.test(e.charAt(Mt))?(r=e.charAt(Mt),Mt++):(r=P,0===Vt&&i(dt)),r===P&&(r=null),r!==P){if(n=[],vt.test(e.charAt(Mt))?(s=e.charAt(Mt),Mt++):(s=P,0===Vt&&i(yt)),s!==P)for(;s!==P;)n.push(s),vt.test(e.charAt(Mt))?(s=e.charAt(Mt),Mt++):(s=P,0===Vt&&i(yt));else n=P;n!==P?(ht.test(e.charAt(Mt))?(s=e.charAt(Mt),Mt++):(s=P,0===Vt&&i(dt)),s===P&&(s=null),s!==P?(Nt=t,r=gt(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;return Vt--,t===P&&(r=P,0===Vt&&i(ft)),t}function x(){var t,r,n,s;if(Vt++,t=Mt,34===e.charCodeAt(Mt)?(r=xt,Mt++):(r=P,0===Vt&&i(Rt)),r!==P){for(n=[],s=R();s!==P;)n.push(s),s=R();n!==P?(34===e.charCodeAt(Mt)?(s=xt,Mt++):(s=P,0===Vt&&i(Rt)),s!==P?(Nt=t,r=mt(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,39===e.charCodeAt(Mt)?(r=qt,Mt++):(r=P,0===Vt&&i(Ct)),r!==P){for(n=[],s=m();s!==P;)n.push(s),s=m();n!==P?(39===e.charCodeAt(Mt)?(s=qt,Mt++):(s=P,0===Vt&&i(Ct)),s!==P?(Nt=t,r=mt(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P)if(t=Mt,r=Mt,Vt++,n=o(),Vt--,n===P?r=void 0:(Mt=r,r=P),r!==P){if(n=[],s=q(),s!==P)for(;s!==P;)n.push(s),s=q();else n=P;n!==P?(Nt=t,r=mt(n),t=r):(Mt=t,t=P)}else Mt=t,t=P}return Vt--,t===P&&(r=P,0===Vt&&i(At)),t}function R(){var t,r,n;return t=Mt,r=Mt,Vt++,wt.test(e.charAt(Mt))?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(Et)),Vt--,n===P?r=void 0:(Mt=r,r=P),r!==P?(e.length>Mt?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(bt)),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=Mt,92===e.charCodeAt(Mt)?(r=Ut,Mt++):(r=P,0===Vt&&i(jt)),r!==P?(n=C(),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)),t}function m(){var t,r,n;return t=Mt,r=Mt,Vt++,Tt.test(e.charAt(Mt))?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(_t)),Vt--,n===P?r=void 0:(Mt=r,r=P),r!==P?(e.length>Mt?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(bt)),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=Mt,92===e.charCodeAt(Mt)?(r=Ut,Mt++):(r=P,0===Vt&&i(jt)),r!==P?(n=C(),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)),t}function q(){var t,r,n;return t=Mt,r=Mt,Vt++,n=c(),Vt--,n===P?r=void 0:(Mt=r,r=P),r!==P?(e.length>Mt?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(bt)),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P),t}function C(){var t,r;return St.test(e.charAt(Mt))?(t=e.charAt(Mt),Mt++):(t=P,0===Vt&&i(kt)),t===P&&(t=Mt,110===e.charCodeAt(Mt)?(r=Bt,Mt++):(r=P,0===Vt&&i(It)),r!==P&&(Nt=t,r=zt()),t=r,t===P&&(t=Mt,114===e.charCodeAt(Mt)?(r=Dt,Mt++):(r=P,0===Vt&&i(Gt)),r!==P&&(Nt=t,r=Ht()),t=r,t===P&&(t=Mt,116===e.charCodeAt(Mt)?(r=Jt,Mt++):(r=P,0===Vt&&i(Kt)),r!==P&&(Nt=t,r=Lt()),t=r))),t}function w(e,t){function r(){return e.apply(this,arguments)||t.apply(this,arguments)}return r.desc=e.desc+" or "+t.desc,r}function E(e,t){function r(){return e.apply(this,arguments)&&t.apply(this,arguments)}return r.desc=e.desc+" and "+t.desc,r}function b(e){function t(){return!e.apply(this,arguments)}return t.desc="not "+e.desc,t}function F(e){function t(){return e.apply(this,arguments)}return t.desc="("+e.desc+")",t}function U(e){return!0}function j(e){return!1}function T(e){if(e.response)for(var t=Wt.ResponseUtils.getContentType(e.response),r=Xt.length;r--;)if(Xt[r].test(t))return!0;return!1}function _(e){function t(t){return t.response&&t.response.status_code===e}return t.desc="resp. code is "+e,t}function S(e){function t(t){return t.request&&e.test(t.request.host)}return e=new RegExp(e,"i"),t.desc="domain matches "+e,t}function k(e){return!!e.error}function B(e){function t(t){return t.request&&Wt.RequestUtils.match_header(t.request,e)||t.response&&Wt.ResponseUtils.match_header(t.response,e)}return e=new RegExp(e,"i"),t.desc="header matches "+e,t}function I(e){function t(t){return t.request&&Wt.RequestUtils.match_header(t.request,e)}return e=new RegExp(e,"i"),t.desc="req. header matches "+e,t}function z(e){function t(t){return t.response&&Wt.ResponseUtils.match_header(t.response,e)}return e=new RegExp(e,"i"),t.desc="resp. header matches "+e,t}function D(e){function t(t){return t.request&&e.test(t.request.method)}return e=new RegExp(e,"i"),t.desc="method matches "+e,t}function G(e){return e.request&&!e.response}function H(e){return!!e.response}function J(e){function t(t){return t.request&&e.test(Wt.RequestUtils.getContentType(t.request))||t.response&&e.test(Wt.ResponseUtils.getContentType(t.response))}return e=new RegExp(e,"i"),t.desc="content type matches "+e,t}function K(e){function t(t){return t.request&&e.test(Wt.RequestUtils.getContentType(t.request))}return e=new RegExp(e,"i"),t.desc="req. content type matches "+e,t}function L(e){function t(t){return t.response&&e.test(Wt.ResponseUtils.getContentType(t.response))}return e=new RegExp(e,"i"),t.desc="resp. content type matches "+e,t}function M(e){function t(t){return t.request&&e.test(Wt.RequestUtils.pretty_url(t.request))}return e=new RegExp(e,"i"),t.desc="url matches "+e,t}var N,O=arguments.length>1?arguments[1]:{},P={},Q={start:u},V=u,W={type:"other",description:"filter expression"},X=function(e){return e},Y={type:"other",description:"whitespace"},Z=/^[ \t\n\r]/,$={type:"class",value:"[ \\t\\n\\r]",description:"[ \\t\\n\\r]"},ee={type:"other",description:"control character"},te=/^[|&!()~"]/,re={type:"class",value:'[|&!()~"]',description:'[|&!()~"]'},ne={type:"other",description:"optional whitespace"},ie="|",se={type:"literal",value:"|",description:'"|"'},ue=function(e,t){return w(e,t)},ce="&",oe={type:"literal",value:"&",description:'"&"'},ae=function(e,t){return E(e,t)},le="!",pe={type:"literal",value:"!",description:'"!"'},fe=function(e){return b(e)},he="(",de={type:"literal",value:"(",description:'"("'},ve=")",ye={type:"literal",value:")",description:'")"'},ge=function(e){return F(e)},Ae="~a",xe={type:"literal",value:"~a",description:'"~a"'},Re=function(){return T},me="~e",qe={type:"literal",value:"~e",description:'"~e"'},Ce=function(){return k},we="~q",Ee={type:"literal",value:"~q",description:'"~q"'},be=function(){return G},Fe="~s",Ue={type:"literal",value:"~s",description:'"~s"'},je=function(){return H},Te="true",_e={type:"literal",value:"true",description:'"true"'},Se=function(){return U},ke="false",Be={type:"literal",value:"false",description:'"false"'},Ie=function(){return j},ze="~c",De={type:"literal",value:"~c",description:'"~c"'},Ge=function(e){return _(e)},He="~d",Je={type:"literal",value:"~d",description:'"~d"'},Ke=function(e){return S(e)},Le="~h",Me={type:"literal",value:"~h",description:'"~h"'},Ne=function(e){return B(e)},Oe="~hq",Pe={type:"literal",value:"~hq",description:'"~hq"'},Qe=function(e){return I(e)},Ve="~hs",We={type:"literal",value:"~hs",description:'"~hs"'},Xe=function(e){return z(e)},Ye="~m",Ze={type:"literal",value:"~m",description:'"~m"'},$e=function(e){return D(e)},et="~t",tt={type:"literal",value:"~t",description:'"~t"'},rt=function(e){return J(e)},nt="~tq",it={type:"literal",value:"~tq",description:'"~tq"'},st=function(e){return K(e)},ut="~ts",ct={type:"literal",value:"~ts",description:'"~ts"'},ot=function(e){return L(e)},at="~u",lt={type:"literal",value:"~u",description:'"~u"'},pt=function(e){return M(e)},ft={type:"other",description:"integer"},ht=/^['"]/,dt={type:"class",value:"['\"]",description:"['\"]"},vt=/^[0-9]/,yt={type:"class",value:"[0-9]",description:"[0-9]"},gt=function(e){return parseInt(e.join(""),10)},At={type:"other",description:"string"},xt='"',Rt={type:"literal",value:'"',description:'"\\""'},mt=function(e){return e.join("")},qt="'",Ct={type:"literal",value:"'",description:'"\'"'},wt=/^["\\]/,Et={type:"class",value:'["\\\\]',description:'["\\\\]'},bt={type:"any",description:"any character"},Ft=function(e){return e},Ut="\\",jt={type:"literal",value:"\\",description:'"\\\\"'},Tt=/^['\\]/,_t={type:"class",value:"['\\\\]",description:"['\\\\]"},St=/^['"\\]/,kt={type:"class",value:"['\"\\\\]",description:"['\"\\\\]"},Bt="n",It={type:"literal",value:"n",description:'"n"'},zt=function(){return"\n"},Dt="r",Gt={type:"literal",value:"r",description:'"r"'},Ht=function(){return"\r"},Jt="t",Kt={type:"literal",value:"t",description:'"t"'},Lt=function(){return"\t"},Mt=0,Nt=0,Ot=[{line:1,column:1,seenCR:!1}],Pt=0,Qt=[],Vt=0;if("startRule"in O){if(!(O.startRule in Q))throw new Error("Can't start parsing from rule \""+O.startRule+'".');V=Q[O.startRule]}var Wt=require("../flow/utils.js");U.desc="true",j.desc="false";var Xt=[new RegExp("text/javascript"),new RegExp("application/x-javascript"),new RegExp("application/javascript"),new RegExp("text/css"),new RegExp("image/.*"),new RegExp("application/x-shockwave-flash")];if(T.desc="is asset",k.desc="has error",G.desc="has no response",H.desc="has response",N=V(),N!==P&&Mt===e.length)return N;throw N!==P&&Mte);r++);var o;return o=e%Math.pow(1024,r)===0?0:1,(e/Math.pow(1024,r)).toFixed(o)+t[r]},formatTimeDelta=exports.formatTimeDelta=function(e){for(var t=e,r=["ms","s","min","h"],o=[1e3,60,60],n=0;Math.abs(t)>=o[n]&&n + flow: _react2.default.PropTypes.object.isRequired, + message: _react2.default.PropTypes.object.isRequired +}; + +ContentView.isContentTooLarge = function (msg) { + return msg.contentLength > 1024 * 1024 * (ContentViews.ViewImage.matches(msg) ? 10 : 0.2); +}; + +function ContentView(props) { + var flow = props.flow; + var message = props.message; + var contentView = props.contentView; + var isDisplayLarge = props.isDisplayLarge; + var displayLarge = props.displayLarge; + var onContentChange = props.onContentChange; + var readonly = props.readonly; + + + if (message.contentLength === 0 && readonly) { + return _react2.default.createElement(MetaViews.ContentEmpty, props); + } + + if (message.contentLength === null && readonly) { + return _react2.default.createElement(MetaViews.ContentMissing, props); + } + + if (!isDisplayLarge && ContentView.isContentTooLarge(message)) { + return _react2.default.createElement(MetaViews.ContentTooLarge, _extends({}, props, { onClick: displayLarge })); + } + + var View = ContentViews[contentView] || ContentViews['ViewServer']; + return _react2.default.createElement( + 'div', + { className: 'contentview' }, + _react2.default.createElement(View, { flow: flow, message: message, contentView: contentView, readonly: readonly, onChange: onContentChange }), + _react2.default.createElement(_ShowFullContentButton2.default, null) + ); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + contentView: state.ui.flow.contentView, + isDisplayLarge: state.ui.flow.displayLarge + }; +}, { + displayLarge: _flow.displayLarge, + updateEdit: _flow.updateEdit +})(ContentView); + +},{"../ducks/ui/flow":54,"./ContentView/ContentViews":8,"./ContentView/MetaViews":10,"./ContentView/ShowFullContentButton":11,"react":"react","react-redux":"react-redux"}],5:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = CodeEditor; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactCodemirror = require('react-codemirror'); + +var _reactCodemirror2 = _interopRequireDefault(_reactCodemirror); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +CodeEditor.propTypes = { + content: _react.PropTypes.string.isRequired, + onChange: _react.PropTypes.func.isRequired +}; + +function CodeEditor(_ref) { + var content = _ref.content; + var onChange = _ref.onChange; + + + var options = { + lineNumbers: true + }; + return _react2.default.createElement( + 'div', + { className: 'codeeditor', onKeyDown: function onKeyDown(e) { + return e.stopPropagation(); + } }, + _react2.default.createElement(_reactCodemirror2.default, { value: content, onChange: onChange, options: options }) + ); +} + +},{"react":"react","react-codemirror":"react-codemirror","react-dom":"react-dom"}],6:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _utils = require('../../flow/utils.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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; } + +exports.default = function (View) { + var _class, _temp; + + return _temp = _class = function (_React$Component) { + _inherits(_class, _React$Component); + + function _class(props) { + _classCallCheck(this, _class); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(_class).call(this, props)); + + _this.state = { + content: undefined, + request: undefined + }; + return _this; + } + + _createClass(_class, [{ + key: 'componentWillMount', + value: function componentWillMount() { + this.updateContent(this.props); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + if (nextProps.message.content !== this.props.message.content || nextProps.message.contentHash !== this.props.message.contentHash || nextProps.contentView !== this.props.contentView) { + this.updateContent(nextProps); + } + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + if (this.state.request) { + this.state.request.abort(); + } + } + }, { + key: 'updateContent', + value: function updateContent(props) { + if (this.state.request) { + this.state.request.abort(); + } + // We have a few special cases where we do not need to make an HTTP request. + if (props.message.content !== undefined) { + return this.setState({ request: undefined, content: props.message.content }); + } + if (props.message.contentLength === 0 || props.message.contentLength === null) { + return this.setState({ request: undefined, content: "" }); + } + + var requestUrl = _utils.MessageUtils.getContentURL(props.flow, props.message, View.name == 'ViewServer' ? props.contentView : undefined); + + // We use XMLHttpRequest instead of fetch() because fetch() is not (yet) abortable. + var request = new XMLHttpRequest(); + request.addEventListener("load", this.requestComplete.bind(this, request)); + request.addEventListener("error", this.requestFailed.bind(this, request)); + request.open("GET", requestUrl); + request.send(); + this.setState({ request: request, content: undefined }); + } + }, { + key: 'requestComplete', + value: function requestComplete(request, e) { + if (request !== this.state.request) { + return; // Stale request + } + this.setState({ + content: request.responseText, + request: undefined + }); + } + }, { + key: 'requestFailed', + value: function requestFailed(request, e) { + if (request !== this.state.request) { + return; // Stale request + } + console.error(e); + // FIXME: Better error handling + this.setState({ + content: "Error getting content.", + request: undefined + }); + } + }, { + key: 'render', + value: function render() { + return this.state.content !== undefined ? _react2.default.createElement(View, _extends({ content: this.state.content }, this.props)) : _react2.default.createElement( + 'div', + { className: 'text-center' }, + _react2.default.createElement('i', { className: 'fa fa-spinner fa-spin' }) + ); + } + }]); + + return _class; + }(_react2.default.Component), _class.displayName = View.displayName || View.name, _class.matches = View.matches, _class.propTypes = _extends({}, View.propTypes, { + content: _react.PropTypes.string, // mark as non-required + flow: _react.PropTypes.object.isRequired, + message: _react.PropTypes.object.isRequired + }), _temp; +}; + +},{"../../flow/utils.js":62,"react":"react"}],7:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _ViewSelector = require('./ViewSelector'); + +var _ViewSelector2 = _interopRequireDefault(_ViewSelector); + +var _UploadContentButton = require('./UploadContentButton'); + +var _UploadContentButton2 = _interopRequireDefault(_UploadContentButton); + +var _DownloadContentButton = require('./DownloadContentButton'); + +var _DownloadContentButton2 = _interopRequireDefault(_DownloadContentButton); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +ContentViewOptions.propTypes = { + flow: _react2.default.PropTypes.object.isRequired, + message: _react2.default.PropTypes.object.isRequired +}; + +function ContentViewOptions(props) { + var flow = props.flow; + var message = props.message; + var uploadContent = props.uploadContent; + var readonly = props.readonly; + var contentViewDescription = props.contentViewDescription; + + return _react2.default.createElement( + 'div', + { className: 'view-options' }, + _react2.default.createElement(_ViewSelector2.default, { message: message }), + ' ', + _react2.default.createElement(_DownloadContentButton2.default, { flow: flow, message: message }), + ' ', + _react2.default.createElement(_UploadContentButton2.default, { uploadContent: uploadContent }), + ' ', + _react2.default.createElement( + 'span', + null, + contentViewDescription + ) + ); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + contentViewDescription: state.ui.flow.viewDescription + }; +})(ContentViewOptions); + +},{"./DownloadContentButton":9,"./UploadContentButton":12,"./ViewSelector":13,"react":"react","react-redux":"react-redux"}],8:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ViewImage = exports.ViewServer = exports.Edit = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _flow = require('../../ducks/ui/flow'); + +var _ContentLoader = require('./ContentLoader'); + +var _ContentLoader2 = _interopRequireDefault(_ContentLoader); + +var _utils = require('../../flow/utils'); + +var _CodeEditor = require('./CodeEditor'); + +var _CodeEditor2 = _interopRequireDefault(_CodeEditor); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 isImage = /^image\/(png|jpe?g|gif|vnc.microsoft.icon|x-icon)$/i; +ViewImage.matches = function (msg) { + return isImage.test(_utils.MessageUtils.getContentType(msg)); +}; +ViewImage.propTypes = { + flow: _react.PropTypes.object.isRequired, + message: _react.PropTypes.object.isRequired +}; +function ViewImage(_ref) { + var flow = _ref.flow; + var message = _ref.message; + + return _react2.default.createElement( + 'div', + { className: 'flowview-image' }, + _react2.default.createElement('img', { src: _utils.MessageUtils.getContentURL(flow, message), alt: 'preview', className: 'img-thumbnail' }) + ); +} + +Edit.propTypes = { + content: _react2.default.PropTypes.string.isRequired +}; + +function Edit(_ref2) { + var content = _ref2.content; + var onChange = _ref2.onChange; + + return _react2.default.createElement(_CodeEditor2.default, { content: content, onChange: onChange }); +} +exports.Edit = Edit = (0, _ContentLoader2.default)(Edit); + +var ViewServer = function (_Component) { + _inherits(ViewServer, _Component); + + function ViewServer() { + _classCallCheck(this, ViewServer); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(ViewServer).apply(this, arguments)); + } + + _createClass(ViewServer, [{ + key: 'componentWillMount', + value: function componentWillMount() { + this.setContentView(this.props); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + this.setContentView(nextProps); + } + }, { + key: 'setContentView', + value: function setContentView(props) { + try { + this.data = JSON.parse(props.content); + } catch (err) { + this.data = { lines: [], description: err.message }; + } + + props.setContentViewDescription(props.contentView != this.data.description ? this.data.description : ''); + + var isFullContentShown = this.data.lines.length < props.maxLines; + if (isFullContentShown) props.setShowFullContent(true); + } + }, { + key: 'render', + value: function render() { + var _props = this.props; + var content = _props.content; + var contentView = _props.contentView; + var message = _props.message; + var maxLines = _props.maxLines; + + var lines = this.props.showFullContent ? this.data.lines : this.data.lines.slice(0, maxLines); + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'pre', + null, + lines.map(function (line, i) { + return _react2.default.createElement( + 'div', + { key: 'line' + i }, + line.map(function (tuple, j) { + return _react2.default.createElement( + 'span', + { key: 'tuple' + j, className: tuple[0] }, + tuple[1] + ); + }) + ); + }) + ), + ViewImage.matches(message) && _react2.default.createElement(ViewImage, this.props) + ); + } + }]); + + return ViewServer; +}(_react.Component); + +ViewServer.defaultProps = { + maxLines: 80 +}; + + +exports.ViewServer = ViewServer = (0, _reactRedux.connect)(function (state) { + return { + showFullContent: state.ui.flow.showFullContent + }; +}, { + setContentViewDescription: _flow.setContentViewDescription, + setShowFullContent: _flow.setShowFullContent +})((0, _ContentLoader2.default)(ViewServer)); + +exports.Edit = Edit; +exports.ViewServer = ViewServer; +exports.ViewImage = ViewImage; + +},{"../../ducks/ui/flow":54,"../../flow/utils":62,"./CodeEditor":5,"./ContentLoader":6,"react":"react","react-redux":"react-redux"}],9:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = DownloadContentButton; + +var _utils = require("../../flow/utils"); + +var _react = require("react"); + +DownloadContentButton.propTypes = { + flow: _react.PropTypes.object.isRequired, + message: _react.PropTypes.object.isRequired +}; + +function DownloadContentButton(_ref) { + var flow = _ref.flow; + var message = _ref.message; + + + return React.createElement( + "a", + { className: "btn btn-default btn-xs", + href: _utils.MessageUtils.getContentURL(flow, message), + title: "Download the content of the flow." }, + React.createElement("i", { className: "fa fa-download" }) + ); +} + +},{"../../flow/utils":62,"react":"react"}],10:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.ContentEmpty = ContentEmpty; +exports.ContentMissing = ContentMissing; +exports.ContentTooLarge = ContentTooLarge; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _utils = require('../../utils.js'); + +var _UploadContentButton = require('./UploadContentButton'); + +var _UploadContentButton2 = _interopRequireDefault(_UploadContentButton); + +var _DownloadContentButton = require('./DownloadContentButton'); + +var _DownloadContentButton2 = _interopRequireDefault(_DownloadContentButton); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function ContentEmpty(_ref) { + var flow = _ref.flow; + var message = _ref.message; + + return _react2.default.createElement( + 'div', + { className: 'alert alert-info' }, + 'No ', + flow.request === message ? 'request' : 'response', + ' content.' + ); +} + +function ContentMissing(_ref2) { + var flow = _ref2.flow; + var message = _ref2.message; + + return _react2.default.createElement( + 'div', + { className: 'alert alert-info' }, + flow.request === message ? 'Request' : 'Response', + ' content missing.' + ); +} + +function ContentTooLarge(_ref3) { + var message = _ref3.message; + var onClick = _ref3.onClick; + var uploadContent = _ref3.uploadContent; + var flow = _ref3.flow; + + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'div', + { className: 'alert alert-warning' }, + _react2.default.createElement( + 'button', + { onClick: onClick, className: 'btn btn-xs btn-warning pull-right' }, + 'Display anyway' + ), + (0, _utils.formatSize)(message.contentLength), + ' content size.' + ), + _react2.default.createElement( + 'div', + { className: 'view-options text-center' }, + _react2.default.createElement(_UploadContentButton2.default, { uploadContent: uploadContent }), + ' ', + _react2.default.createElement(_DownloadContentButton2.default, { flow: flow, message: message }) + ) + ); +} + +},{"../../utils.js":63,"./DownloadContentButton":9,"./UploadContentButton":12,"react":"react"}],11:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _reactDom = require('react-dom'); + +var _Button = require('../common/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _flow = require('../../ducks/ui/flow'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +ShowFullContentButton.propTypes = { + setShowFullContent: _react.PropTypes.func.isRequired, + showFullContent: _react.PropTypes.bool.isRequired +}; + +function ShowFullContentButton(_ref) { + var setShowFullContent = _ref.setShowFullContent; + var showFullContent = _ref.showFullContent; + + + return !showFullContent && _react2.default.createElement(_Button2.default, { className: 'view-all-content-btn btn-xs', onClick: function onClick() { + return setShowFullContent(true); + }, text: 'Show full content' }); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + showFullContent: state.ui.flow.showFullContent + }; +}, { + setShowFullContent: _flow.setShowFullContent +})(ShowFullContentButton); + +},{"../../ducks/ui/flow":54,"../common/Button":40,"react":"react","react-dom":"react-dom","react-redux":"react-redux"}],12:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = UploadContentButton; + +var _react = require("react"); + +UploadContentButton.propTypes = { + uploadContent: _react.PropTypes.func.isRequired +}; + +function UploadContentButton(_ref) { + var uploadContent = _ref.uploadContent; + + + var fileInput = void 0; + + return React.createElement( + "a", + { className: "btn btn-default btn-xs", + onClick: function onClick() { + return fileInput.click(); + }, + title: "Upload a file to replace the content." }, + React.createElement("i", { className: "fa fa-upload" }), + React.createElement("input", { + ref: function ref(_ref2) { + return fileInput = _ref2; + }, + className: "hidden", + type: "file", + onChange: function onChange(e) { + if (e.target.files.length > 0) uploadContent(e.target.files[0]); + } + }) + ); +} + +},{"react":"react"}],13:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _reactRedux = require('react-redux'); + +var _ContentViews = require('./ContentViews'); + +var ContentViews = _interopRequireWildcard(_ContentViews); + +var _flow = require('../../ducks/ui/flow'); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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; } + +function ViewItem(_ref) { + var name = _ref.name; + var setContentView = _ref.setContentView; + var children = _ref.children; + + return _react2.default.createElement( + 'li', + null, + _react2.default.createElement( + 'a', + { href: '#', onClick: function onClick() { + return setContentView(name); + } }, + children + ) + ); +} + +/*ViewSelector.propTypes = { + contentViews: PropTypes.array.isRequired, + activeView: PropTypes.string.isRequired, + isEdit: PropTypes.bool.isRequired, + isContentViewSelectorOpen: PropTypes.bool.isRequired, + setContentViewSelectorOpen: PropTypes.func.isRequired +}*/ + +var ViewSelector = function (_Component) { + _inherits(ViewSelector, _Component); + + function ViewSelector(props, context) { + _classCallCheck(this, ViewSelector); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ViewSelector).call(this, props, context)); + + _this.close = _this.close.bind(_this); + _this.state = { open: false }; + return _this; + } + + _createClass(ViewSelector, [{ + key: 'close', + value: function close() { + this.setState({ open: false }); + document.removeEventListener('click', this.close); + } + }, { + key: 'onDropdown', + value: function onDropdown(e) { + e.preventDefault(); + this.setState({ open: !this.state.open }); + document.addEventListener('click', this.close); + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var _props = this.props; + var contentViews = _props.contentViews; + var activeView = _props.activeView; + var isEdit = _props.isEdit; + var setContentView = _props.setContentView; + + var edit = ContentViews.Edit.displayName; + + return _react2.default.createElement( + 'div', + { className: (0, _classnames2.default)('dropup pull-left', { open: this.state.open }) }, + _react2.default.createElement( + 'a', + { className: 'btn btn-default btn-xs', + onClick: function onClick(e) { + return _this2.onDropdown(e); + }, + href: '#' }, + _react2.default.createElement( + 'b', + null, + 'View:' + ), + ' ', + activeView, + _react2.default.createElement('span', { className: 'caret' }) + ), + _react2.default.createElement( + 'ul', + { className: 'dropdown-menu', role: 'menu' }, + contentViews.map(function (name) { + return _react2.default.createElement( + ViewItem, + { key: name, setContentView: setContentView, name: name }, + name.toLowerCase().replace('_', ' ') + ); + }), + isEdit && _react2.default.createElement( + ViewItem, + { key: edit, setContentView: setContentView, name: edit }, + edit.toLowerCase() + ) + ) + ); + } + }]); + + return ViewSelector; +}(_react.Component); + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + contentViews: state.settings.contentViews, + activeView: state.ui.flow.contentView, + isEdit: !!state.ui.flow.modifiedFlow + }; +}, { + setContentView: _flow.setContentView +})(ViewSelector); + +},{"../../ducks/ui/flow":54,"./ContentViews":8,"classnames":"classnames","react":"react","react-redux":"react-redux"}],14:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _eventLog = require('../ducks/eventLog'); + +var _ToggleButton = require('./common/ToggleButton'); + +var _ToggleButton2 = _interopRequireDefault(_ToggleButton); + +var _EventList = require('./EventLog/EventList'); + +var _EventList2 = _interopRequireDefault(_EventList); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 EventLog = function (_Component) { + _inherits(EventLog, _Component); + + function EventLog(props, context) { + _classCallCheck(this, EventLog); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(EventLog).call(this, props, context)); + + _this.state = { height: _this.props.defaultHeight }; + + _this.onDragStart = _this.onDragStart.bind(_this); + _this.onDragMove = _this.onDragMove.bind(_this); + _this.onDragStop = _this.onDragStop.bind(_this); + return _this; + } + + _createClass(EventLog, [{ + key: 'onDragStart', + value: function onDragStart(event) { + event.preventDefault(); + this.dragStart = this.state.height + event.pageY; + window.addEventListener('mousemove', this.onDragMove); + window.addEventListener('mouseup', this.onDragStop); + window.addEventListener('dragend', this.onDragStop); + } + }, { + key: 'onDragMove', + value: function onDragMove(event) { + event.preventDefault(); + this.setState({ height: this.dragStart - event.pageY }); + } + }, { + key: 'onDragStop', + value: function onDragStop(event) { + event.preventDefault(); + window.removeEventListener('mousemove', this.onDragMove); + } + }, { + key: 'render', + value: function render() { + var height = this.state.height; + var _props = this.props; + var filters = _props.filters; + var events = _props.events; + var toggleFilter = _props.toggleFilter; + var close = _props.close; + + + return _react2.default.createElement( + 'div', + { className: 'eventlog', style: { height: height } }, + _react2.default.createElement( + 'div', + { onMouseDown: this.onDragStart }, + 'Eventlog', + _react2.default.createElement( + 'div', + { className: 'pull-right' }, + ['debug', 'info', 'web'].map(function (type) { + return _react2.default.createElement(_ToggleButton2.default, { key: type, text: type, checked: filters[type], onToggle: function onToggle() { + return toggleFilter(type); + } }); + }), + _react2.default.createElement('i', { onClick: close, className: 'fa fa-close' }) + ) + ), + _react2.default.createElement(_EventList2.default, { events: events }) + ); + } + }]); + + return EventLog; +}(_react.Component); + +EventLog.propTypes = { + filters: _react.PropTypes.object.isRequired, + events: _react.PropTypes.array.isRequired, + toggleFilter: _react.PropTypes.func.isRequired, + close: _react.PropTypes.func.isRequired, + defaultHeight: _react.PropTypes.number +}; +EventLog.defaultProps = { + defaultHeight: 200 +}; +exports.default = (0, _reactRedux.connect)(function (state) { + return { + filters: state.eventLog.filters, + events: state.eventLog.view.data + }; +}, { + close: _eventLog.toggleVisibility, + toggleFilter: _eventLog.toggleFilter +})(EventLog); + +},{"../ducks/eventLog":48,"./EventLog/EventList":15,"./common/ToggleButton":42,"react":"react","react-redux":"react-redux"}],15:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _shallowequal = require('shallowequal'); + +var _shallowequal2 = _interopRequireDefault(_shallowequal); + +var _AutoScroll = require('../helpers/AutoScroll'); + +var _AutoScroll2 = _interopRequireDefault(_AutoScroll); + +var _VirtualScroll = require('../helpers/VirtualScroll'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 EventLogList = function (_Component) { + _inherits(EventLogList, _Component); + + function EventLogList(props) { + _classCallCheck(this, EventLogList); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(EventLogList).call(this, props)); + + _this.heights = {}; + _this.state = { vScroll: (0, _VirtualScroll.calcVScroll)() }; + + _this.onViewportUpdate = _this.onViewportUpdate.bind(_this); + return _this; + } + + _createClass(EventLogList, [{ + key: 'componentDidMount', + value: function componentDidMount() { + window.addEventListener('resize', this.onViewportUpdate); + this.onViewportUpdate(); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + window.removeEventListener('resize', this.onViewportUpdate); + } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate() { + this.onViewportUpdate(); + } + }, { + key: 'onViewportUpdate', + value: function onViewportUpdate() { + var _this2 = this; + + var viewport = _reactDom2.default.findDOMNode(this); + + var vScroll = (0, _VirtualScroll.calcVScroll)({ + itemCount: this.props.events.length, + rowHeight: this.props.rowHeight, + viewportTop: viewport.scrollTop, + viewportHeight: viewport.offsetHeight, + itemHeights: this.props.events.map(function (entry) { + return _this2.heights[entry.id]; + }) + }); + + if (!(0, _shallowequal2.default)(this.state.vScroll, vScroll)) { + this.setState({ vScroll: vScroll }); + } + } + }, { + key: 'setHeight', + value: function setHeight(id, node) { + if (node && !this.heights[id]) { + var height = node.offsetHeight; + if (this.heights[id] !== height) { + this.heights[id] = height; + this.onViewportUpdate(); + } + } + } + }, { + key: 'render', + value: function render() { + var _this3 = this; + + var vScroll = this.state.vScroll; + var events = this.props.events; + + + return _react2.default.createElement( + 'pre', + { onScroll: this.onViewportUpdate }, + _react2.default.createElement('div', { style: { height: vScroll.paddingTop } }), + events.slice(vScroll.start, vScroll.end).map(function (event) { + return _react2.default.createElement( + 'div', + { key: event.id, ref: function ref(node) { + return _this3.setHeight(event.id, node); + } }, + _react2.default.createElement(LogIcon, { event: event }), + event.message + ); + }), + _react2.default.createElement('div', { style: { height: vScroll.paddingBottom } }) + ); + } + }]); + + return EventLogList; +}(_react.Component); + +EventLogList.propTypes = { + events: _react.PropTypes.array.isRequired, + rowHeight: _react.PropTypes.number +}; +EventLogList.defaultProps = { + rowHeight: 18 +}; + + +function LogIcon(_ref) { + var event = _ref.event; + + var icon = { web: 'html5', debug: 'bug' }[event.level] || 'info'; + return _react2.default.createElement('i', { className: 'fa fa-fw fa-' + icon }); +} + +exports.default = (0, _AutoScroll2.default)(EventLogList); + +},{"../helpers/AutoScroll":44,"../helpers/VirtualScroll":45,"react":"react","react-dom":"react-dom","shallowequal":"shallowequal"}],16:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _shallowequal = require('shallowequal'); + +var _shallowequal2 = _interopRequireDefault(_shallowequal); + +var _AutoScroll = require('./helpers/AutoScroll'); + +var _AutoScroll2 = _interopRequireDefault(_AutoScroll); + +var _VirtualScroll = require('./helpers/VirtualScroll'); + +var _FlowTableHead = require('./FlowTable/FlowTableHead'); + +var _FlowTableHead2 = _interopRequireDefault(_FlowTableHead); + +var _FlowRow = require('./FlowTable/FlowRow'); + +var _FlowRow2 = _interopRequireDefault(_FlowRow); + +var _filt = require('../filt/filt'); + +var _filt2 = _interopRequireDefault(_filt); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 FlowTable = function (_React$Component) { + _inherits(FlowTable, _React$Component); + + function FlowTable(props, context) { + _classCallCheck(this, FlowTable); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(FlowTable).call(this, props, context)); + + _this.state = { vScroll: (0, _VirtualScroll.calcVScroll)() }; + _this.onViewportUpdate = _this.onViewportUpdate.bind(_this); + return _this; + } + + _createClass(FlowTable, [{ + key: 'componentWillMount', + value: function componentWillMount() { + window.addEventListener('resize', this.onViewportUpdate); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + window.removeEventListener('resize', this.onViewportUpdate); + } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate() { + this.onViewportUpdate(); + + if (!this.shouldScrollIntoView) { + return; + } + + this.shouldScrollIntoView = false; + + var _props = this.props; + var rowHeight = _props.rowHeight; + var flows = _props.flows; + var selected = _props.selected; + + var viewport = _reactDom2.default.findDOMNode(this); + var head = _reactDom2.default.findDOMNode(this.refs.head); + + var headHeight = head ? head.offsetHeight : 0; + + var rowTop = flows.indexOf(selected) * rowHeight + headHeight; + var rowBottom = rowTop + rowHeight; + + var viewportTop = viewport.scrollTop; + var viewportHeight = viewport.offsetHeight; + + // Account for pinned thead + if (rowTop - headHeight < viewportTop) { + viewport.scrollTop = rowTop - headHeight; + } else if (rowBottom > viewportTop + viewportHeight) { + viewport.scrollTop = rowBottom - viewportHeight; + } + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + if (nextProps.selected && nextProps.selected !== this.props.selected) { + this.shouldScrollIntoView = true; + } + } + }, { + key: 'onViewportUpdate', + value: function onViewportUpdate() { + var viewport = _reactDom2.default.findDOMNode(this); + var viewportTop = viewport.scrollTop; + + var vScroll = (0, _VirtualScroll.calcVScroll)({ + viewportTop: viewportTop, + viewportHeight: viewport.offsetHeight, + itemCount: this.props.flows.length, + rowHeight: this.props.rowHeight + }); + + if (this.state.viewportTop !== viewportTop || !(0, _shallowequal2.default)(this.state.vScroll, vScroll)) { + this.setState({ vScroll: vScroll, viewportTop: viewportTop }); + } + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var _state = this.state; + var vScroll = _state.vScroll; + var viewportTop = _state.viewportTop; + var _props2 = this.props; + var flows = _props2.flows; + var selected = _props2.selected; + var highlight = _props2.highlight; + + var isHighlighted = highlight ? _filt2.default.parse(highlight) : function () { + return false; + }; + + return _react2.default.createElement( + 'div', + { className: 'flow-table', onScroll: this.onViewportUpdate }, + _react2.default.createElement( + 'table', + null, + _react2.default.createElement( + 'thead', + { ref: 'head', style: { transform: 'translateY(' + viewportTop + 'px)' } }, + _react2.default.createElement(_FlowTableHead2.default, null) + ), + _react2.default.createElement( + 'tbody', + null, + _react2.default.createElement('tr', { style: { height: vScroll.paddingTop } }), + flows.slice(vScroll.start, vScroll.end).map(function (flow) { + return _react2.default.createElement(_FlowRow2.default, { + key: flow.id, + flow: flow, + selected: flow === selected, + highlighted: isHighlighted(flow), + onSelect: _this2.props.onSelect + }); + }), + _react2.default.createElement('tr', { style: { height: vScroll.paddingBottom } }) + ) + ) + ); + } + }]); + + return FlowTable; +}(_react2.default.Component); + +FlowTable.propTypes = { + onSelect: _react.PropTypes.func.isRequired, + flows: _react.PropTypes.array.isRequired, + rowHeight: _react.PropTypes.number, + highlight: _react.PropTypes.string, + selected: _react.PropTypes.object +}; +FlowTable.defaultProps = { + rowHeight: 32 +}; +exports.default = (0, _AutoScroll2.default)(FlowTable); + +},{"../filt/filt":61,"./FlowTable/FlowRow":18,"./FlowTable/FlowTableHead":19,"./helpers/AutoScroll":44,"./helpers/VirtualScroll":45,"react":"react","react-dom":"react-dom","shallowequal":"shallowequal"}],17:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.TLSColumn = TLSColumn; +exports.IconColumn = IconColumn; +exports.PathColumn = PathColumn; +exports.MethodColumn = MethodColumn; +exports.StatusColumn = StatusColumn; +exports.SizeColumn = SizeColumn; +exports.TimeColumn = TimeColumn; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _utils = require('../../flow/utils.js'); + +var _utils2 = require('../../utils.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function TLSColumn(_ref) { + var flow = _ref.flow; + + return _react2.default.createElement('td', { className: (0, _classnames2.default)('col-tls', flow.request.scheme === 'https' ? 'col-tls-https' : 'col-tls-http') }); +} + +TLSColumn.headerClass = 'col-tls'; +TLSColumn.headerName = ''; + +function IconColumn(_ref2) { + var flow = _ref2.flow; + + return _react2.default.createElement( + 'td', + { className: 'col-icon' }, + _react2.default.createElement('div', { className: (0, _classnames2.default)('resource-icon', IconColumn.getIcon(flow)) }) + ); +} + +IconColumn.headerClass = 'col-icon'; +IconColumn.headerName = ''; + +IconColumn.getIcon = function (flow) { + if (!flow.response) { + return 'resource-icon-plain'; + } + + var contentType = _utils.ResponseUtils.getContentType(flow.response) || ''; + + // @todo We should assign a type to the flow somewhere else. + if (flow.response.status_code === 304) { + return 'resource-icon-not-modified'; + } + if (300 <= flow.response.status_code && flow.response.status_code < 400) { + return 'resource-icon-redirect'; + } + if (contentType.indexOf('image') >= 0) { + return 'resource-icon-image'; + } + if (contentType.indexOf('javascript') >= 0) { + return 'resource-icon-js'; + } + if (contentType.indexOf('css') >= 0) { + return 'resource-icon-css'; + } + if (contentType.indexOf('html') >= 0) { + return 'resource-icon-document'; + } + + return 'resource-icon-plain'; +}; + +function PathColumn(_ref3) { + var flow = _ref3.flow; + + return _react2.default.createElement( + 'td', + { className: 'col-path' }, + flow.request.is_replay && _react2.default.createElement('i', { className: 'fa fa-fw fa-repeat pull-right' }), + flow.intercepted && _react2.default.createElement('i', { className: 'fa fa-fw fa-pause pull-right' }), + _utils.RequestUtils.pretty_url(flow.request) + ); +} + +PathColumn.headerClass = 'col-path'; +PathColumn.headerName = 'Path'; + +function MethodColumn(_ref4) { + var flow = _ref4.flow; + + return _react2.default.createElement( + 'td', + { className: 'col-method' }, + flow.request.method + ); +} + +MethodColumn.headerClass = 'col-method'; +MethodColumn.headerName = 'Method'; + +function StatusColumn(_ref5) { + var flow = _ref5.flow; + + return _react2.default.createElement( + 'td', + { className: 'col-status' }, + flow.response && flow.response.status_code + ); +} + +StatusColumn.headerClass = 'col-status'; +StatusColumn.headerName = 'Status'; + +function SizeColumn(_ref6) { + var flow = _ref6.flow; + + return _react2.default.createElement( + 'td', + { className: 'col-size' }, + (0, _utils2.formatSize)(SizeColumn.getTotalSize(flow)) + ); +} + +SizeColumn.getTotalSize = function (flow) { + var total = flow.request.contentLength; + if (flow.response) { + total += flow.response.contentLength || 0; + } + return total; +}; + +SizeColumn.headerClass = 'col-size'; +SizeColumn.headerName = 'Size'; + +function TimeColumn(_ref7) { + var flow = _ref7.flow; + + return _react2.default.createElement( + 'td', + { className: 'col-time' }, + flow.response ? (0, _utils2.formatTimeDelta)(1000 * (flow.response.timestamp_end - flow.request.timestamp_start)) : '...' + ); +} + +TimeColumn.headerClass = 'col-time'; +TimeColumn.headerName = 'Time'; + +exports.default = [TLSColumn, IconColumn, PathColumn, MethodColumn, StatusColumn, SizeColumn, TimeColumn]; + +},{"../../flow/utils.js":62,"../../utils.js":63,"classnames":"classnames","react":"react"}],18:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _FlowColumns = require('./FlowColumns'); + +var _FlowColumns2 = _interopRequireDefault(_FlowColumns); + +var _utils = require('../../utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +FlowRow.propTypes = { + onSelect: _react.PropTypes.func.isRequired, + flow: _react.PropTypes.object.isRequired, + highlighted: _react.PropTypes.bool, + selected: _react.PropTypes.bool +}; + +function FlowRow(_ref) { + var flow = _ref.flow; + var selected = _ref.selected; + var highlighted = _ref.highlighted; + var onSelect = _ref.onSelect; + + var className = (0, _classnames2.default)({ + 'selected': selected, + 'highlighted': highlighted, + 'intercepted': flow.intercepted, + 'has-request': flow.request, + 'has-response': flow.response + }); + + return _react2.default.createElement( + 'tr', + { className: className, onClick: function onClick() { + return onSelect(flow.id); + } }, + _FlowColumns2.default.map(function (Column) { + return _react2.default.createElement(Column, { key: Column.name, flow: flow }); + }) + ); +} + +exports.default = (0, _utils.pure)(FlowRow); + +},{"../../utils":63,"./FlowColumns":17,"classnames":"classnames","react":"react"}],19:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _FlowColumns = require('./FlowColumns'); + +var _FlowColumns2 = _interopRequireDefault(_FlowColumns); + +var _flowView = require('../../ducks/flowView'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +FlowTableHead.propTypes = { + updateSort: _react.PropTypes.func.isRequired, + sortDesc: _react2.default.PropTypes.bool.isRequired, + sortColumn: _react2.default.PropTypes.string +}; + +function FlowTableHead(_ref) { + var sortColumn = _ref.sortColumn; + var sortDesc = _ref.sortDesc; + var updateSort = _ref.updateSort; + + var sortType = sortDesc ? 'sort-desc' : 'sort-asc'; + + return _react2.default.createElement( + 'tr', + null, + _FlowColumns2.default.map(function (Column) { + return _react2.default.createElement( + 'th', + { className: (0, _classnames2.default)(Column.headerClass, sortColumn === Column.name && sortType), + key: Column.name, + onClick: function onClick() { + return updateSort(Column.name, Column.name !== sortColumn ? false : !sortDesc); + } }, + Column.headerName + ); + }) + ); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + sortDesc: state.flowView.sort.desc, + sortColumn: state.flowView.sort.column + }; +}, { + updateSort: _flowView.updateSort +})(FlowTableHead); + +},{"../../ducks/flowView":49,"./FlowColumns":17,"classnames":"classnames","react":"react","react-redux":"react-redux"}],20:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _Nav = require('./FlowView/Nav'); + +var _Nav2 = _interopRequireDefault(_Nav); + +var _Messages = require('./FlowView/Messages'); + +var _Details = require('./FlowView/Details'); + +var _Details2 = _interopRequireDefault(_Details); + +var _Prompt = require('./Prompt'); + +var _Prompt2 = _interopRequireDefault(_Prompt); + +var _flow = require('../ducks/ui/flow'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 FlowView = function (_Component) { + _inherits(FlowView, _Component); + + function FlowView(props, context) { + _classCallCheck(this, FlowView); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(FlowView).call(this, props, context)); + + _this.onPromptFinish = _this.onPromptFinish.bind(_this); + return _this; + } + + _createClass(FlowView, [{ + key: 'onPromptFinish', + value: function onPromptFinish(edit) { + this.props.setPrompt(false); + if (edit && this.tabComponent) { + this.tabComponent.edit(edit); + } + } + }, { + key: 'getPromptOptions', + value: function getPromptOptions() { + switch (this.props.tab) { + + case 'request': + return ['method', 'url', { text: 'http version', key: 'v' }, 'header']; + break; + + case 'response': + return [{ text: 'http version', key: 'v' }, 'code', 'message', 'header']; + break; + + case 'details': + return; + + default: + throw 'Unknown tab for edit: ' + this.props.tab; + } + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var _props = this.props; + var flow = _props.flow; + var active = _props.tab; + var updateFlow = _props.updateFlow; + + var tabs = ['request', 'response', 'error'].filter(function (k) { + return flow[k]; + }).concat(['details']); + + if (tabs.indexOf(active) < 0) { + if (active === 'response' && flow.error) { + active = 'error'; + } else if (active === 'error' && flow.response) { + active = 'response'; + } else { + active = tabs[0]; + } + } + + var Tab = FlowView.allTabs[_lodash2.default.capitalize(active)]; + + return _react2.default.createElement( + 'div', + { className: 'flow-detail' }, + _react2.default.createElement(_Nav2.default, { + flow: flow, + tabs: tabs, + active: active, + onSelectTab: this.props.selectTab + }), + _react2.default.createElement(Tab, { ref: function ref(tab) { + return _this2.tabComponent = tab; + }, flow: flow, updateFlow: updateFlow }), + this.props.promptOpen && _react2.default.createElement(_Prompt2.default, { options: this.getPromptOptions(), done: this.onPromptFinish }) + ); + } + }]); + + return FlowView; +}(_react.Component); + +FlowView.allTabs = { Request: _Messages.Request, Response: _Messages.Response, Error: _Messages.ErrorView, Details: _Details2.default }; +exports.default = FlowView; +exports.default = (0, _reactRedux.connect)(function (state) { + return { + promptOpen: state.ui.promptOpen, + tab: state.ui.flow.tab + }; +}, { + selectTab: _flow.selectTab +})(FlowView); + +},{"../ducks/ui/flow":54,"./FlowView/Details":21,"./FlowView/Messages":23,"./FlowView/Nav":24,"./Prompt":36,"lodash":"lodash","react":"react","react-redux":"react-redux"}],21:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +exports.TimeStamp = TimeStamp; +exports.ConnectionInfo = ConnectionInfo; +exports.CertificateInfo = CertificateInfo; +exports.Timing = Timing; +exports.default = Details; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _utils = require('../../utils.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function TimeStamp(_ref) { + var t = _ref.t; + var deltaTo = _ref.deltaTo; + var title = _ref.title; + + return t ? _react2.default.createElement( + 'tr', + null, + _react2.default.createElement( + 'td', + null, + title, + ':' + ), + _react2.default.createElement( + 'td', + null, + (0, _utils.formatTimeStamp)(t), + deltaTo && _react2.default.createElement( + 'span', + { className: 'text-muted' }, + '(', + (0, _utils.formatTimeDelta)(1000 * (t - deltaTo)), + ')' + ) + ) + ) : _react2.default.createElement('tr', null); +} + +function ConnectionInfo(_ref2) { + var conn = _ref2.conn; + + return _react2.default.createElement( + 'table', + { className: 'connection-table' }, + _react2.default.createElement( + 'tbody', + null, + _react2.default.createElement( + 'tr', + { key: 'address' }, + _react2.default.createElement( + 'td', + null, + 'Address:' + ), + _react2.default.createElement( + 'td', + null, + conn.address.address.join(':') + ) + ), + conn.sni && _react2.default.createElement( + 'tr', + { key: 'sni' }, + _react2.default.createElement( + 'td', + null, + _react2.default.createElement( + 'abbr', + { title: 'TLS Server Name Indication' }, + 'TLS SNI:' + ) + ), + _react2.default.createElement( + 'td', + null, + conn.sni + ) + ) + ) + ); +} + +function CertificateInfo(_ref3) { + var flow = _ref3.flow; + + // @todo We should fetch human-readable certificate representation from the server + return _react2.default.createElement( + 'div', + null, + flow.client_conn.cert && [_react2.default.createElement( + 'h4', + { key: 'name' }, + 'Client Certificate' + ), _react2.default.createElement( + 'pre', + { key: 'value', style: { maxHeight: 100 } }, + flow.client_conn.cert + )], + flow.server_conn.cert && [_react2.default.createElement( + 'h4', + { key: 'name' }, + 'Server Certificate' + ), _react2.default.createElement( + 'pre', + { key: 'value', style: { maxHeight: 100 } }, + flow.server_conn.cert + )] + ); +} + +function Timing(_ref4) { + var flow = _ref4.flow; + var sc = flow.server_conn; + var cc = flow.client_conn; + var req = flow.request; + var res = flow.response; + + + var timestamps = [{ + title: "Server conn. initiated", + t: sc.timestamp_start, + deltaTo: req.timestamp_start + }, { + title: "Server conn. TCP handshake", + t: sc.timestamp_tcp_setup, + deltaTo: req.timestamp_start + }, { + title: "Server conn. SSL handshake", + t: sc.timestamp_ssl_setup, + deltaTo: req.timestamp_start + }, { + title: "Client conn. established", + t: cc.timestamp_start, + deltaTo: req.timestamp_start + }, { + title: "Client conn. SSL handshake", + t: cc.timestamp_ssl_setup, + deltaTo: req.timestamp_start + }, { + title: "First request byte", + t: req.timestamp_start + }, { + title: "Request complete", + t: req.timestamp_end, + deltaTo: req.timestamp_start + }, res && { + title: "First response byte", + t: res.timestamp_start, + deltaTo: req.timestamp_start + }, res && { + title: "Response complete", + t: res.timestamp_end, + deltaTo: req.timestamp_start + }]; + + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'h4', + null, + 'Timing' + ), + _react2.default.createElement( + 'table', + { className: 'timing-table' }, + _react2.default.createElement( + 'tbody', + null, + timestamps.filter(function (v) { + return v; + }).sort(function (a, b) { + return a.t - b.t; + }).map(function (item) { + return _react2.default.createElement(TimeStamp, _extends({ key: item.title }, item)); + }) + ) + ) + ); +} + +function Details(_ref5) { + var flow = _ref5.flow; + + return _react2.default.createElement( + 'section', + null, + _react2.default.createElement( + 'h4', + null, + 'Client Connection' + ), + _react2.default.createElement(ConnectionInfo, { conn: flow.client_conn }), + _react2.default.createElement( + 'h4', + null, + 'Server Connection' + ), + _react2.default.createElement(ConnectionInfo, { conn: flow.server_conn }), + _react2.default.createElement(CertificateInfo, { flow: flow }), + _react2.default.createElement(Timing, { flow: flow }) + ); +} + +},{"../../utils.js":63,"lodash":"lodash","react":"react"}],22:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _ValueEditor = require('../ValueEditor/ValueEditor'); + +var _ValueEditor2 = _interopRequireDefault(_ValueEditor); + +var _utils = require('../../utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +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 HeaderEditor = function (_Component) { + _inherits(HeaderEditor, _Component); + + function HeaderEditor(props) { + _classCallCheck(this, HeaderEditor); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(HeaderEditor).call(this, props)); + + _this.onKeyDown = _this.onKeyDown.bind(_this); + return _this; + } + + _createClass(HeaderEditor, [{ + key: 'render', + value: function render() { + var _props = this.props; + var onTab = _props.onTab; + + var props = _objectWithoutProperties(_props, ['onTab']); + + return _react2.default.createElement(_ValueEditor2.default, _extends({}, props, { + onKeyDown: this.onKeyDown + })); + } + }, { + key: 'focus', + value: function focus() { + _reactDom2.default.findDOMNode(this).focus(); + } + }, { + key: 'onKeyDown', + value: function onKeyDown(e) { + switch (e.keyCode) { + case _utils.Key.BACKSPACE: + var s = window.getSelection().getRangeAt(0); + if (s.startOffset === 0 && s.endOffset === 0) { + this.props.onRemove(e); + } + break; + case _utils.Key.ENTER: + case _utils.Key.TAB: + if (!e.shiftKey) { + this.props.onTab(e); + } + break; + } + } + }]); + + return HeaderEditor; +}(_react.Component); + +var Headers = function (_Component2) { + _inherits(Headers, _Component2); + + function Headers() { + _classCallCheck(this, Headers); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(Headers).apply(this, arguments)); + } + + _createClass(Headers, [{ + key: 'onChange', + value: function onChange(row, col, val) { + var nextHeaders = _.cloneDeep(this.props.message.headers); + + nextHeaders[row][col] = val; + + if (!nextHeaders[row][0] && !nextHeaders[row][1]) { + // do not delete last row + if (nextHeaders.length === 1) { + nextHeaders[0][0] = 'Name'; + nextHeaders[0][1] = 'Value'; + } else { + nextHeaders.splice(row, 1); + // manually move selection target if this has been the last row. + if (row === nextHeaders.length) { + this._nextSel = row - 1 + '-value'; + } + } + } + + this.props.onChange(nextHeaders); + } + }, { + key: 'edit', + value: function edit() { + this.refs['0-key'].focus(); + } + }, { + key: 'onTab', + value: function onTab(row, col, e) { + var headers = this.props.message.headers; + + if (col === 0) { + this._nextSel = row + '-value'; + return; + } + if (row !== headers.length - 1) { + this._nextSel = row + 1 + '-key'; + return; + } + + e.preventDefault(); + + var nextHeaders = _.cloneDeep(this.props.message.headers); + nextHeaders.push(['Name', 'Value']); + this.props.onChange(nextHeaders); + this._nextSel = row + 1 + '-key'; + } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate() { + if (this._nextSel && this.refs[this._nextSel]) { + this.refs[this._nextSel].focus(); + this._nextSel = undefined; + } + } + }, { + key: 'onRemove', + value: function onRemove(row, col, e) { + if (col === 1) { + e.preventDefault(); + this.refs[row + '-key'].focus(); + } else if (row > 0) { + e.preventDefault(); + this.refs[row - 1 + '-value'].focus(); + } + } + }, { + key: 'render', + value: function render() { + var _this3 = this; + + var _props2 = this.props; + var message = _props2.message; + var readonly = _props2.readonly; + + + return _react2.default.createElement( + 'table', + { className: 'header-table' }, + _react2.default.createElement( + 'tbody', + null, + message.headers.map(function (header, i) { + return _react2.default.createElement( + 'tr', + { key: i }, + _react2.default.createElement( + 'td', + { className: 'header-name' }, + _react2.default.createElement(HeaderEditor, { + ref: i + '-key', + content: header[0], + readonly: readonly, + onDone: function onDone(val) { + return _this3.onChange(i, 0, val); + }, + onRemove: function onRemove(event) { + return _this3.onRemove(i, 0, event); + }, + onTab: function onTab(event) { + return _this3.onTab(i, 0, event); + } + }), + _react2.default.createElement( + 'span', + { className: 'header-colon' }, + ':' + ) + ), + _react2.default.createElement( + 'td', + { className: 'header-value' }, + _react2.default.createElement(HeaderEditor, { + ref: i + '-value', + content: header[1], + readonly: readonly, + onDone: function onDone(val) { + return _this3.onChange(i, 1, val); + }, + onRemove: function onRemove(event) { + return _this3.onRemove(i, 1, event); + }, + onTab: function onTab(event) { + return _this3.onTab(i, 1, event); + } + }) + ) + ); + }) + ) + ); + } + }]); + + return Headers; +}(_react.Component); + +Headers.propTypes = { + onChange: _react.PropTypes.func.isRequired, + message: _react.PropTypes.object.isRequired +}; +exports.default = Headers; + +},{"../../utils":63,"../ValueEditor/ValueEditor":39,"react":"react","react-dom":"react-dom"}],23:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.Response = exports.Request = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +exports.ErrorView = ErrorView; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _utils = require('../../flow/utils.js'); + +var _utils2 = require('../../utils.js'); + +var _ContentView = require('../ContentView'); + +var _ContentView2 = _interopRequireDefault(_ContentView); + +var _ContentViewOptions = require('../ContentView/ContentViewOptions'); + +var _ContentViewOptions2 = _interopRequireDefault(_ContentViewOptions); + +var _ValidateEditor = require('../ValueEditor/ValidateEditor'); + +var _ValidateEditor2 = _interopRequireDefault(_ValidateEditor); + +var _ValueEditor = require('../ValueEditor/ValueEditor'); + +var _ValueEditor2 = _interopRequireDefault(_ValueEditor); + +var _Headers = require('./Headers'); + +var _Headers2 = _interopRequireDefault(_Headers); + +var _flow = require('../../ducks/ui/flow'); + +var _flows = require('../../ducks/flows'); + +var FlowActions = _interopRequireWildcard(_flows); + +var _ToggleEdit = require('./ToggleEdit'); + +var _ToggleEdit2 = _interopRequireDefault(_ToggleEdit); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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; } + +function RequestLine(_ref) { + var flow = _ref.flow; + var readonly = _ref.readonly; + var updateFlow = _ref.updateFlow; + + return _react2.default.createElement( + 'div', + { className: 'first-line request-line' }, + _react2.default.createElement( + 'div', + null, + _react2.default.createElement(_ValueEditor2.default, { + content: flow.request.method, + readonly: readonly, + onDone: function onDone(method) { + return updateFlow({ request: { method: method } }); + } + }), + ' ', + _react2.default.createElement(_ValidateEditor2.default, { + content: _utils.RequestUtils.pretty_url(flow.request), + readonly: readonly, + onDone: function onDone(url) { + return updateFlow({ request: _extends({ path: '' }, (0, _utils.parseUrl)(url)) }); + }, + isValid: function isValid(url) { + return !!(0, _utils.parseUrl)(url).host; + } + }), + ' ', + _react2.default.createElement(_ValidateEditor2.default, { + content: flow.request.http_version, + readonly: readonly, + onDone: function onDone(http_version) { + return updateFlow({ request: { http_version: http_version } }); + }, + isValid: _utils.isValidHttpVersion + }) + ) + ); +} + +function ResponseLine(_ref2) { + var flow = _ref2.flow; + var readonly = _ref2.readonly; + var updateFlow = _ref2.updateFlow; + + return _react2.default.createElement( + 'div', + { className: 'first-line response-line' }, + _react2.default.createElement(_ValidateEditor2.default, { + content: flow.response.http_version, + readonly: readonly, + onDone: function onDone(nextVer) { + return updateFlow({ response: { http_version: nextVer } }); + }, + isValid: _utils.isValidHttpVersion + }), + ' ', + _react2.default.createElement(_ValidateEditor2.default, { + content: flow.response.status_code + '', + readonly: readonly, + onDone: function onDone(code) { + return updateFlow({ response: { code: parseInt(code) } }); + }, + isValid: function isValid(code) { + return (/^\d+$/.test(code) + ); + } + }), + ' ', + _react2.default.createElement(_ValueEditor2.default, { + content: flow.response.reason, + readonly: readonly, + onDone: function onDone(msg) { + return updateFlow({ response: { msg: msg } }); + } + }) + ); +} + +var Message = (0, _reactRedux.connect)(function (state) { + return { + flow: state.ui.flow.modifiedFlow || state.flows.byId[state.flows.selected[0]], + isEdit: !!state.ui.flow.modifiedFlow + }; +}, { + updateFlow: _flow.updateEdit, + uploadContent: FlowActions.uploadContent +}); + +var Request = exports.Request = function (_Component) { + _inherits(Request, _Component); + + function Request() { + _classCallCheck(this, Request); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(Request).apply(this, arguments)); + } + + _createClass(Request, [{ + key: 'render', + value: function render() { + var _props = this.props; + var flow = _props.flow; + var isEdit = _props.isEdit; + var updateFlow = _props.updateFlow; + var _uploadContent = _props.uploadContent; + + var noContent = !isEdit && (flow.request.contentLength == 0 || flow.request.contentLength == null); + return _react2.default.createElement( + 'section', + { className: 'request' }, + _react2.default.createElement( + 'article', + null, + _react2.default.createElement(_ToggleEdit2.default, null), + _react2.default.createElement(RequestLine, { + flow: flow, + readonly: !isEdit, + updateFlow: updateFlow }), + _react2.default.createElement(_Headers2.default, { + message: flow.request, + readonly: !isEdit, + onChange: function onChange(headers) { + return updateFlow({ request: { headers: headers } }); + } + }), + _react2.default.createElement('hr', null), + _react2.default.createElement(_ContentView2.default, { + readonly: !isEdit, + flow: flow, + onContentChange: function onContentChange(content) { + return updateFlow({ request: { content: content } }); + }, + message: flow.request }) + ), + !noContent && _react2.default.createElement( + 'footer', + null, + _react2.default.createElement(_ContentViewOptions2.default, { + flow: flow, + readonly: !isEdit, + message: flow.request, + uploadContent: function uploadContent(content) { + return _uploadContent(flow, content, "request"); + } }) + ) + ); + } + }, { + key: 'edit', + value: function edit(k) { + throw "unimplemented"; + /* + switch (k) { + case 'm': + this.refs.requestLine.refs.method.focus() + break + case 'u': + this.refs.requestLine.refs.url.focus() + break + case 'v': + this.refs.requestLine.refs.httpVersion.focus() + break + case 'h': + this.refs.headers.edit() + break + default: + throw new Error(`Unimplemented: ${k}`) + } + */ + } + }]); + + return Request; +}(_react.Component); + +exports.Request = Request = Message(Request); + +var Response = exports.Response = function (_Component2) { + _inherits(Response, _Component2); + + function Response() { + _classCallCheck(this, Response); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(Response).apply(this, arguments)); + } + + _createClass(Response, [{ + key: 'render', + value: function render() { + var _props2 = this.props; + var flow = _props2.flow; + var isEdit = _props2.isEdit; + var updateFlow = _props2.updateFlow; + var _uploadContent2 = _props2.uploadContent; + + var noContent = !isEdit && (flow.response.contentLength == 0 || flow.response.contentLength == null); + + return _react2.default.createElement( + 'section', + { className: 'response' }, + _react2.default.createElement( + 'article', + null, + _react2.default.createElement(_ToggleEdit2.default, null), + _react2.default.createElement(ResponseLine, { + flow: flow, + readonly: !isEdit, + updateFlow: updateFlow }), + _react2.default.createElement(_Headers2.default, { + message: flow.response, + readonly: !isEdit, + onChange: function onChange(headers) { + return updateFlow({ response: { headers: headers } }); + } + }), + _react2.default.createElement('hr', null), + _react2.default.createElement(_ContentView2.default, { + readonly: !isEdit, + flow: flow, + onContentChange: function onContentChange(content) { + return updateFlow({ response: { content: content } }); + }, + message: flow.response + }) + ), + !noContent && _react2.default.createElement( + 'footer', + null, + _react2.default.createElement(_ContentViewOptions2.default, { + flow: flow, + message: flow.response, + uploadContent: function uploadContent(content) { + return _uploadContent2(flow, content, "response"); + }, + readonly: !isEdit }) + ) + ); + } + }, { + key: 'edit', + value: function edit(k) { + throw "unimplemented"; + /* + switch (k) { + case 'c': + this.refs.responseLine.refs.status_code.focus() + break + case 'm': + this.refs.responseLine.refs.msg.focus() + break + case 'v': + this.refs.responseLine.refs.httpVersion.focus() + break + case 'h': + this.refs.headers.edit() + break + default: + throw new Error(`'Unimplemented: ${k}`) + } + */ + } + }]); + + return Response; +}(_react.Component); + +exports.Response = Response = Message(Response); + +ErrorView.propTypes = { + flow: _react.PropTypes.object.isRequired +}; + +function ErrorView(_ref3) { + var flow = _ref3.flow; + + return _react2.default.createElement( + 'section', + null, + _react2.default.createElement( + 'div', + { className: 'alert alert-warning' }, + flow.error.msg, + _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'small', + null, + (0, _utils2.formatTimeStamp)(flow.error.timestamp) + ) + ) + ) + ); +} + +},{"../../ducks/flows":50,"../../ducks/ui/flow":54,"../../flow/utils.js":62,"../../utils.js":63,"../ContentView":4,"../ContentView/ContentViewOptions":7,"../ValueEditor/ValidateEditor":38,"../ValueEditor/ValueEditor":39,"./Headers":22,"./ToggleEdit":25,"react":"react","react-redux":"react-redux"}],24:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = Nav; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +NavAction.propTypes = { + icon: _react.PropTypes.string.isRequired, + title: _react.PropTypes.string.isRequired, + onClick: _react.PropTypes.func.isRequired +}; + +function NavAction(_ref) { + var icon = _ref.icon; + var title = _ref.title; + var _onClick = _ref.onClick; + + return _react2.default.createElement( + 'a', + { title: title, + href: '#', + className: 'nav-action', + onClick: function onClick(event) { + event.preventDefault(); + _onClick(event); + } }, + _react2.default.createElement('i', { className: 'fa fa-fw ' + icon }) + ); +} + +Nav.propTypes = { + active: _react.PropTypes.string.isRequired, + tabs: _react.PropTypes.array.isRequired, + onSelectTab: _react.PropTypes.func.isRequired +}; + +function Nav(_ref2) { + var active = _ref2.active; + var tabs = _ref2.tabs; + var onSelectTab = _ref2.onSelectTab; + + return _react2.default.createElement( + 'nav', + { className: 'nav-tabs nav-tabs-sm' }, + tabs.map(function (tab) { + return _react2.default.createElement( + 'a', + { key: tab, + href: '#', + className: (0, _classnames2.default)({ active: active === tab }), + onClick: function onClick(event) { + event.preventDefault(); + onSelectTab(tab); + } }, + _.capitalize(tab) + ); + }) + ); +} + +},{"classnames":"classnames","react":"react","react-redux":"react-redux"}],25:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _flow = require('../../ducks/ui/flow'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +ToggleEdit.propTypes = { + isEdit: _react.PropTypes.bool.isRequired, + flow: _react.PropTypes.object.isRequired, + startEdit: _react.PropTypes.func.isRequired, + stopEdit: _react.PropTypes.func.isRequired +}; + +function ToggleEdit(_ref) { + var isEdit = _ref.isEdit; + var startEdit = _ref.startEdit; + var stopEdit = _ref.stopEdit; + var flow = _ref.flow; + var modifiedFlow = _ref.modifiedFlow; + + return _react2.default.createElement( + 'div', + { className: 'edit-flow-container' }, + isEdit ? _react2.default.createElement( + 'a', + { className: 'edit-flow', onClick: function onClick() { + return stopEdit(flow, modifiedFlow); + } }, + _react2.default.createElement('i', { className: 'fa fa-check' }) + ) : _react2.default.createElement( + 'a', + { className: 'edit-flow', onClick: function onClick() { + return startEdit(flow); + } }, + _react2.default.createElement('i', { className: 'fa fa-pencil' }) + ) + ); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + isEdit: !!state.ui.flow.modifiedFlow, + modifiedFlow: state.ui.flow.modifiedFlow || state.flows.byId[state.flows.selected[0]], + flow: state.flows.byId[state.flows.selected[0]] + }; +}, { + startEdit: _flow.startEdit, + stopEdit: _flow.stopEdit +})(ToggleEdit); + +},{"../../ducks/ui/flow":54,"react":"react","react-redux":"react-redux"}],26:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _utils = require('../utils.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +Footer.propTypes = { + settings: _react2.default.PropTypes.object.isRequired +}; + +function Footer(_ref) { + var settings = _ref.settings; + + return _react2.default.createElement( + 'footer', + null, + settings.mode && settings.mode != "regular" && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + settings.mode, + ' mode' + ), + settings.intercept && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'Intercept: ', + settings.intercept + ), + settings.showhost && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'showhost' + ), + settings.no_upstream_cert && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'no-upstream-cert' + ), + settings.rawtcp && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'raw-tcp' + ), + !settings.http2 && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'no-http2' + ), + settings.anticache && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'anticache' + ), + settings.anticomp && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'anticomp' + ), + settings.stickyauth && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'stickyauth: ', + settings.stickyauth + ), + settings.stickycookie && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'stickycookie: ', + settings.stickycookie + ), + settings.stream && _react2.default.createElement( + 'span', + { className: 'label label-success' }, + 'stream: ', + (0, _utils.formatSize)(settings.stream) + ) + ); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + settings: state.settings + }; +})(Footer); + +},{"../utils.js":63,"react":"react","react-redux":"react-redux"}],27:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _MainMenu = require('./Header/MainMenu'); + +var _MainMenu2 = _interopRequireDefault(_MainMenu); + +var _ViewMenu = require('./Header/ViewMenu'); + +var _ViewMenu2 = _interopRequireDefault(_ViewMenu); + +var _OptionMenu = require('./Header/OptionMenu'); + +var _OptionMenu2 = _interopRequireDefault(_OptionMenu); + +var _FileMenu = require('./Header/FileMenu'); + +var _FileMenu2 = _interopRequireDefault(_FileMenu); + +var _FlowMenu = require('./Header/FlowMenu'); + +var _FlowMenu2 = _interopRequireDefault(_FlowMenu); + +var _header = require('../ducks/ui/header'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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); } } + +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 Header = function (_Component) { + _inherits(Header, _Component); + + function Header() { + _classCallCheck(this, Header); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(Header).apply(this, arguments)); + } + + _createClass(Header, [{ + key: 'handleClick', + value: function handleClick(active, e) { + e.preventDefault(); + this.props.setActiveMenu(active.title); + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var _props = this.props; + var selectedFlowId = _props.selectedFlowId; + var activeMenu = _props.activeMenu; + + + var entries = [].concat(_toConsumableArray(Header.entries)); + if (selectedFlowId) entries.push(_FlowMenu2.default); + + var Active = _.find(entries, function (e) { + return e.title == activeMenu; + }); + + return _react2.default.createElement( + 'header', + null, + _react2.default.createElement( + 'nav', + { className: 'nav-tabs nav-tabs-lg' }, + _react2.default.createElement(_FileMenu2.default, null), + entries.map(function (Entry) { + return _react2.default.createElement( + 'a', + { key: Entry.title, + href: '#', + className: (0, _classnames2.default)({ active: Entry === Active }), + onClick: function onClick(e) { + return _this2.handleClick(Entry, e); + } }, + Entry.title + ); + }) + ), + _react2.default.createElement( + 'div', + { className: 'menu' }, + _react2.default.createElement(Active, null) + ) + ); + } + }]); + + return Header; +}(_react.Component); + +Header.entries = [_MainMenu2.default, _ViewMenu2.default, _OptionMenu2.default]; +exports.default = (0, _reactRedux.connect)(function (state) { + return { + selectedFlowId: state.flows.selected[0], + activeMenu: state.ui.header.activeMenu + }; +}, { + setActiveMenu: _header.setActiveMenu +})(Header); + +},{"../ducks/ui/header":55,"./Header/FileMenu":28,"./Header/FlowMenu":31,"./Header/MainMenu":32,"./Header/OptionMenu":33,"./Header/ViewMenu":34,"classnames":"classnames","react":"react","react-redux":"react-redux"}],28:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _flows = require('../../ducks/flows'); + +var flowsActions = _interopRequireWildcard(_flows); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 FileMenu = function (_Component) { + _inherits(FileMenu, _Component); + + function FileMenu(props, context) { + _classCallCheck(this, FileMenu); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(FileMenu).call(this, props, context)); + + _this.state = { show: false }; + + _this.close = _this.close.bind(_this); + _this.onFileClick = _this.onFileClick.bind(_this); + _this.onNewClick = _this.onNewClick.bind(_this); + _this.onOpenClick = _this.onOpenClick.bind(_this); + _this.onOpenFile = _this.onOpenFile.bind(_this); + _this.onSaveClick = _this.onSaveClick.bind(_this); + return _this; + } + + _createClass(FileMenu, [{ + key: 'close', + value: function close() { + this.setState({ show: false }); + document.removeEventListener('click', this.close); + } + }, { + key: 'onFileClick', + value: function onFileClick(e) { + e.preventDefault(); + + if (this.state.show) { + return; + } + + document.addEventListener('click', this.close); + this.setState({ show: true }); + } + }, { + key: 'onNewClick', + value: function onNewClick(e) { + e.preventDefault(); + if (confirm('Delete all flows?')) { + this.props.clearFlows(); + } + } + }, { + key: 'onOpenClick', + value: function onOpenClick(e) { + e.preventDefault(); + this.fileInput.click(); + } + }, { + key: 'onOpenFile', + value: function onOpenFile(e) { + e.preventDefault(); + if (e.target.files.length > 0) { + this.props.loadFlows(e.target.files[0]); + this.fileInput.value = ''; + } + } + }, { + key: 'onSaveClick', + value: function onSaveClick(e) { + e.preventDefault(); + this.props.saveFlows(); + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + return _react2.default.createElement( + 'div', + { className: (0, _classnames2.default)('dropdown pull-left', { open: this.state.show }) }, + _react2.default.createElement( + 'a', + { href: '#', className: 'special', onClick: this.onFileClick }, + 'mitmproxy' + ), + _react2.default.createElement( + 'ul', + { className: 'dropdown-menu', role: 'menu' }, + _react2.default.createElement( + 'li', + null, + _react2.default.createElement( + 'a', + { href: '#', onClick: this.onNewClick }, + _react2.default.createElement('i', { className: 'fa fa-fw fa-file' }), + 'New' + ) + ), + _react2.default.createElement( + 'li', + null, + _react2.default.createElement( + 'a', + { href: '#', onClick: this.onOpenClick }, + _react2.default.createElement('i', { className: 'fa fa-fw fa-folder-open' }), + 'Open...' + ), + _react2.default.createElement('input', { + ref: function ref(_ref) { + return _this2.fileInput = _ref; + }, + className: 'hidden', + type: 'file', + onChange: this.onOpenFile + }) + ), + _react2.default.createElement( + 'li', + null, + _react2.default.createElement( + 'a', + { href: '#', onClick: this.onSaveClick }, + _react2.default.createElement('i', { className: 'fa fa-fw fa-floppy-o' }), + 'Save...' + ) + ), + _react2.default.createElement('li', { role: 'presentation', className: 'divider' }), + _react2.default.createElement( + 'li', + null, + _react2.default.createElement( + 'a', + { href: 'http://mitm.it/', target: '_blank' }, + _react2.default.createElement('i', { className: 'fa fa-fw fa-external-link' }), + 'Install Certificates...' + ) + ) + ) + ); + } + }]); + + return FileMenu; +}(_react.Component); + +exports.default = (0, _reactRedux.connect)(null, { + clearFlows: flowsActions.clear, + loadFlows: flowsActions.upload, + saveFlows: flowsActions.download +})(FileMenu); + +},{"../../ducks/flows":50,"classnames":"classnames","react":"react","react-redux":"react-redux"}],29:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _utils = require('../../utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 FilterDocs = function (_Component) { + _inherits(FilterDocs, _Component); + + // @todo move to redux + + function FilterDocs(props, context) { + _classCallCheck(this, FilterDocs); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(FilterDocs).call(this, props, context)); + + _this.state = { doc: FilterDocs.doc }; + return _this; + } + + _createClass(FilterDocs, [{ + key: 'componentWillMount', + value: function componentWillMount() { + var _this2 = this; + + if (!FilterDocs.xhr) { + FilterDocs.xhr = (0, _utils.fetchApi)('/filter-help').then(function (response) { + return response.json(); + }); + FilterDocs.xhr.catch(function () { + FilterDocs.xhr = null; + }); + } + if (!this.state.doc) { + FilterDocs.xhr.then(function (doc) { + FilterDocs.doc = doc; + _this2.setState({ doc: doc }); + }); + } + } + }, { + key: 'render', + value: function render() { + var doc = this.state.doc; + + return !doc ? _react2.default.createElement('i', { className: 'fa fa-spinner fa-spin' }) : _react2.default.createElement( + 'table', + { className: 'table table-condensed' }, + _react2.default.createElement( + 'tbody', + null, + doc.commands.map(function (cmd) { + return _react2.default.createElement( + 'tr', + { key: cmd[1] }, + _react2.default.createElement( + 'td', + null, + cmd[0].replace(' ', ' ') + ), + _react2.default.createElement( + 'td', + null, + cmd[1] + ) + ); + }), + _react2.default.createElement( + 'tr', + { key: 'docs-link' }, + _react2.default.createElement( + 'td', + { colSpan: '2' }, + _react2.default.createElement( + 'a', + { href: 'http://docs.mitmproxy.org/en/stable/features/filters.html', + target: '_blank' }, + _react2.default.createElement('i', { className: 'fa fa-external-link' }), + '  mitmproxy docs' + ) + ) + ) + ) + ); + } + }]); + + return FilterDocs; +}(_react.Component); + +FilterDocs.xhr = null; +FilterDocs.doc = null; +exports.default = FilterDocs; + +},{"../../utils":63,"react":"react"}],30:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _utils = require('../../utils.js'); + +var _filt = require('../../filt/filt'); + +var _filt2 = _interopRequireDefault(_filt); + +var _FilterDocs = require('./FilterDocs'); + +var _FilterDocs2 = _interopRequireDefault(_FilterDocs); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 FilterInput = function (_Component) { + _inherits(FilterInput, _Component); + + function FilterInput(props, context) { + _classCallCheck(this, FilterInput); + + // Consider both focus and mouseover for showing/hiding the tooltip, + // because onBlur of the input is triggered before the click on the tooltip + // finalized, hiding the tooltip just as the user clicks on it. + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(FilterInput).call(this, props, context)); + + _this.state = { value: _this.props.value, focus: false, mousefocus: false }; + + _this.onChange = _this.onChange.bind(_this); + _this.onFocus = _this.onFocus.bind(_this); + _this.onBlur = _this.onBlur.bind(_this); + _this.onKeyDown = _this.onKeyDown.bind(_this); + _this.onMouseEnter = _this.onMouseEnter.bind(_this); + _this.onMouseLeave = _this.onMouseLeave.bind(_this); + return _this; + } + + _createClass(FilterInput, [{ + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + this.setState({ value: nextProps.value }); + } + }, { + key: 'isValid', + value: function isValid(filt) { + try { + var str = filt == null ? this.state.value : filt; + if (str) { + _filt2.default.parse(str); + } + return true; + } catch (e) { + return false; + } + } + }, { + key: 'getDesc', + value: function getDesc() { + if (!this.state.value) { + return _react2.default.createElement(_FilterDocs2.default, null); + } + try { + return _filt2.default.parse(this.state.value).desc; + } catch (e) { + return '' + e; + } + } + }, { + key: 'onChange', + value: function onChange(e) { + var value = e.target.value; + this.setState({ value: value }); + + // Only propagate valid filters upwards. + if (this.isValid(value)) { + this.props.onChange(value); + } + } + }, { + key: 'onFocus', + value: function onFocus() { + this.setState({ focus: true }); + } + }, { + key: 'onBlur', + value: function onBlur() { + this.setState({ focus: false }); + } + }, { + key: 'onMouseEnter', + value: function onMouseEnter() { + this.setState({ mousefocus: true }); + } + }, { + key: 'onMouseLeave', + value: function onMouseLeave() { + this.setState({ mousefocus: false }); + } + }, { + key: 'onKeyDown', + value: function onKeyDown(e) { + if (e.keyCode === _utils.Key.ESC || e.keyCode === _utils.Key.ENTER) { + this.blur(); + // If closed using ESC/ENTER, hide the tooltip. + this.setState({ mousefocus: false }); + } + e.stopPropagation(); + } + }, { + key: 'blur', + value: function blur() { + _reactDom2.default.findDOMNode(this.refs.input).blur(); + } + }, { + key: 'select', + value: function select() { + _reactDom2.default.findDOMNode(this.refs.input).select(); + } + }, { + key: 'render', + value: function render() { + var _props = this.props; + var type = _props.type; + var color = _props.color; + var placeholder = _props.placeholder; + var _state = this.state; + var value = _state.value; + var focus = _state.focus; + var mousefocus = _state.mousefocus; + + return _react2.default.createElement( + 'div', + { className: (0, _classnames2.default)('filter-input input-group', { 'has-error': !this.isValid() }) }, + _react2.default.createElement( + 'span', + { className: 'input-group-addon' }, + _react2.default.createElement('i', { className: 'fa fa-fw fa-' + type, style: { color: color } }) + ), + _react2.default.createElement('input', { + type: 'text', + ref: 'input', + placeholder: placeholder, + className: 'form-control', + value: value, + onChange: this.onChange, + onFocus: this.onFocus, + onBlur: this.onBlur, + onKeyDown: this.onKeyDown + }), + (focus || mousefocus) && _react2.default.createElement( + 'div', + { className: 'popover bottom', + onMouseEnter: this.onMouseEnter, + onMouseLeave: this.onMouseLeave }, + _react2.default.createElement('div', { className: 'arrow' }), + _react2.default.createElement( + 'div', + { className: 'popover-content' }, + this.getDesc() + ) + ) + ); + } + }]); + + return FilterInput; +}(_react.Component); + +exports.default = FilterInput; + +},{"../../filt/filt":61,"../../utils.js":63,"./FilterDocs":29,"classnames":"classnames","react":"react","react-dom":"react-dom"}],31:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _Button = require('../common/Button'); + +var _Button2 = _interopRequireDefault(_Button); + +var _utils = require('../../flow/utils.js'); + +var _flows = require('../../ducks/flows'); + +var flowsActions = _interopRequireWildcard(_flows); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +FlowMenu.title = 'Flow'; + +FlowMenu.propTypes = { + flow: _react.PropTypes.object.isRequired +}; + +function FlowMenu(_ref) { + var flow = _ref.flow; + var acceptFlow = _ref.acceptFlow; + var replayFlow = _ref.replayFlow; + var duplicateFlow = _ref.duplicateFlow; + var removeFlow = _ref.removeFlow; + var revertFlow = _ref.revertFlow; + + + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'div', + { className: 'menu-row' }, + _react2.default.createElement(_Button2.default, { disabled: !flow || !flow.intercepted, title: '[a]ccept intercepted flow', text: 'Accept', icon: 'fa-play', onClick: function onClick() { + return acceptFlow(flow); + } }), + _react2.default.createElement(_Button2.default, { title: '[r]eplay flow', text: 'Replay', icon: 'fa-repeat', onClick: function onClick() { + return replayFlow(flow); + } }), + _react2.default.createElement(_Button2.default, { title: '[D]uplicate flow', text: 'Duplicate', icon: 'fa-copy', onClick: function onClick() { + return duplicateFlow(flow); + } }), + _react2.default.createElement(_Button2.default, { title: '[d]elete flow', text: 'Delete', icon: 'fa-trash', onClick: function onClick() { + return removeFlow(flow); + } }), + _react2.default.createElement(_Button2.default, { disabled: !flow || !flow.modified, title: 'revert changes to flow [V]', text: 'Revert', icon: 'fa-history', onClick: function onClick() { + return revertFlow(flow); + } }), + _react2.default.createElement(_Button2.default, { title: 'download', text: 'Download', icon: 'fa-download', onClick: function onClick() { + return window.location = _utils.MessageUtils.getContentURL(flow, flow.response); + } }) + ), + _react2.default.createElement('div', { className: 'clearfix' }) + ); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + flow: state.flows.byId[state.flows.selected[0]] + }; +}, { + acceptFlow: flowsActions.accept, + replayFlow: flowsActions.replay, + duplicateFlow: flowsActions.duplicate, + removeFlow: flowsActions.remove, + revertFlow: flowsActions.revert +})(FlowMenu); + +},{"../../ducks/flows":50,"../../flow/utils.js":62,"../common/Button":40,"react":"react","react-redux":"react-redux"}],32:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = MainMenu; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _FilterInput = require('./FilterInput'); + +var _FilterInput2 = _interopRequireDefault(_FilterInput); + +var _settings = require('../../ducks/settings'); + +var _flowView = require('../../ducks/flowView'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +MainMenu.title = "Start"; + +function MainMenu() { + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'div', + { className: 'menu-row' }, + _react2.default.createElement(FlowFilterInput, null), + _react2.default.createElement(HighlightInput, null), + _react2.default.createElement(InterceptInput, null) + ), + _react2.default.createElement('div', { className: 'clearfix' }) + ); +} + +var InterceptInput = (0, _reactRedux.connect)(function (state) { + return { + value: state.settings.intercept || '', + placeholder: 'Intercept', + type: 'pause', + color: 'hsl(208, 56%, 53%)' + }; +}, { onChange: function onChange(intercept) { + return (0, _settings.update)({ intercept: intercept }); + } })(_FilterInput2.default); + +var FlowFilterInput = (0, _reactRedux.connect)(function (state) { + return { + value: state.flowView.filter || '', + placeholder: 'Search', + type: 'search', + color: 'black' + }; +}, { onChange: _flowView.updateFilter })(_FilterInput2.default); + +var HighlightInput = (0, _reactRedux.connect)(function (state) { + return { + value: state.flowView.highlight || '', + placeholder: 'Highlight', + type: 'tag', + color: 'hsl(48, 100%, 50%)' + }; +}, { onChange: _flowView.updateHighlight })(_FilterInput2.default); + +},{"../../ducks/flowView":49,"../../ducks/settings":53,"./FilterInput":30,"react":"react","react-redux":"react-redux"}],33:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _ToggleButton = require('../common/ToggleButton'); + +var _ToggleButton2 = _interopRequireDefault(_ToggleButton); + +var _ToggleInputButton = require('../common/ToggleInputButton'); + +var _ToggleInputButton2 = _interopRequireDefault(_ToggleInputButton); + +var _settings = require('../../ducks/settings'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +OptionMenu.title = 'Options'; + +OptionMenu.propTypes = { + settings: _react.PropTypes.object.isRequired, + updateSettings: _react.PropTypes.func.isRequired +}; + +function OptionMenu(_ref) { + var settings = _ref.settings; + var updateSettings = _ref.updateSettings; + + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'div', + { className: 'menu-row' }, + _react2.default.createElement(_ToggleButton2.default, { text: 'showhost', + checked: settings.showhost, + onToggle: function onToggle() { + return updateSettings({ showhost: !settings.showhost }); + } + }), + _react2.default.createElement(_ToggleButton2.default, { text: 'no_upstream_cert', + checked: settings.no_upstream_cert, + onToggle: function onToggle() { + return updateSettings({ no_upstream_cert: !settings.no_upstream_cert }); + } + }), + _react2.default.createElement(_ToggleButton2.default, { text: 'rawtcp', + checked: settings.rawtcp, + onToggle: function onToggle() { + return updateSettings({ rawtcp: !settings.rawtcp }); + } + }), + _react2.default.createElement(_ToggleButton2.default, { text: 'http2', + checked: settings.http2, + onToggle: function onToggle() { + return updateSettings({ http2: !settings.http2 }); + } + }), + _react2.default.createElement(_ToggleButton2.default, { text: 'anticache', + checked: settings.anticache, + onToggle: function onToggle() { + return updateSettings({ anticache: !settings.anticache }); + } + }), + _react2.default.createElement(_ToggleButton2.default, { text: 'anticomp', + checked: settings.anticomp, + onToggle: function onToggle() { + return updateSettings({ anticomp: !settings.anticomp }); + } + }), + _react2.default.createElement(_ToggleInputButton2.default, { name: 'stickyauth', placeholder: 'Sticky auth filter', + checked: !!settings.stickyauth, + txt: settings.stickyauth || '', + onToggleChanged: function onToggleChanged(txt) { + return updateSettings({ stickyauth: !settings.stickyauth ? txt : null }); + } + }), + _react2.default.createElement(_ToggleInputButton2.default, { name: 'stickycookie', placeholder: 'Sticky cookie filter', + checked: !!settings.stickycookie, + txt: settings.stickycookie || '', + onToggleChanged: function onToggleChanged(txt) { + return updateSettings({ stickycookie: !settings.stickycookie ? txt : null }); + } + }), + _react2.default.createElement(_ToggleInputButton2.default, { name: 'stream', placeholder: 'stream...', + checked: !!settings.stream, + txt: settings.stream || '', + inputType: 'number', + onToggleChanged: function onToggleChanged(txt) { + return updateSettings({ stream: !settings.stream ? txt : null }); + } + }) + ), + _react2.default.createElement('div', { className: 'clearfix' }) + ); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + settings: state.settings + }; +}, { + updateSettings: _settings.update +})(OptionMenu); + +},{"../../ducks/settings":53,"../common/ToggleButton":42,"../common/ToggleInputButton":43,"react":"react","react-redux":"react-redux"}],34:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _ToggleButton = require('../common/ToggleButton'); + +var _ToggleButton2 = _interopRequireDefault(_ToggleButton); + +var _eventLog = require('../../ducks/eventLog'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +ViewMenu.title = 'View'; +ViewMenu.route = 'flows'; + +ViewMenu.propTypes = { + eventLogVisible: _react.PropTypes.bool.isRequired, + toggleEventLog: _react.PropTypes.func.isRequired +}; + +function ViewMenu(_ref) { + var eventLogVisible = _ref.eventLogVisible; + var toggleEventLog = _ref.toggleEventLog; + + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement( + 'div', + { className: 'menu-row' }, + _react2.default.createElement(_ToggleButton2.default, { text: 'Show Event Log', checked: eventLogVisible, onToggle: toggleEventLog }) + ), + _react2.default.createElement('div', { className: 'clearfix' }) + ); +} + +exports.default = (0, _reactRedux.connect)(function (state) { + return { + eventLogVisible: state.eventLog.visible + }; +}, { + toggleEventLog: _eventLog.toggleVisibility +})(ViewMenu); + +},{"../../ducks/eventLog":48,"../common/ToggleButton":42,"react":"react","react-redux":"react-redux"}],35:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _Splitter = require('./common/Splitter'); + +var _Splitter2 = _interopRequireDefault(_Splitter); + +var _FlowTable = require('./FlowTable'); + +var _FlowTable2 = _interopRequireDefault(_FlowTable); + +var _FlowView = require('./FlowView'); + +var _FlowView2 = _interopRequireDefault(_FlowView); + +var _flows = require('../ducks/flows'); + +var flowsActions = _interopRequireWildcard(_flows); + +var _flowView = require('../ducks/flowView'); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 MainView = function (_Component) { + _inherits(MainView, _Component); + + function MainView() { + _classCallCheck(this, MainView); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(MainView).apply(this, arguments)); + } + + _createClass(MainView, [{ + key: 'render', + value: function render() { + var _this2 = this; + + var _props = this.props; + var flows = _props.flows; + var selectedFlow = _props.selectedFlow; + var highlight = _props.highlight; + + return _react2.default.createElement( + 'div', + { className: 'main-view' }, + _react2.default.createElement(_FlowTable2.default, { + ref: 'flowTable', + flows: flows, + selected: selectedFlow, + highlight: highlight, + onSelect: this.props.selectFlow + }), + selectedFlow && [_react2.default.createElement(_Splitter2.default, { key: 'splitter' }), _react2.default.createElement(_FlowView2.default, { + key: 'flowDetails', + ref: 'flowDetails', + tab: this.props.routeParams.detailTab, + query: this.props.query, + updateFlow: function updateFlow(data) { + return _this2.props.updateFlow(selectedFlow, data); + }, + flow: selectedFlow + })] + ); + } + }]); + + return MainView; +}(_react.Component); + +MainView.propTypes = { + highlight: _react.PropTypes.string, + sort: _react.PropTypes.object +}; +exports.default = (0, _reactRedux.connect)(function (state) { + return { + flows: state.flowView.data, + filter: state.flowView.filter, + highlight: state.flowView.highlight, + selectedFlow: state.flows.byId[state.flows.selected[0]] + }; +}, { + selectFlow: flowsActions.select, + updateFilter: _flowView.updateFilter, + updateHighlight: _flowView.updateHighlight, + updateFlow: flowsActions.update +})(MainView); + +},{"../ducks/flowView":49,"../ducks/flows":50,"./FlowTable":16,"./FlowView":20,"./common/Splitter":41,"react":"react","react-redux":"react-redux"}],36:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = Prompt; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _utils = require('../utils.js'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +Prompt.propTypes = { + options: _react.PropTypes.array.isRequired, + done: _react.PropTypes.func.isRequired, + prompt: _react.PropTypes.string +}; + +function Prompt(_ref) { + var prompt = _ref.prompt; + var done = _ref.done; + var options = _ref.options; + + var opts = []; + + for (var i = 0; i < options.length; i++) { + var opt = options[i]; + if (_lodash2.default.isString(opt)) { + var str = opt; + while (str.length > 0 && keyTaken(str[0])) { + str = str.substr(1); + } + opt = { text: opt, key: str[0] }; + } + if (!opt.text || !opt.key || keyTaken(opt.key)) { + throw 'invalid options'; + } + opts.push(opt); + } + + function keyTaken(k) { + return _lodash2.default.map(opts, 'key').includes(k); + } + + function onKeyDown(event) { + event.stopPropagation(); + event.preventDefault(); + var key = opts.find(function (opt) { + return _utils.Key[opt.key.toUpperCase()] === event.keyCode; + }); + if (!key && event.keyCode !== _utils.Key.ESC && event.keyCode !== _utils.Key.ENTER) { + return; + } + done(key.key || false); + } + + return _react2.default.createElement( + 'div', + { tabIndex: '0', onKeyDown: onKeyDown, className: 'prompt-dialog' }, + _react2.default.createElement( + 'div', + { className: 'prompt-content' }, + prompt || _react2.default.createElement( + 'strong', + null, + 'Select: ' + ), + opts.map(function (opt) { + var idx = opt.text.indexOf(opt.key); + function onClick(event) { + done(opt.key); + event.stopPropagation(); + } + return _react2.default.createElement( + 'span', + { key: opt.key, className: 'option', onClick: onClick }, + idx !== -1 ? opt.text.substring(0, idx) : opt.text + '(', + _react2.default.createElement( + 'strong', + { className: 'text-primary' }, + opt.key + ), + idx !== -1 ? opt.text.substring(idx + 1) : ')' + ); + }) + ) + ); +} + +},{"../utils.js":63,"lodash":"lodash","react":"react","react-dom":"react-dom"}],37:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactRedux = require('react-redux'); + +var _app = require('../ducks/app'); + +var _keyboard = require('../ducks/ui/keyboard'); + +var _Header = require('./Header'); + +var _Header2 = _interopRequireDefault(_Header); + +var _EventLog = require('./EventLog'); + +var _EventLog2 = _interopRequireDefault(_EventLog); + +var _Footer = require('./Footer'); + +var _Footer2 = _interopRequireDefault(_Footer); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 ProxyAppMain = function (_Component) { + _inherits(ProxyAppMain, _Component); + + function ProxyAppMain() { + _classCallCheck(this, ProxyAppMain); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(ProxyAppMain).apply(this, arguments)); + } + + _createClass(ProxyAppMain, [{ + key: 'componentWillMount', + value: function componentWillMount() { + this.props.appInit(this.context.router); + window.addEventListener('keydown', this.props.onKeyDown); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + this.props.appDestruct(this.context.router); + window.removeEventListener('keydown', this.props.onKeyDown); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + /* + FIXME: improve react-router -> redux integration. + if (nextProps.location.query[Query.SEARCH] !== nextProps.filter) { + this.props.updateFilter(nextProps.location.query[Query.SEARCH], false) + } + if (nextProps.location.query[Query.HIGHLIGHT] !== nextProps.highlight) { + this.props.updateHighlight(nextProps.location.query[Query.HIGHLIGHT], false) + } + */ + if (nextProps.query === this.props.query && nextProps.selectedFlowId === this.props.selectedFlowId && nextProps.panel === this.props.panel) { + return; + } + if (nextProps.selectedFlowId) { + this.context.router.replace({ pathname: '/flows/' + nextProps.selectedFlowId + '/' + nextProps.panel, query: nextProps.query }); + } else { + this.context.router.replace({ pathname: '/flows', query: nextProps.query }); + } + } + }, { + key: 'render', + value: function render() { + var _props = this.props; + var showEventLog = _props.showEventLog; + var location = _props.location; + var children = _props.children; + var query = _props.query; + + return _react2.default.createElement( + 'div', + { id: 'container', tabIndex: '0' }, + _react2.default.createElement(_Header2.default, null), + _react2.default.cloneElement(children, { ref: 'view', location: location, query: query }), + showEventLog && _react2.default.createElement(_EventLog2.default, { key: 'eventlog' }), + _react2.default.createElement(_Footer2.default, null) + ); + } + }]); + + return ProxyAppMain; +}(_react.Component); + +ProxyAppMain.contextTypes = { + router: _react.PropTypes.object.isRequired +}; +exports.default = (0, _reactRedux.connect)(function (state) { + return { + showEventLog: state.eventLog.visible, + query: state.flowView.filter, + panel: state.ui.flow.tab, + selectedFlowId: state.flows.selected[0] + }; +}, { + appInit: _app.init, + appDestruct: _app.destruct, + onKeyDown: _keyboard.onKeyDown +})(ProxyAppMain); + +},{"../ducks/app":47,"../ducks/ui/keyboard":57,"./EventLog":14,"./Footer":26,"./Header":27,"react":"react","react-redux":"react-redux"}],38:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _ValueEditor = require('./ValueEditor'); + +var _ValueEditor2 = _interopRequireDefault(_ValueEditor); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 ValidateEditor = function (_Component) { + _inherits(ValidateEditor, _Component); + + function ValidateEditor(props) { + _classCallCheck(this, ValidateEditor); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ValidateEditor).call(this, props)); + + _this.state = { valid: props.isValid(props.content) }; + _this.onInput = _this.onInput.bind(_this); + _this.onDone = _this.onDone.bind(_this); + return _this; + } + + _createClass(ValidateEditor, [{ + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + this.setState({ valid: nextProps.isValid(nextProps.content) }); + } + }, { + key: 'onInput', + value: function onInput(content) { + this.setState({ valid: this.props.isValid(content) }); + } + }, { + key: 'onDone', + value: function onDone(content) { + if (!this.props.isValid(content)) { + this.editor.reset(); + content = this.props.content; + } + this.props.onDone(content); + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var className = (0, _classnames2.default)(this.props.className, { + 'has-success': this.state.valid, + 'has-warning': !this.state.valid + }); + return _react2.default.createElement(_ValueEditor2.default, { + content: this.props.content, + readonly: this.props.readonly, + onDone: this.onDone, + onInput: this.onInput, + className: className, + ref: function ref(e) { + return _this2.editor = e; + } + }); + } + }]); + + return ValidateEditor; +}(_react.Component); + +ValidateEditor.propTypes = { + content: _react.PropTypes.string.isRequired, + readonly: _react.PropTypes.bool, + onDone: _react.PropTypes.func.isRequired, + className: _react.PropTypes.string, + isValid: _react.PropTypes.func.isRequired +}; +exports.default = ValidateEditor; + +},{"./ValueEditor":39,"classnames":"classnames","react":"react"}],39:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _utils = require('../../utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 ValueEditor = function (_Component) { + _inherits(ValueEditor, _Component); + + function ValueEditor(props) { + _classCallCheck(this, ValueEditor); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ValueEditor).call(this, props)); + + _this.state = { editable: false }; + + _this.onPaste = _this.onPaste.bind(_this); + _this.onMouseDown = _this.onMouseDown.bind(_this); + _this.onMouseUp = _this.onMouseUp.bind(_this); + _this.onFocus = _this.onFocus.bind(_this); + _this.onClick = _this.onClick.bind(_this); + _this.blur = _this.blur.bind(_this); + _this.onBlur = _this.onBlur.bind(_this); + _this.reset = _this.reset.bind(_this); + _this.onKeyDown = _this.onKeyDown.bind(_this); + _this.onInput = _this.onInput.bind(_this); + return _this; + } + + _createClass(ValueEditor, [{ + key: 'blur', + value: function blur() { + // a stop would cause a blur as a side-effect. + // but a blur event must trigger a stop as well. + // to fix this, make stop = blur and do the actual stop in the onBlur handler. + this.input.blur(); + } + }, { + key: 'reset', + value: function reset() { + this.input.innerHTML = _lodash2.default.escape(this.props.content); + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var className = (0, _classnames2.default)('inline-input', { + 'readonly': this.props.readonly, + 'editable': !this.props.readonly + }, this.props.className); + return _react2.default.createElement('div', { + ref: function ref(input) { + return _this2.input = input; + }, + tabIndex: this.props.readonly ? undefined : 0, + className: className, + contentEditable: this.state.editable || undefined, + onFocus: this.onFocus, + onMouseDown: this.onMouseDown, + onClick: this.onClick, + onBlur: this.onBlur, + onKeyDown: this.onKeyDown, + onInput: this.onInput, + onPaste: this.onPaste, + dangerouslySetInnerHTML: { __html: _lodash2.default.escape(this.props.content) } + }); + } + }, { + key: 'onPaste', + value: function onPaste(e) { + e.preventDefault(); + var content = e.clipboardData.getData('text/plain'); + document.execCommand('insertHTML', false, content); + } + }, { + key: 'onMouseDown', + value: function onMouseDown(e) { + this._mouseDown = true; + window.addEventListener('mouseup', this.onMouseUp); + } + }, { + key: 'onMouseUp', + value: function onMouseUp() { + if (this._mouseDown) { + this._mouseDown = false; + window.removeEventListener('mouseup', this.onMouseUp); + } + } + }, { + key: 'onClick', + value: function onClick(e) { + this.onMouseUp(); + this.onFocus(e); + } + }, { + key: 'onFocus', + value: function onFocus(e) { + var _this3 = this; + + if (this._mouseDown || this._ignore_events || this.state.editable || this.props.readonly) { + return; + } + + // contenteditable in FireFox is more or less broken. + // - we need to blur() and then focus(), otherwise the caret is not shown. + // - blur() + focus() == we need to save the caret position before + // Firefox sometimes just doesn't set a caret position => use caretPositionFromPoint + var sel = window.getSelection(); + var range = void 0; + if (sel.rangeCount > 0) { + range = sel.getRangeAt(0); + } else if (document.caretPositionFromPoint && e.clientX && e.clientY) { + var pos = document.caretPositionFromPoint(e.clientX, e.clientY); + range = document.createRange(); + range.setStart(pos.offsetNode, pos.offset); + } else if (document.caretRangeFromPoint && e.clientX && e.clientY) { + range = document.caretRangeFromPoint(e.clientX, e.clientY); + } else { + range = document.createRange(); + range.selectNodeContents(this.input); + } + + this._ignore_events = true; + this.setState({ editable: true }, function () { + _this3.input.blur(); + _this3.input.focus(); + _this3._ignore_events = false; + range.selectNodeContents(_this3.input); + sel.removeAllRanges(); + sel.addRange(range); + }); + } + }, { + key: 'onBlur', + value: function onBlur(e) { + if (this._ignore_events || this.props.readonly) { + return; + } + window.getSelection().removeAllRanges(); //make sure that selection is cleared on blur + this.setState({ editable: false }); + this.props.onDone(this.input.textContent); + } + }, { + key: 'onKeyDown', + value: function onKeyDown(e) { + e.stopPropagation(); + switch (e.keyCode) { + case _utils.Key.ESC: + e.preventDefault(); + this.reset(); + this.blur(); + break; + case _utils.Key.ENTER: + if (!e.shiftKey) { + e.preventDefault(); + this.blur(); + } + break; + default: + break; + } + this.props.onKeyDown(e); + } + }, { + key: 'onInput', + value: function onInput() { + this.props.onInput(this.input.textContent); + } + }]); + + return ValueEditor; +}(_react.Component); + +ValueEditor.propTypes = { + content: _react.PropTypes.string.isRequired, + readonly: _react.PropTypes.bool, + onDone: _react.PropTypes.func.isRequired, + className: _react.PropTypes.string, + onInput: _react.PropTypes.func, + onKeyDown: _react.PropTypes.func +}; +ValueEditor.defaultProps = { + onInput: function onInput() {}, + onKeyDown: function onKeyDown() {} +}; +exports.default = ValueEditor; + +},{"../../utils":63,"classnames":"classnames","lodash":"lodash","react":"react"}],40:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = Button; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +Button.propTypes = { + onClick: _react.PropTypes.func.isRequired, + text: _react.PropTypes.string, + icon: _react.PropTypes.string +}; + +function Button(_ref) { + var onClick = _ref.onClick; + var text = _ref.text; + var icon = _ref.icon; + var disabled = _ref.disabled; + var className = _ref.className; + + return _react2.default.createElement( + 'div', + { className: (0, _classnames2.default)(className, 'btn btn-default'), + onClick: onClick, + disabled: disabled }, + icon && _react2.default.createElement('i', { className: "fa fa-fw " + icon }), + text && text + ); +} + +},{"classnames":"classnames","react":"react"}],41:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 Splitter = function (_Component) { + _inherits(Splitter, _Component); + + function Splitter(props, context) { + _classCallCheck(this, Splitter); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Splitter).call(this, props, context)); + + _this.state = { applied: false, startX: false, startY: false }; + + _this.onMouseMove = _this.onMouseMove.bind(_this); + _this.onMouseDown = _this.onMouseDown.bind(_this); + _this.onMouseUp = _this.onMouseUp.bind(_this); + _this.onDragEnd = _this.onDragEnd.bind(_this); + return _this; + } + + _createClass(Splitter, [{ + key: 'onMouseDown', + value: function onMouseDown(e) { + this.setState({ startX: e.pageX, startY: e.pageY }); + + window.addEventListener('mousemove', this.onMouseMove); + window.addEventListener('mouseup', this.onMouseUp); + // Occasionally, only a dragEnd event is triggered, but no mouseUp. + window.addEventListener('dragend', this.onDragEnd); + } + }, { + key: 'onDragEnd', + value: function onDragEnd() { + _reactDom2.default.findDOMNode(this).style.transform = ''; + + window.removeEventListener('dragend', this.onDragEnd); + window.removeEventListener('mouseup', this.onMouseUp); + window.removeEventListener('mousemove', this.onMouseMove); + } + }, { + key: 'onMouseUp', + value: function onMouseUp(e) { + this.onDragEnd(); + + var node = _reactDom2.default.findDOMNode(this); + var prev = node.previousElementSibling; + + var flexBasis = prev.offsetHeight + e.pageY - this.state.startY; + + if (this.props.axis === 'x') { + flexBasis = prev.offsetWidth + e.pageX - this.state.startX; + } + + prev.style.flex = '0 0 ' + Math.max(0, flexBasis) + 'px'; + node.nextElementSibling.style.flex = '1 1 auto'; + + this.setState({ applied: true }); + this.onResize(); + } + }, { + key: 'onMouseMove', + value: function onMouseMove(e) { + var dX = 0; + var dY = 0; + if (this.props.axis === 'x') { + dX = e.pageX - this.state.startX; + } else { + dY = e.pageY - this.state.startY; + } + _reactDom2.default.findDOMNode(this).style.transform = 'translate(' + dX + 'px, ' + dY + 'px)'; + } + }, { + key: 'onResize', + value: function onResize() { + // Trigger a global resize event. This notifies components that employ virtual scrolling + // that their viewport may have changed. + window.setTimeout(function () { + return window.dispatchEvent(new CustomEvent('resize')); + }, 1); + } + }, { + key: 'reset', + value: function reset(willUnmount) { + if (!this.state.applied) { + return; + } + + var node = _reactDom2.default.findDOMNode(this); + + node.previousElementSibling.style.flex = ''; + node.nextElementSibling.style.flex = ''; + + if (!willUnmount) { + this.setState({ applied: false }); + } + this.onResize(); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + this.reset(true); + } + }, { + key: 'render', + value: function render() { + return _react2.default.createElement( + 'div', + { className: (0, _classnames2.default)('splitter', this.props.axis === 'x' ? 'splitter-x' : 'splitter-y') }, + _react2.default.createElement('div', { onMouseDown: this.onMouseDown, draggable: 'true' }) + ); + } + }]); + + return Splitter; +}(_react.Component); + +Splitter.defaultProps = { axis: 'x' }; +exports.default = Splitter; + +},{"classnames":"classnames","react":"react","react-dom":"react-dom"}],42:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = ToggleButton; + +var _react = require("react"); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +ToggleButton.propTypes = { + checked: _react.PropTypes.bool.isRequired, + onToggle: _react.PropTypes.func.isRequired, + text: _react.PropTypes.string.isRequired +}; + +function ToggleButton(_ref) { + var checked = _ref.checked; + var onToggle = _ref.onToggle; + var text = _ref.text; + + return _react2.default.createElement( + "div", + { className: "btn btn-toggle " + (checked ? "btn-primary" : "btn-default"), onClick: onToggle }, + _react2.default.createElement("i", { className: "fa fa-fw " + (checked ? "fa-check-square-o" : "fa-square-o") }), + " ", + text + ); +} + +},{"react":"react"}],43:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _classnames = require('classnames'); + +var _classnames2 = _interopRequireDefault(_classnames); + +var _utils = require('../../utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 ToggleInputButton = function (_Component) { + _inherits(ToggleInputButton, _Component); + + function ToggleInputButton(props) { + _classCallCheck(this, ToggleInputButton); + + var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ToggleInputButton).call(this, props)); + + _this.state = { txt: props.txt }; + return _this; + } + + _createClass(ToggleInputButton, [{ + key: 'onChange', + value: function onChange(e) { + this.setState({ txt: e.target.value }); + } + }, { + key: 'onKeyDown', + value: function onKeyDown(e) { + e.stopPropagation(); + if (e.keyCode === _utils.Key.ENTER) { + this.props.onToggleChanged(this.state.txt); + } + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + return _react2.default.createElement( + 'div', + { className: 'input-group toggle-input-btn' }, + _react2.default.createElement( + 'span', + { className: 'input-group-btn', + onClick: function onClick() { + return _this2.props.onToggleChanged(_this2.state.txt); + } }, + _react2.default.createElement( + 'div', + { className: (0, _classnames2.default)('btn', this.props.checked ? 'btn-primary' : 'btn-default') }, + _react2.default.createElement('span', { className: (0, _classnames2.default)('fa', this.props.checked ? 'fa-check-square-o' : 'fa-square-o') }), + ' ', + this.props.name + ) + ), + _react2.default.createElement('input', { + className: 'form-control', + placeholder: this.props.placeholder, + disabled: this.props.checked, + value: this.state.txt, + type: this.props.inputType, + onChange: function onChange(e) { + return _this2.onChange(e); + }, + onKeyDown: function onKeyDown(e) { + return _this2.onKeyDown(e); + } + }) + ); + } + }]); + + return ToggleInputButton; +}(_react.Component); + +ToggleInputButton.propTypes = { + name: _react.PropTypes.string.isRequired, + txt: _react.PropTypes.string.isRequired, + onToggleChanged: _react.PropTypes.func.isRequired +}; +exports.default = ToggleInputButton; + +},{"../../utils":63,"classnames":"classnames","react":"react"}],44:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + +var _react = require("react"); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require("react-dom"); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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 symShouldStick = Symbol("shouldStick"); +var isAtBottom = function isAtBottom(v) { + return v.scrollTop + v.clientHeight === v.scrollHeight; +}; + +exports.default = function (Component) { + var _class, _temp; + + return Object.assign((_temp = _class = function (_Component) { + _inherits(AutoScrollWrapper, _Component); + + function AutoScrollWrapper() { + _classCallCheck(this, AutoScrollWrapper); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(AutoScrollWrapper).apply(this, arguments)); + } + + _createClass(AutoScrollWrapper, [{ + key: "componentWillUpdate", + value: function componentWillUpdate() { + var viewport = _reactDom2.default.findDOMNode(this); + this[symShouldStick] = viewport.scrollTop && isAtBottom(viewport); + _get(Object.getPrototypeOf(AutoScrollWrapper.prototype), "componentWillUpdate", this) && _get(Object.getPrototypeOf(AutoScrollWrapper.prototype), "componentWillUpdate", this).call(this); + } + }, { + key: "componentDidUpdate", + value: function componentDidUpdate() { + var viewport = _reactDom2.default.findDOMNode(this); + if (this[symShouldStick] && !isAtBottom(viewport)) { + viewport.scrollTop = viewport.scrollHeight; + } + _get(Object.getPrototypeOf(AutoScrollWrapper.prototype), "componentDidUpdate", this) && _get(Object.getPrototypeOf(AutoScrollWrapper.prototype), "componentDidUpdate", this).call(this); + } + }]); + + return AutoScrollWrapper; + }(Component), _class.displayName = Component.name, _temp), Component); +}; + +},{"react":"react","react-dom":"react-dom"}],45:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.calcVScroll = calcVScroll; +/** + * Calculate virtual scroll stuffs + * + * @param {?Object} opts Options for calculation + * + * @returns {Object} result + * + * __opts__ should have following properties: + * - {number} itemCount + * - {number} rowHeight + * - {number} viewportTop + * - {number} viewportHeight + * - {Array} [itemHeights] + * + * __result__ have following properties: + * - {number} start + * - {number} end + * - {number} paddingTop + * - {number} paddingBottom + */ +function calcVScroll(opts) { + if (!opts) { + return { start: 0, end: 0, paddingTop: 0, paddingBottom: 0 }; + } + + var itemCount = opts.itemCount; + var rowHeight = opts.rowHeight; + var viewportTop = opts.viewportTop; + var viewportHeight = opts.viewportHeight; + var itemHeights = opts.itemHeights; + + var viewportBottom = viewportTop + viewportHeight; + + var start = 0; + var end = 0; + + var paddingTop = 0; + var paddingBottom = 0; + + if (itemHeights) { + + for (var i = 0, pos = 0; i < itemCount; i++) { + var height = itemHeights[i] || rowHeight; + + if (pos <= viewportTop && i % 2 === 0) { + paddingTop = pos; + start = i; + } + + if (pos <= viewportBottom) { + end = i + 1; + } else { + paddingBottom += height; + } + + pos += height; + } + } else { + + // Make sure that we start at an even row so that CSS `:nth-child(even)` is preserved + start = Math.max(0, Math.floor(viewportTop / rowHeight) - 1) & ~1; + end = Math.min(itemCount, start + Math.ceil(viewportHeight / rowHeight) + 2); + + // When a large trunk of elements is removed from the button, start may be far off the viewport. + // To make this issue less severe, limit the top placeholder to the total number of rows. + paddingTop = Math.min(start, itemCount) * rowHeight; + paddingBottom = Math.max(0, itemCount - end) * rowHeight; + } + + return { start: start, end: end, paddingTop: paddingTop, paddingBottom: paddingBottom }; +} + +},{}],46:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.AppDispatcher = undefined; + +var _flux = require("flux"); + +var _flux2 = _interopRequireDefault(_flux); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var PayloadSources = { + VIEW: "view", + SERVER: "server" +}; + +var AppDispatcher = exports.AppDispatcher = new _flux2.default.Dispatcher(); +AppDispatcher.dispatchViewAction = function (action) { + action.source = PayloadSources.VIEW; + this.dispatch(action); +}; +AppDispatcher.dispatchServerAction = function (action) { + action.source = PayloadSources.SERVER; + this.dispatch(action); +}; + +},{"flux":"flux"}],47:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.INIT = undefined; +exports.reduce = reduce; +exports.init = init; +exports.destruct = destruct; + +var _websocket = require('./websocket'); + +var INIT = exports.INIT = 'APP_INIT'; + +var defaultState = {}; + +function reduce() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + default: + return state; + } +} + +function init() { + return function (dispatch) { + dispatch((0, _websocket.connect)()); + dispatch({ type: INIT }); + }; +} + +function destruct() { + return function (dispatch) { + dispatch((0, _websocket.disconnect)()); + dispatch({ type: DESTRUCT }); + }; +} + +},{"./websocket":60}],48:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FETCH_ERROR = exports.UNKNOWN_CMD = exports.TOGGLE_FILTER = exports.TOGGLE_VISIBILITY = exports.RECEIVE = exports.ADD = exports.DATA_URL = exports.MSG_TYPE = undefined; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; + +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; }; + +exports.default = reduce; +exports.toggleFilter = toggleFilter; +exports.toggleVisibility = toggleVisibility; +exports.add = add; +exports.handleWsMsg = handleWsMsg; +exports.fetchData = fetchData; +exports.receiveData = receiveData; + +var _list = require('./utils/list'); + +var listActions = _interopRequireWildcard(_list); + +var _view = require('./utils/view'); + +var viewActions = _interopRequireWildcard(_view); + +var _websocket = require('./websocket'); + +var websocketActions = _interopRequireWildcard(_websocket); + +var _msgQueue = require('./msgQueue'); + +var msgQueueActions = _interopRequireWildcard(_msgQueue); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var MSG_TYPE = exports.MSG_TYPE = 'UPDATE_EVENTLOG'; +var DATA_URL = exports.DATA_URL = '/events'; + +var ADD = exports.ADD = 'EVENTLOG_ADD'; +var RECEIVE = exports.RECEIVE = 'EVENTLOG_RECEIVE'; +var TOGGLE_VISIBILITY = exports.TOGGLE_VISIBILITY = 'EVENTLOG_TOGGLE_VISIBILITY'; +var TOGGLE_FILTER = exports.TOGGLE_FILTER = 'EVENTLOG_TOGGLE_FILTER'; +var UNKNOWN_CMD = exports.UNKNOWN_CMD = 'EVENTLOG_UNKNOWN_CMD'; +var FETCH_ERROR = exports.FETCH_ERROR = 'EVENTLOG_FETCH_ERROR'; + +var defaultState = { + logId: 0, + visible: false, + filters: { debug: false, info: true, web: true }, + list: (0, listActions.default)(undefined, {}), + view: (0, viewActions.default)(undefined, {}) +}; + +function reduce() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + var _ret = function () { + switch (action.type) { + + case TOGGLE_VISIBILITY: + return { + v: _extends({}, state, { + visible: !state.visible + }) + }; + + case TOGGLE_FILTER: + var filters = _extends({}, state.filters, _defineProperty({}, action.filter, !state.filters[action.filter])); + return { + v: _extends({}, state, { + filters: filters, + view: (0, viewActions.default)(state.view, viewActions.updateFilter(state.list.data, function (log) { + return filters[log.level]; + })) + }) + }; + + case ADD: + var item = { + id: state.logId, + message: action.message, + level: action.level + }; + return { + v: _extends({}, state, { + logId: state.logId + 1, + list: (0, listActions.default)(state.list, listActions.add(item)), + view: (0, viewActions.default)(state.view, viewActions.add(item, function (log) { + return state.filters[log.level]; + })) + }) + }; + + case RECEIVE: + return { + v: _extends({}, state, { + list: (0, listActions.default)(state.list, listActions.receive(action.list)), + view: (0, viewActions.default)(state.view, viewActions.receive(action.list, function (log) { + return state.filters[log.level]; + })) + }) + }; + + default: + return { + v: state + }; + } + }(); + + if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v; +} + +/** + * @public + */ +function toggleFilter(filter) { + return { type: TOGGLE_FILTER, filter: filter }; +} + +/** + * @public + * + * @todo move to ui? + */ +function toggleVisibility() { + return { type: TOGGLE_VISIBILITY }; +} + +/** + * @public + */ +function add(message) { + var level = arguments.length <= 1 || arguments[1] === undefined ? 'web' : arguments[1]; + + return { type: ADD, message: message, level: level }; +} + +/** + * This action creater takes all WebSocket events + * + * @public websocket + */ +function handleWsMsg(msg) { + switch (msg.cmd) { + + case websocketActions.CMD_ADD: + return add(msg.data.message, msg.data.level); + + case websocketActions.CMD_RESET: + return fetchData(); + + default: + return { type: UNKNOWN_CMD, msg: msg }; + } +} + +/** + * @public websocket + */ +function fetchData() { + return msgQueueActions.fetchData(MSG_TYPE); +} + +/** + * @public msgQueue + */ +function receiveData(list) { + return { type: RECEIVE, list: list }; +} + +},{"./msgQueue":52,"./utils/list":58,"./utils/view":59,"./websocket":60}],49:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.UPDATE_HIGHLIGHT = exports.UPDATE_SORT = exports.UPDATE_FILTER = undefined; + +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; }; + +exports.makeFilter = makeFilter; +exports.makeSort = makeSort; +exports.default = reduce; +exports.updateFilter = updateFilter; +exports.updateHighlight = updateHighlight; +exports.updateSort = updateSort; +exports.selectRelative = selectRelative; + +var _view = require('./utils/view'); + +var viewActions = _interopRequireWildcard(_view); + +var _flows = require('./flows'); + +var flowActions = _interopRequireWildcard(_flows); + +var _filt = require('../filt/filt'); + +var _filt2 = _interopRequireDefault(_filt); + +var _utils = require('../flow/utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var UPDATE_FILTER = exports.UPDATE_FILTER = 'FLOWVIEW_UPDATE_FILTER'; +var UPDATE_SORT = exports.UPDATE_SORT = 'FLOWVIEW_UPDATE_SORT'; +var UPDATE_HIGHLIGHT = exports.UPDATE_HIGHLIGHT = 'FLOWVIEW_UPDATE_HIGHLIGHT'; + +var sortKeyFuns = { + + TLSColumn: function TLSColumn(flow) { + return flow.request.scheme; + }, + + PathColumn: function PathColumn(flow) { + return _utils.RequestUtils.pretty_url(flow.request); + }, + + MethodColumn: function MethodColumn(flow) { + return flow.request.method; + }, + + StatusColumn: function StatusColumn(flow) { + return flow.response && flow.response.status_code; + }, + + TimeColumn: function TimeColumn(flow) { + return flow.response && flow.response.timestamp_end - flow.request.timestamp_start; + }, + + SizeColumn: function SizeColumn(flow) { + var total = flow.request.contentLength; + if (flow.response) { + total += flow.response.contentLength || 0; + } + return total; + } +}; + +function makeFilter(filter) { + if (!filter) { + return; + } + return _filt2.default.parse(filter); +} + +function makeSort(_ref) { + var column = _ref.column; + var desc = _ref.desc; + + var sortKeyFun = sortKeyFuns[column]; + if (!sortKeyFun) { + return; + } + return function (a, b) { + var ka = sortKeyFun(a); + var kb = sortKeyFun(b); + if (ka > kb) { + return desc ? -1 : 1; + } + if (ka < kb) { + return desc ? 1 : -1; + } + return 0; + }; +} + +var defaultState = _extends({ + highlight: null, + filter: null, + sort: { column: null, desc: false } +}, (0, viewActions.default)(undefined, {})); + +function reduce() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + case UPDATE_HIGHLIGHT: + return _extends({}, state, { + highlight: action.highlight + }); + + case UPDATE_FILTER: + return _extends({}, (0, viewActions.default)(state, viewActions.updateFilter(action.flows, makeFilter(action.filter), makeSort(state.sort))), { + filter: action.filter + }); + + case UPDATE_SORT: + var sort = { column: action.column, desc: action.desc }; + return _extends({}, (0, viewActions.default)(state, viewActions.updateSort(makeSort(sort))), { + sort: sort + }); + + case flowActions.ADD: + return _extends({}, (0, viewActions.default)(state, viewActions.add(action.item, makeFilter(state.filter), makeSort(state.sort)))); + + case flowActions.UPDATE: + return _extends({}, (0, viewActions.default)(state, viewActions.update(action.item, makeFilter(state.filter), makeSort(state.sort)))); + + case flowActions.REMOVE: + return _extends({}, (0, viewActions.default)(state, viewActions.remove(action.id))); + + case flowActions.RECEIVE: + return _extends({}, (0, viewActions.default)(state, viewActions.receive(action.list, makeFilter(state.filter), makeSort(state.sort)))); + + default: + return _extends({}, (0, viewActions.default)(state, action)); + } +} + +/** + * @public + */ +function updateFilter(filter) { + return function (dispatch, getState) { + dispatch({ type: UPDATE_FILTER, filter: filter, flows: getState().flows.data }); + }; +} + +/** + * @public + */ +function updateHighlight(highlight) { + return { type: UPDATE_HIGHLIGHT, highlight: highlight }; +} + +/** + * @public + */ +function updateSort(column, desc) { + return { type: UPDATE_SORT, column: column, desc: desc }; +} + +/** + * @public + */ +function selectRelative(shift) { + return function (dispatch, getState) { + var currentSelectionIndex = getState().flowView.indexOf[getState().flows.selected[0]]; + var minIndex = 0; + var maxIndex = getState().flowView.data.length - 1; + var newIndex = void 0; + if (currentSelectionIndex === undefined) { + newIndex = shift < 0 ? minIndex : maxIndex; + } else { + newIndex = currentSelectionIndex + shift; + newIndex = Math.max(newIndex, minIndex); + newIndex = Math.min(newIndex, maxIndex); + } + var flow = getState().flowView.data[newIndex]; + dispatch(flowActions.select(flow ? flow.id : undefined)); + }; +} + +},{"../filt/filt":61,"../flow/utils":62,"./flows":50,"./utils/view":59}],50:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SELECT = exports.FETCH_ERROR = exports.UNKNOWN_CMD = exports.REQUEST_ACTION = exports.RECEIVE = exports.REMOVE = exports.UPDATE = exports.ADD = exports.DATA_URL = exports.MSG_TYPE = undefined; + +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; }; + +exports.default = reduce; +exports.accept = accept; +exports.acceptAll = acceptAll; +exports.remove = remove; +exports.duplicate = duplicate; +exports.replay = replay; +exports.revert = revert; +exports.update = update; +exports.uploadContent = uploadContent; +exports.clear = clear; +exports.download = download; +exports.upload = upload; +exports.select = select; +exports.handleWsMsg = handleWsMsg; +exports.fetchFlows = fetchFlows; +exports.receiveData = receiveData; +exports.addFlow = addFlow; +exports.updateFlow = updateFlow; +exports.removeFlow = removeFlow; + +var _utils = require('../utils'); + +var _list = require('./utils/list'); + +var listActions = _interopRequireWildcard(_list); + +var _msgQueue = require('./msgQueue'); + +var msgQueueActions = _interopRequireWildcard(_msgQueue); + +var _websocket = require('./websocket'); + +var websocketActions = _interopRequireWildcard(_websocket); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var MSG_TYPE = exports.MSG_TYPE = 'UPDATE_FLOWS'; +var DATA_URL = exports.DATA_URL = '/flows'; + +var ADD = exports.ADD = 'FLOWS_ADD'; +var UPDATE = exports.UPDATE = 'FLOWS_UPDATE'; +var REMOVE = exports.REMOVE = 'FLOWS_REMOVE'; +var RECEIVE = exports.RECEIVE = 'FLOWS_RECEIVE'; +var REQUEST_ACTION = exports.REQUEST_ACTION = 'FLOWS_REQUEST_ACTION'; +var UNKNOWN_CMD = exports.UNKNOWN_CMD = 'FLOWS_UNKNOWN_CMD'; +var FETCH_ERROR = exports.FETCH_ERROR = 'FLOWS_FETCH_ERROR'; +var SELECT = exports.SELECT = 'FLOWS_SELECT'; + +var defaultState = _extends({ + selected: [] +}, (0, listActions.default)(undefined, {})); + +function reduce() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + case ADD: + return _extends({}, state, (0, listActions.default)(state, listActions.add(action.item))); + + case UPDATE: + return _extends({}, state, (0, listActions.default)(state, listActions.update(action.item))); + + case REMOVE: + return _extends({}, state, (0, listActions.default)(state, listActions.remove(action.id))); + + case RECEIVE: + return _extends({}, state, (0, listActions.default)(state, listActions.receive(action.list))); + + case SELECT: + return _extends({}, state, { + selected: action.flowIds + }); + + default: + return _extends({}, state, (0, listActions.default)(state, action)); + } +} + +/** + * @public + */ +function accept(flow) { + return function (dispatch) { + return (0, _utils.fetchApi)('/flows/' + flow.id + '/accept', { method: 'POST' }); + }; +} + +/** + * @public + */ +function acceptAll() { + return function (dispatch) { + return (0, _utils.fetchApi)('/flows/accept', { method: 'POST' }); + }; +} + +/** + * @public + */ +function remove(flow) { + return function (dispatch) { + return (0, _utils.fetchApi)('/flows/' + flow.id, { method: 'DELETE' }); + }; +} + +/** + * @public + */ +function duplicate(flow) { + return function (dispatch) { + return (0, _utils.fetchApi)('/flows/' + flow.id + '/duplicate', { method: 'POST' }); + }; +} + +/** + * @public + */ +function replay(flow) { + return function (dispatch) { + return (0, _utils.fetchApi)('/flows/' + flow.id + '/replay', { method: 'POST' }); + }; +} + +/** + * @public + */ +function revert(flow) { + return function (dispatch) { + return (0, _utils.fetchApi)('/flows/' + flow.id + '/revert', { method: 'POST' }); + }; +} + +/** + * @public + */ +function update(flow, data) { + return function (dispatch) { + return _utils.fetchApi.put('/flows/' + flow.id, data); + }; +} + +function uploadContent(flow, file, type) { + var body = new FormData(); + file = new Blob([file], { type: 'plain/text' }); + body.append('file', file); + return function (dispatch) { + return (0, _utils.fetchApi)('/flows/' + flow.id + '/' + type + '/content', { method: 'post', body: body }); + }; +} + +/** + * @public + */ +function clear() { + return function (dispatch) { + return (0, _utils.fetchApi)('/clear', { method: 'POST' }); + }; +} + +/** + * @public + */ +function download() { + window.location = '/flows/dump'; + return { type: REQUEST_ACTION }; +} + +/** + * @public + */ +function upload(file) { + var body = new FormData(); + body.append('file', file); + return function (dispatch) { + return (0, _utils.fetchApi)('/flows/dump', { method: 'post', body: body }); + }; +} + +function select(id) { + return { + type: SELECT, + flowIds: id ? [id] : [] + }; +} + +/** + * This action creater takes all WebSocket events + * + * @public websocket + */ +function handleWsMsg(msg) { + switch (msg.cmd) { + + case websocketActions.CMD_ADD: + return addFlow(msg.data); + + case websocketActions.CMD_UPDATE: + return updateFlow(msg.data); + + case websocketActions.CMD_REMOVE: + return removeFlow(msg.data.id); + + case websocketActions.CMD_RESET: + return fetchFlows(); + + default: + return { type: UNKNOWN_CMD, msg: msg }; + } +} + +/** + * @public websocket + */ +function fetchFlows() { + return msgQueueActions.fetchData(MSG_TYPE); +} + +/** + * @public msgQueue + */ +function receiveData(list) { + return { type: RECEIVE, list: list }; +} + +/** + * @private + */ +function addFlow(item) { + return { type: ADD, item: item }; +} + +/** + * @private + */ +function updateFlow(item) { + return { type: UPDATE, item: item }; +} + +/** + * @private + */ +function removeFlow(id) { + return { type: REMOVE, id: id }; +} + +},{"../utils":63,"./msgQueue":52,"./utils/list":58,"./websocket":60}],51:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _redux = require('redux'); + +var _eventLog = require('./eventLog'); + +var _eventLog2 = _interopRequireDefault(_eventLog); + +var _websocket = require('./websocket'); + +var _websocket2 = _interopRequireDefault(_websocket); + +var _flows = require('./flows'); + +var _flows2 = _interopRequireDefault(_flows); + +var _flowView = require('./flowView'); + +var _flowView2 = _interopRequireDefault(_flowView); + +var _settings = require('./settings'); + +var _settings2 = _interopRequireDefault(_settings); + +var _index = require('./ui/index'); + +var _index2 = _interopRequireDefault(_index); + +var _msgQueue = require('./msgQueue'); + +var _msgQueue2 = _interopRequireDefault(_msgQueue); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = (0, _redux.combineReducers)({ + eventLog: _eventLog2.default, + websocket: _websocket2.default, + flows: _flows2.default, + flowView: _flowView2.default, + settings: _settings2.default, + ui: _index2.default, + msgQueue: _msgQueue2.default +}); + +},{"./eventLog":48,"./flowView":49,"./flows":50,"./msgQueue":52,"./settings":53,"./ui/index":56,"./websocket":60,"redux":"redux"}],52:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.FETCH_ERROR = exports.CLEAR = exports.ENQUEUE = exports.INIT = undefined; + +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 _handlers; + +exports.default = reduce; +exports.handleWsMsg = handleWsMsg; +exports.fetchData = fetchData; +exports.receive = receive; +exports.init = init; +exports.clear = clear; +exports.fetchError = fetchError; + +var _utils = require('../utils'); + +var _websocket = require('./websocket'); + +var websocketActions = _interopRequireWildcard(_websocket); + +var _eventLog = require('./eventLog'); + +var eventLogActions = _interopRequireWildcard(_eventLog); + +var _flows = require('./flows'); + +var flowsActions = _interopRequireWildcard(_flows); + +var _settings = require('./settings'); + +var settingsActions = _interopRequireWildcard(_settings); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _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); } } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var INIT = exports.INIT = 'MSG_QUEUE_INIT'; +var ENQUEUE = exports.ENQUEUE = 'MSG_QUEUE_ENQUEUE'; +var CLEAR = exports.CLEAR = 'MSG_QUEUE_CLEAR'; +var FETCH_ERROR = exports.FETCH_ERROR = 'MSG_QUEUE_FETCH_ERROR'; + +var handlers = (_handlers = {}, _defineProperty(_handlers, eventLogActions.MSG_TYPE, eventLogActions), _defineProperty(_handlers, flowsActions.MSG_TYPE, flowsActions), _defineProperty(_handlers, settingsActions.MSG_TYPE, settingsActions), _handlers); + +var defaultState = {}; + +function reduce() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + case INIT: + return _extends({}, state, _defineProperty({}, action.queue, [])); + + case ENQUEUE: + return _extends({}, state, _defineProperty({}, action.queue, [].concat(_toConsumableArray(state[action.queue]), [action.msg]))); + + case CLEAR: + return _extends({}, state, _defineProperty({}, action.queue, null)); + + default: + return state; + } +} + +/** + * @public websocket + */ +function handleWsMsg(msg) { + return function (dispatch, getState) { + var handler = handlers[msg.type]; + if (msg.cmd === websocketActions.CMD_RESET) { + return dispatch(fetchData(handler.MSG_TYPE)); + } + if (getState().msgQueue[handler.MSG_TYPE]) { + return dispatch({ type: ENQUEUE, queue: handler.MSG_TYPE, msg: msg }); + } + return dispatch(handler.handleWsMsg(msg)); + }; +} + +/** + * @public + */ +function fetchData(type) { + return function (dispatch) { + var handler = handlers[type]; + + dispatch(init(handler.MSG_TYPE)); + + (0, _utils.fetchApi)(handler.DATA_URL).then(function (res) { + return res.json(); + }).then(function (json) { + return dispatch(receive(type, json)); + }).catch(function (error) { + return dispatch(fetchError(type, error)); + }); + }; +} + +/** + * @private + */ +function receive(type, res) { + return function (dispatch, getState) { + var handler = handlers[type]; + var queue = getState().msgQueue[handler.MSG_TYPE] || []; + + dispatch(clear(handler.MSG_TYPE)); + dispatch(handler.receiveData(res.data)); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = queue[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var msg = _step.value; + + dispatch(handler.handleWsMsg(msg)); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + }; +} + +/** + * @private + */ +function init(queue) { + return { type: INIT, queue: queue }; +} + +/** + * @private + */ +function clear(queue) { + return { type: CLEAR, queue: queue }; +} + +/** + * @private + */ +function fetchError(type, error) { + var _ref; + + return _ref = { type: FETCH_ERROR }, _defineProperty(_ref, 'type', type), _defineProperty(_ref, 'error', error), _ref; +} + +},{"../utils":63,"./eventLog":48,"./flows":50,"./settings":53,"./websocket":60}],53:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.UNKNOWN_CMD = exports.REQUEST_UPDATE = exports.UPDATE = exports.RECEIVE = exports.DATA_URL = exports.MSG_TYPE = undefined; + +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; }; + +exports.default = reducer; +exports.handleWsMsg = handleWsMsg; +exports.update = update; +exports.fetchData = fetchData; +exports.receiveData = receiveData; +exports.updateSettings = updateSettings; + +var _utils = require('../utils'); + +var _websocket = require('./websocket'); + +var websocketActions = _interopRequireWildcard(_websocket); + +var _msgQueue = require('./msgQueue'); + +var msgQueueActions = _interopRequireWildcard(_msgQueue); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var MSG_TYPE = exports.MSG_TYPE = 'UPDATE_SETTINGS'; +var DATA_URL = exports.DATA_URL = '/settings'; + +var RECEIVE = exports.RECEIVE = 'RECEIVE'; +var UPDATE = exports.UPDATE = 'UPDATE'; +var REQUEST_UPDATE = exports.REQUEST_UPDATE = 'REQUEST_UPDATE'; +var UNKNOWN_CMD = exports.UNKNOWN_CMD = 'SETTINGS_UNKNOWN_CMD'; + +var defaultState = {}; + +function reducer() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + case RECEIVE: + return action.settings; + + case UPDATE: + return _extends({}, state, action.settings); + + default: + return state; + } +} + +/** + * @public msgQueue + */ +function handleWsMsg(msg) { + switch (msg.cmd) { + + case websocketActions.CMD_UPDATE: + return updateSettings(msg.data); + + default: + console.error('unknown settings update', msg); + return { type: UNKNOWN_CMD, msg: msg }; + } +} + +/** + * @public + */ +function update(settings) { + _utils.fetchApi.put('/settings', settings); + return { type: REQUEST_UPDATE }; +} + +/** + * @public websocket + */ +function fetchData() { + return msgQueueActions.fetchData(MSG_TYPE); +} + +/** + * @public msgQueue + */ +function receiveData(settings) { + return { type: RECEIVE, settings: settings }; +} + +/** + * @private + */ +function updateSettings(settings) { + return { type: UPDATE, settings: settings }; +} + +},{"../utils":63,"./msgQueue":52,"./websocket":60}],54:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SET_CONTENT_VIEW_DESCRIPTION = exports.SET_SHOW_FULL_CONTENT = exports.UPLOAD_CONTENT = exports.UPDATE_EDIT = exports.START_EDIT = exports.SET_TAB = exports.DISPLAY_LARGE = exports.SET_CONTENT_VIEW = undefined; + +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; }; + +exports.default = reducer; +exports.setContentView = setContentView; +exports.displayLarge = displayLarge; +exports.selectTab = selectTab; +exports.startEdit = startEdit; +exports.updateEdit = updateEdit; +exports.setContentViewDescription = setContentViewDescription; +exports.setShowFullContent = setShowFullContent; +exports.updateEdit = updateEdit; +exports.stopEdit = stopEdit; + +var _flows = require('../flows'); + +var flowsActions = _interopRequireWildcard(_flows); + +var _utils = require('../../utils'); + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var SET_CONTENT_VIEW = exports.SET_CONTENT_VIEW = 'UI_FLOWVIEW_SET_CONTENT_VIEW', + DISPLAY_LARGE = exports.DISPLAY_LARGE = 'UI_FLOWVIEW_DISPLAY_LARGE', + SET_TAB = exports.SET_TAB = "UI_FLOWVIEW_SET_TAB", + START_EDIT = exports.START_EDIT = 'UI_FLOWVIEW_START_EDIT', + UPDATE_EDIT = exports.UPDATE_EDIT = 'UI_FLOWVIEW_UPDATE_EDIT', + UPLOAD_CONTENT = exports.UPLOAD_CONTENT = 'UI_FLOWVIEW_UPLOAD_CONTENT', + SET_SHOW_FULL_CONTENT = exports.SET_SHOW_FULL_CONTENT = 'UI_SET_SHOW_FULL_CONTENT', + SET_CONTENT_VIEW_DESCRIPTION = exports.SET_CONTENT_VIEW_DESCRIPTION = "UI_SET_CONTENT_VIEW_DESCRIPTION"; + +var defaultState = { + displayLarge: false, + contentViewDescription: '', + showFullContent: false, + modifiedFlow: false, + contentView: 'Auto', + tab: 'request' +}; + +function reducer() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + var wasInEditMode = !!state.modifiedFlow; + switch (action.type) { + + case START_EDIT: + return _extends({}, state, { + modifiedFlow: action.flow, + contentView: 'Edit', + showFullContent: true + }); + + case UPDATE_EDIT: + return _extends({}, state, { + modifiedFlow: _lodash2.default.merge({}, state.modifiedFlow, action.update) + }); + + case flowsActions.SELECT: + return _extends({}, state, { + modifiedFlow: false, + displayLarge: false, + contentView: wasInEditMode ? 'Auto' : state.contentView, + viewDescription: '', + showFullContent: false + }); + + case flowsActions.UPDATE: + // There is no explicit "stop edit" event. + // We stop editing when we receive an update for + // the currently edited flow from the server + if (action.item.id === state.modifiedFlow.id) { + return _extends({}, state, { + modifiedFlow: false, + displayLarge: false, + contentView: wasInEditMode ? 'Auto' : state.contentView, + viewDescription: '', + showFullContent: false + }); + } else { + return state; + } + + case SET_CONTENT_VIEW_DESCRIPTION: + return _extends({}, state, { + viewDescription: action.description + }); + + case SET_SHOW_FULL_CONTENT: + return _extends({}, state, { + showFullContent: action.show + }); + + case SET_TAB: + return _extends({}, state, { + tab: action.tab, + displayLarge: false, + showFullContent: false + }); + + case SET_CONTENT_VIEW: + return _extends({}, state, { + contentView: action.contentView, + showFullContent: action.contentView == 'Edit' + }); + + case DISPLAY_LARGE: + return _extends({}, state, { + displayLarge: true + }); + default: + return state; + } +} + +function setContentView(contentView) { + return { type: SET_CONTENT_VIEW, contentView: contentView }; +} + +function displayLarge() { + return { type: DISPLAY_LARGE }; +} + +function selectTab(tab) { + return { type: SET_TAB, tab: tab }; +} + +function startEdit(flow) { + return { type: START_EDIT, flow: flow }; +} + +function updateEdit(update) { + return { type: UPDATE_EDIT, update: update }; +} + +function setContentViewDescription(description) { + return { type: SET_CONTENT_VIEW_DESCRIPTION, description: description }; +} + +function setShowFullContent(show) { + return { type: SET_SHOW_FULL_CONTENT, show: show }; +} + +function updateEdit(update) { + return { type: UPDATE_EDIT, update: update }; +} + +function stopEdit(flow, modifiedFlow) { + var diff = (0, _utils.getDiff)(flow, modifiedFlow); + return flowsActions.update(flow, diff); +} + +},{"../../utils":63,"../flows":50,"lodash":"lodash"}],55:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SET_ACTIVE_MENU = undefined; + +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; }; + +exports.default = reducer; +exports.setActiveMenu = setActiveMenu; + +var _flows = require('../flows'); + +var flowsActions = _interopRequireWildcard(_flows); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var SET_ACTIVE_MENU = exports.SET_ACTIVE_MENU = 'UI_SET_ACTIVE_MENU'; + +var defaultState = { + activeMenu: 'Start', + isFlowSelected: false +}; + +function reducer() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + case SET_ACTIVE_MENU: + return _extends({}, state, { + activeMenu: action.activeMenu + }); + + case flowsActions.SELECT: + // First Select + if (action.flowIds.length && !state.isFlowSelected) { + return _extends({}, state, { + activeMenu: 'Flow', + isFlowSelected: true + }); + } + + // Deselect + if (!action.flowIds.length && state.isFlowSelected) { + var activeMenu = state.activeMenu; + if (activeMenu == 'Flow') { + activeMenu = 'Start'; + } + return _extends({}, state, { + activeMenu: activeMenu, + isFlowSelected: false + }); + } + return state; + default: + return state; + } +} + +function setActiveMenu(activeMenu) { + return { type: SET_ACTIVE_MENU, activeMenu: activeMenu }; +} + +},{"../flows":50}],56:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _redux = require('redux'); + +var _flow = require('./flow'); + +var _flow2 = _interopRequireDefault(_flow); + +var _header = require('./header'); + +var _header2 = _interopRequireDefault(_header); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = (0, _redux.combineReducers)({ + flow: _flow2.default, + header: _header2.default +}); + +},{"./flow":54,"./header":55,"redux":"redux"}],57:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.onKeyDown = onKeyDown; + +var _utils = require('../../utils'); + +var _flowView = require('../flowView'); + +var _flow = require('./flow'); + +var _flows = require('../flows'); + +var flowsActions = _interopRequireWildcard(_flows); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function onKeyDown(e) { + console.debug("onKeyDown", e); + if (e.ctrlKey) { + return function () {}; + } + var key = e.keyCode; + var shiftKey = e.shiftKey; + e.preventDefault(); + return function (dispatch, getState) { + + var flow = getState().flows.byId[getState().flows.selected[0]]; + + switch (key) { + case _utils.Key.K: + case _utils.Key.UP: + dispatch((0, _flowView.selectRelative)(-1)); + break; + + case _utils.Key.J: + case _utils.Key.DOWN: + dispatch((0, _flowView.selectRelative)(+1)); + break; + + case _utils.Key.SPACE: + case _utils.Key.PAGE_DOWN: + dispatch((0, _flowView.selectRelative)(+10)); + break; + + case _utils.Key.PAGE_UP: + dispatch((0, _flowView.selectRelative)(-10)); + break; + + case _utils.Key.END: + dispatch((0, _flowView.selectRelative)(+1e10)); + break; + + case _utils.Key.HOME: + dispatch((0, _flowView.selectRelative)(-1e10)); + break; + + case _utils.Key.ESC: + dispatch(flowsActions.select(null)); + break; + + case _utils.Key.LEFT: + { + if (!flow) break; + var tabs = ['request', 'response', 'error'].filter(function (k) { + return flow[k]; + }).concat(['details']), + currentTab = getState().ui.flow.tab, + nextTab = tabs[(tabs.indexOf(currentTab) - 1 + tabs.length) % tabs.length]; + dispatch((0, _flow.selectTab)(nextTab)); + break; + } + + case _utils.Key.TAB: + case _utils.Key.RIGHT: + { + if (!flow) break; + var _tabs = ['request', 'response', 'error'].filter(function (k) { + return flow[k]; + }).concat(['details']), + _currentTab = getState().ui.flow.tab, + _nextTab = _tabs[(_tabs.indexOf(_currentTab) + 1) % _tabs.length]; + dispatch((0, _flow.selectTab)(_nextTab)); + break; + } + + case _utils.Key.C: + if (shiftKey) { + dispatch(flowsActions.clear()); + } + break; + + case _utils.Key.D: + { + if (!flow) { + return; + } + if (shiftKey) { + dispatch(flowsActions.duplicate(flow)); + } else { + dispatch(flowsActions.remove(flow)); + } + break; + } + + case _utils.Key.A: + { + if (shiftKey) { + dispatch(flowsActions.acceptAll()); + } else if (flow && flow.intercepted) { + dispatch(flowsActions.accept(flow)); + } + break; + } + + case _utils.Key.R: + { + if (!shiftKey && flow) { + dispatch(flowsActions.replay(flow)); + } + break; + } + + case _utils.Key.V: + { + if (!shiftKey && flow && flow.modified) { + dispatch(flowsActions.revert(flow)); + } + break; + } + + default: + return; + } + }; +} + +},{"../../utils":63,"../flowView":49,"../flows":50,"./flow":54}],58:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RECEIVE = exports.REMOVE = exports.UPDATE = exports.ADD = undefined; + +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; }; + +exports.default = reduce; +exports.add = add; +exports.update = update; +exports.remove = remove; +exports.receive = receive; + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +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 ADD = exports.ADD = 'LIST_ADD'; +var UPDATE = exports.UPDATE = 'LIST_UPDATE'; +var REMOVE = exports.REMOVE = 'LIST_REMOVE'; +var RECEIVE = exports.RECEIVE = 'LIST_RECEIVE'; + +var defaultState = { + data: [], + byId: {}, + indexOf: {} +}; + +function reduce() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + case ADD: + return _extends({}, state, { + data: [].concat(_toConsumableArray(state.data), [action.item]), + byId: _extends({}, state.byId, _defineProperty({}, action.item.id, action.item)), + indexOf: _extends({}, state.indexOf, _defineProperty({}, action.item.id, state.data.length)) + }); + + case UPDATE: + { + var index = state.indexOf[action.item.id]; + + if (index == null) { + return state; + } + + var data = [].concat(_toConsumableArray(state.data)); + + data[index] = action.item; + + return _extends({}, state, { + data: data, + byId: _extends({}, state.byId, _defineProperty({}, action.item.id, action.item)) + }); + } + + case REMOVE: + { + var _index = state.indexOf[action.id]; + + if (_index == null) { + return state; + } + + var _data = [].concat(_toConsumableArray(state.data)); + var indexOf = _extends({}, state.indexOf, _defineProperty({}, action.id, null)); + + _data.splice(_index, 1); + for (var i = _data.length - 1; i >= _index; i--) { + indexOf[_data[i].id] = i; + } + + return _extends({}, state, { + data: _data, + indexOf: indexOf, + byId: _extends({}, state.byId, _defineProperty({}, action.id, null)) + }); + } + + case RECEIVE: + return _extends({}, state, { + data: action.list, + byId: _lodash2.default.fromPairs(action.list.map(function (item) { + return [item.id, item]; + })), + indexOf: _lodash2.default.fromPairs(action.list.map(function (item, index) { + return [item.id, index]; + })) + }); + + default: + return state; + } +} + +/** + * @public + */ +function add(item) { + return { type: ADD, item: item }; +} + +/** + * @public + */ +function update(item) { + return { type: UPDATE, item: item }; +} + +/** + * @public + */ +function remove(id) { + return { type: REMOVE, id: id }; +} + +/** + * @public + */ +function receive(list) { + return { type: RECEIVE, list: list }; +} + +},{"lodash":"lodash"}],59:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.RECEIVE = exports.REMOVE = exports.UPDATE = exports.ADD = exports.UPDATE_SORT = exports.UPDATE_FILTER = undefined; + +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; }; + +exports.default = reduce; +exports.updateFilter = updateFilter; +exports.updateSort = updateSort; +exports.add = add; +exports.update = update; +exports.remove = remove; +exports.receive = receive; + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +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 UPDATE_FILTER = exports.UPDATE_FILTER = 'VIEW_UPDATE_FILTER'; +var UPDATE_SORT = exports.UPDATE_SORT = 'VIEW_UPDATE_SORT'; +var ADD = exports.ADD = 'VIEW_ADD'; +var UPDATE = exports.UPDATE = 'VIEW_UPDATE'; +var REMOVE = exports.REMOVE = 'VIEW_REMOVE'; +var RECEIVE = exports.RECEIVE = 'VIEW_RECEIVE'; + +var defaultState = { + data: [], + indexOf: {} +}; + +function reduce() { + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + case UPDATE_FILTER: + { + var data = action.list.filter(action.filter).sort(action.sort); + return _extends({}, state, { + data: data, + indexOf: _lodash2.default.fromPairs(data.map(function (item, index) { + return [item.id, index]; + })) + }); + } + + case UPDATE_SORT: + { + var _data = [].concat(_toConsumableArray(state.data)).sort(action.sort); + return _extends({}, state, { + data: _data, + indexOf: _lodash2.default.fromPairs(_data.map(function (item, index) { + return [item.id, index]; + })) + }); + } + + case ADD: + if (state.indexOf[action.item.id] != null || !action.filter(action.item)) { + return state; + } + return _extends({}, state, sortedInsert(state, action.item, action.sort)); + + case REMOVE: + if (state.indexOf[action.id] == null) { + return state; + } + return _extends({}, state, sortedRemove(state, action.id)); + + case UPDATE: + if (state.indexOf[action.item.id] == null) { + return; + } + var nextState = _extends({}, state, sortedRemove(state, action.item.id)); + if (!action.filter(action.item)) { + return nextState; + } + return _extends({}, nextState, sortedInsert(nextState, action.item, action.sort)); + + case RECEIVE: + { + var _data2 = action.list.filter(action.filter).sort(action.sort); + return _extends({}, state, { + data: _data2, + indexOf: _lodash2.default.fromPairs(_data2.map(function (item, index) { + return [item.id, index]; + })) + }); + } + + default: + return state; + } +} + +function updateFilter(list) { + var filter = arguments.length <= 1 || arguments[1] === undefined ? defaultFilter : arguments[1]; + var sort = arguments.length <= 2 || arguments[2] === undefined ? defaultSort : arguments[2]; + + return { type: UPDATE_FILTER, list: list, filter: filter, sort: sort }; +} + +function updateSort() { + var sort = arguments.length <= 0 || arguments[0] === undefined ? defaultSort : arguments[0]; + + return { type: UPDATE_SORT, sort: sort }; +} + +function add(item) { + var filter = arguments.length <= 1 || arguments[1] === undefined ? defaultFilter : arguments[1]; + var sort = arguments.length <= 2 || arguments[2] === undefined ? defaultSort : arguments[2]; + + return { type: ADD, item: item, filter: filter, sort: sort }; +} + +function update(item) { + var filter = arguments.length <= 1 || arguments[1] === undefined ? defaultFilter : arguments[1]; + var sort = arguments.length <= 2 || arguments[2] === undefined ? defaultSort : arguments[2]; + + return { type: UPDATE, item: item, filter: filter, sort: sort }; +} + +function remove(id) { + return { type: REMOVE, id: id }; +} + +function receive(list) { + var filter = arguments.length <= 1 || arguments[1] === undefined ? defaultFilter : arguments[1]; + var sort = arguments.length <= 2 || arguments[2] === undefined ? defaultSort : arguments[2]; + + return { type: RECEIVE, list: list, filter: filter, sort: sort }; +} + +function sortedInsert(state, item, sort) { + var index = sortedIndex(state.data, item, sort); + var data = [].concat(_toConsumableArray(state.data)); + var indexOf = _extends({}, state.indexOf); + + data.splice(index, 0, item); + for (var i = data.length - 1; i >= index; i--) { + indexOf[data[i].id] = i; + } + + return { data: data, indexOf: indexOf }; +} + +function sortedRemove(state, id) { + var index = state.indexOf[id]; + var data = [].concat(_toConsumableArray(state.data)); + var indexOf = _extends({}, state.indexOf, _defineProperty({}, id, null)); + + data.splice(index, 1); + for (var i = data.length - 1; i >= index; i--) { + indexOf[data[i].id] = i; + } + + return { data: data, indexOf: indexOf }; +} + +function sortedIndex(list, item, sort) { + var low = 0; + var high = list.length; + + while (low < high) { + var middle = low + high >>> 1; + if (sort(item, list[middle]) >= 0) { + low = middle + 1; + } else { + high = middle; + } + } + + return low; +} + +function defaultFilter() { + return true; +} + +function defaultSort(a, b) { + return 0; +} + +},{"lodash":"lodash"}],60:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.MESSAGE = exports.ERROR = exports.DISCONNECTED = exports.DISCONNECT = exports.CONNECTED = exports.CONNECT = exports.SYM_SOCKET = exports.CMD_RESET = exports.CMD_REMOVE = exports.CMD_UPDATE = exports.CMD_ADD = undefined; + +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; }; + +exports.default = reduce; +exports.connect = connect; +exports.disconnect = disconnect; +exports.onConnect = onConnect; +exports.onMessage = onMessage; +exports.onDisconnect = onDisconnect; +exports.onError = onError; + +var _actions = require('../actions.js'); + +var _dispatcher = require('../dispatcher.js'); + +var _msgQueue = require('./msgQueue'); + +var msgQueueActions = _interopRequireWildcard(_msgQueue); + +var _eventLog = require('./eventLog'); + +var eventLogActions = _interopRequireWildcard(_eventLog); + +var _flows = require('./flows'); + +var flowsActions = _interopRequireWildcard(_flows); + +var _settings = require('./settings'); + +var settingsActions = _interopRequireWildcard(_settings); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +var CMD_ADD = exports.CMD_ADD = 'add'; +var CMD_UPDATE = exports.CMD_UPDATE = 'update'; +var CMD_REMOVE = exports.CMD_REMOVE = 'remove'; +var CMD_RESET = exports.CMD_RESET = 'reset'; + +var SYM_SOCKET = exports.SYM_SOCKET = Symbol('WEBSOCKET_SYM_SOCKET'); + +var CONNECT = exports.CONNECT = 'WEBSOCKET_CONNECT'; +var CONNECTED = exports.CONNECTED = 'WEBSOCKET_CONNECTED'; +var DISCONNECT = exports.DISCONNECT = 'WEBSOCKET_DISCONNECT'; +var DISCONNECTED = exports.DISCONNECTED = 'WEBSOCKET_DISCONNECTED'; +var ERROR = exports.ERROR = 'WEBSOCKET_ERROR'; +var MESSAGE = exports.MESSAGE = 'WEBSOCKET_MESSAGE'; + +/* we may want to have an error message attribute here at some point */ +var defaultState = { connected: false, socket: null }; + +function reduce() { + var _extends3; + + var state = arguments.length <= 0 || arguments[0] === undefined ? defaultState : arguments[0]; + var action = arguments[1]; + + switch (action.type) { + + case CONNECT: + return _extends({}, state, _defineProperty({}, SYM_SOCKET, action.socket)); + + case CONNECTED: + return _extends({}, state, { connected: true }); + + case DISCONNECT: + return _extends({}, state, { connected: false }); + + case DISCONNECTED: + return _extends({}, state, (_extends3 = {}, _defineProperty(_extends3, SYM_SOCKET, null), _defineProperty(_extends3, 'connected', false), _extends3)); + + default: + return state; + } +} + +function connect() { + return function (dispatch) { + var socket = new WebSocket(location.origin.replace('http', 'ws') + '/updates'); + + socket.addEventListener('open', function () { + return dispatch(onConnect()); + }); + socket.addEventListener('close', function () { + return dispatch(onDisconnect()); + }); + socket.addEventListener('message', function (msg) { + return dispatch(onMessage(JSON.parse(msg.data))); + }); + socket.addEventListener('error', function (error) { + return dispatch(onError(error)); + }); + + dispatch({ type: CONNECT, socket: socket }); + }; +} + +function disconnect() { + return function (dispatch, getState) { + getState().settings[SYM_SOCKET].close(); + dispatch({ type: DISCONNECT }); + }; +} + +function onConnect() { + // workaround to make sure that our state is already available. + return function (dispatch) { + dispatch({ type: CONNECTED }); + dispatch(settingsActions.fetchData()); + dispatch(flowsActions.fetchFlows()); + dispatch(eventLogActions.fetchData()); + }; +} + +function onMessage(msg) { + return msgQueueActions.handleWsMsg(msg); +} + +function onDisconnect() { + return function (dispatch) { + dispatch(eventLogActions.add('WebSocket connection closed.')); + dispatch({ type: DISCONNECTED }); + }; +} + +function onError(error) { + // @todo let event log subscribe WebSocketActions.ERROR + return function (dispatch) { + dispatch(eventLogActions.add('WebSocket connection error.')); + dispatch({ type: ERROR, error: error }); + }; +} + +},{"../actions.js":2,"../dispatcher.js":46,"./eventLog":48,"./flows":50,"./msgQueue":52,"./settings":53}],61:[function(require,module,exports){ +"use strict"; + +module.exports = function () { + "use strict"; + + /* + * Generated by PEG.js 0.9.0. + * + * http://pegjs.org/ + */ + + function peg$subclass(child, parent) { + function ctor() { + this.constructor = child; + } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + } + + function peg$SyntaxError(message, expected, found, location) { + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; + + if (typeof Error.captureStackTrace === "function") { + Error.captureStackTrace(this, peg$SyntaxError); + } + } + + peg$subclass(peg$SyntaxError, Error); + + function peg$parse(input) { + var options = arguments.length > 1 ? arguments[1] : {}, + parser = this, + peg$FAILED = {}, + peg$startRuleFunctions = { start: peg$parsestart }, + peg$startRuleFunction = peg$parsestart, + peg$c0 = { type: "other", description: "filter expression" }, + peg$c1 = function peg$c1(orExpr) { + return orExpr; + }, + peg$c2 = { type: "other", description: "whitespace" }, + peg$c3 = /^[ \t\n\r]/, + peg$c4 = { type: "class", value: "[ \\t\\n\\r]", description: "[ \\t\\n\\r]" }, + peg$c5 = { type: "other", description: "control character" }, + peg$c6 = /^[|&!()~"]/, + peg$c7 = { type: "class", value: "[|&!()~\"]", description: "[|&!()~\"]" }, + peg$c8 = { type: "other", description: "optional whitespace" }, + peg$c9 = "|", + peg$c10 = { type: "literal", value: "|", description: "\"|\"" }, + peg$c11 = function peg$c11(first, second) { + return or(first, second); + }, + peg$c12 = "&", + peg$c13 = { type: "literal", value: "&", description: "\"&\"" }, + peg$c14 = function peg$c14(first, second) { + return and(first, second); + }, + peg$c15 = "!", + peg$c16 = { type: "literal", value: "!", description: "\"!\"" }, + peg$c17 = function peg$c17(expr) { + return not(expr); + }, + peg$c18 = "(", + peg$c19 = { type: "literal", value: "(", description: "\"(\"" }, + peg$c20 = ")", + peg$c21 = { type: "literal", value: ")", description: "\")\"" }, + peg$c22 = function peg$c22(expr) { + return binding(expr); + }, + peg$c23 = "~a", + peg$c24 = { type: "literal", value: "~a", description: "\"~a\"" }, + peg$c25 = function peg$c25() { + return assetFilter; + }, + peg$c26 = "~e", + peg$c27 = { type: "literal", value: "~e", description: "\"~e\"" }, + peg$c28 = function peg$c28() { + return errorFilter; + }, + peg$c29 = "~q", + peg$c30 = { type: "literal", value: "~q", description: "\"~q\"" }, + peg$c31 = function peg$c31() { + return noResponseFilter; + }, + peg$c32 = "~s", + peg$c33 = { type: "literal", value: "~s", description: "\"~s\"" }, + peg$c34 = function peg$c34() { + return responseFilter; + }, + peg$c35 = "true", + peg$c36 = { type: "literal", value: "true", description: "\"true\"" }, + peg$c37 = function peg$c37() { + return trueFilter; + }, + peg$c38 = "false", + peg$c39 = { type: "literal", value: "false", description: "\"false\"" }, + peg$c40 = function peg$c40() { + return falseFilter; + }, + peg$c41 = "~c", + peg$c42 = { type: "literal", value: "~c", description: "\"~c\"" }, + peg$c43 = function peg$c43(s) { + return responseCode(s); + }, + peg$c44 = "~d", + peg$c45 = { type: "literal", value: "~d", description: "\"~d\"" }, + peg$c46 = function peg$c46(s) { + return domain(s); + }, + peg$c47 = "~h", + peg$c48 = { type: "literal", value: "~h", description: "\"~h\"" }, + peg$c49 = function peg$c49(s) { + return header(s); + }, + peg$c50 = "~hq", + peg$c51 = { type: "literal", value: "~hq", description: "\"~hq\"" }, + peg$c52 = function peg$c52(s) { + return requestHeader(s); + }, + peg$c53 = "~hs", + peg$c54 = { type: "literal", value: "~hs", description: "\"~hs\"" }, + peg$c55 = function peg$c55(s) { + return responseHeader(s); + }, + peg$c56 = "~m", + peg$c57 = { type: "literal", value: "~m", description: "\"~m\"" }, + peg$c58 = function peg$c58(s) { + return method(s); + }, + peg$c59 = "~t", + peg$c60 = { type: "literal", value: "~t", description: "\"~t\"" }, + peg$c61 = function peg$c61(s) { + return contentType(s); + }, + peg$c62 = "~tq", + peg$c63 = { type: "literal", value: "~tq", description: "\"~tq\"" }, + peg$c64 = function peg$c64(s) { + return requestContentType(s); + }, + peg$c65 = "~ts", + peg$c66 = { type: "literal", value: "~ts", description: "\"~ts\"" }, + peg$c67 = function peg$c67(s) { + return responseContentType(s); + }, + peg$c68 = "~u", + peg$c69 = { type: "literal", value: "~u", description: "\"~u\"" }, + peg$c70 = function peg$c70(s) { + return url(s); + }, + peg$c71 = { type: "other", description: "integer" }, + peg$c72 = /^['"]/, + peg$c73 = { type: "class", value: "['\"]", description: "['\"]" }, + peg$c74 = /^[0-9]/, + peg$c75 = { type: "class", value: "[0-9]", description: "[0-9]" }, + peg$c76 = function peg$c76(digits) { + return parseInt(digits.join(""), 10); + }, + peg$c77 = { type: "other", description: "string" }, + peg$c78 = "\"", + peg$c79 = { type: "literal", value: "\"", description: "\"\\\"\"" }, + peg$c80 = function peg$c80(chars) { + return chars.join(""); + }, + peg$c81 = "'", + peg$c82 = { type: "literal", value: "'", description: "\"'\"" }, + peg$c83 = /^["\\]/, + peg$c84 = { type: "class", value: "[\"\\\\]", description: "[\"\\\\]" }, + peg$c85 = { type: "any", description: "any character" }, + peg$c86 = function peg$c86(char) { + return char; + }, + peg$c87 = "\\", + peg$c88 = { type: "literal", value: "\\", description: "\"\\\\\"" }, + peg$c89 = /^['\\]/, + peg$c90 = { type: "class", value: "['\\\\]", description: "['\\\\]" }, + peg$c91 = /^['"\\]/, + peg$c92 = { type: "class", value: "['\"\\\\]", description: "['\"\\\\]" }, + peg$c93 = "n", + peg$c94 = { type: "literal", value: "n", description: "\"n\"" }, + peg$c95 = function peg$c95() { + return "\n"; + }, + peg$c96 = "r", + peg$c97 = { type: "literal", value: "r", description: "\"r\"" }, + peg$c98 = function peg$c98() { + return "\r"; + }, + peg$c99 = "t", + peg$c100 = { type: "literal", value: "t", description: "\"t\"" }, + peg$c101 = function peg$c101() { + return "\t"; + }, + peg$currPos = 0, + peg$savedPos = 0, + peg$posDetailsCache = [{ line: 1, column: 1, seenCR: false }], + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$silentFails = 0, + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$savedPos, peg$currPos); + } + + function location() { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description) { + throw peg$buildException(null, [{ type: "other", description: description }], input.substring(peg$savedPos, peg$currPos), peg$computeLocation(peg$savedPos, peg$currPos)); + } + + function error(message) { + throw peg$buildException(message, null, input.substring(peg$savedPos, peg$currPos), peg$computeLocation(peg$savedPos, peg$currPos)); + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos], + p, + ch; + + if (details) { + return details; + } else { + p = pos - 1; + while (!peg$posDetailsCache[p]) { + p--; + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column, + seenCR: details.seenCR + }; + + while (p < pos) { + ch = input.charAt(p); + if (ch === "\n") { + if (!details.seenCR) { + details.line++; + } + details.column = 1; + details.seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + details.line++; + details.column = 1; + details.seenCR = true; + } else { + details.column++; + details.seenCR = false; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + return details; + } + } + + function peg$computeLocation(startPos, endPos) { + var startPosDetails = peg$computePosDetails(startPos), + endPosDetails = peg$computePosDetails(endPos); + + return { + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { + return; + } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildException(message, expected, found, location) { + function cleanupExpected(expected) { + var i = 1; + + expected.sort(function (a, b) { + if (a.description < b.description) { + return -1; + } else if (a.description > b.description) { + return 1; + } else { + return 0; + } + }); + + while (i < expected.length) { + if (expected[i - 1] === expected[i]) { + expected.splice(i, 1); + } else { + i++; + } + } + } + + function buildMessage(expected, found) { + function stringEscape(s) { + function hex(ch) { + return ch.charCodeAt(0).toString(16).toUpperCase(); + } + + return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\x08/g, '\\b').replace(/\t/g, '\\t').replace(/\n/g, '\\n').replace(/\f/g, '\\f').replace(/\r/g, '\\r').replace(/[\x00-\x07\x0B\x0E\x0F]/g, function (ch) { + return '\\x0' + hex(ch); + }).replace(/[\x10-\x1F\x80-\xFF]/g, function (ch) { + return '\\x' + hex(ch); + }).replace(/[\u0100-\u0FFF]/g, function (ch) { + return "\\u0" + hex(ch); + }).replace(/[\u1000-\uFFFF]/g, function (ch) { + return "\\u" + hex(ch); + }); + } + + var expectedDescs = new Array(expected.length), + expectedDesc, + foundDesc, + i; + + for (i = 0; i < expected.length; i++) { + expectedDescs[i] = expected[i].description; + } + + expectedDesc = expected.length > 1 ? expectedDescs.slice(0, -1).join(", ") + " or " + expectedDescs[expected.length - 1] : expectedDescs[0]; + + foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; + + return "Expected " + expectedDesc + " but " + foundDesc + " found."; + } + + if (expected !== null) { + cleanupExpected(expected); + } + + return new peg$SyntaxError(message !== null ? message : buildMessage(expected, found), expected, found, location); + } + + function peg$parsestart() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse__(); + if (s1 !== peg$FAILED) { + s2 = peg$parseOrExpr(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c1(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c0); + } + } + + return s0; + } + + function peg$parsews() { + var s0, s1; + + peg$silentFails++; + if (peg$c3.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c4); + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c2); + } + } + + return s0; + } + + function peg$parsecc() { + var s0, s1; + + peg$silentFails++; + if (peg$c6.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c7); + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c5); + } + } + + return s0; + } + + function peg$parse__() { + var s0, s1; + + peg$silentFails++; + s0 = []; + s1 = peg$parsews(); + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = peg$parsews(); + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c8); + } + } + + return s0; + } + + function peg$parseOrExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseAndExpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 124) { + s3 = peg$c9; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c10); + } + } + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + s5 = peg$parseOrExpr(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c11(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parseAndExpr(); + } + + return s0; + } + + function peg$parseAndExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseNotExpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 38) { + s3 = peg$c12; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c13); + } + } + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + s5 = peg$parseAndExpr(); + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c14(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseNotExpr(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseAndExpr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c14(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parseNotExpr(); + } + } + + return s0; + } + + function peg$parseNotExpr() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 33) { + s1 = peg$c15; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c16); + } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + s3 = peg$parseNotExpr(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c17(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parseBindingExpr(); + } + + return s0; + } + + function peg$parseBindingExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 40) { + s1 = peg$c18; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c19); + } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + s3 = peg$parseOrExpr(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c20; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c21); + } + } + if (s5 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c22(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parseExpr(); + } + + return s0; + } + + function peg$parseExpr() { + var s0; + + s0 = peg$parseNullaryExpr(); + if (s0 === peg$FAILED) { + s0 = peg$parseUnaryExpr(); + } + + return s0; + } + + function peg$parseNullaryExpr() { + var s0, s1; + + s0 = peg$parseBooleanLiteral(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c23) { + s1 = peg$c23; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c24); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c25(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c26) { + s1 = peg$c26; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c27); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c28(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c29) { + s1 = peg$c29; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c30); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c31(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c32) { + s1 = peg$c32; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c33); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c34(); + } + s0 = s1; + } + } + } + } + + return s0; + } + + function peg$parseBooleanLiteral() { + var s0, s1; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c35) { + s1 = peg$c35; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c36); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c37(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 5) === peg$c38) { + s1 = peg$c38; + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c39); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c40(); + } + s0 = s1; + } + + return s0; + } + + function peg$parseUnaryExpr() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c41) { + s1 = peg$c41; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c42); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseIntegerLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c43(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c44) { + s1 = peg$c44; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c45); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c46(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c47) { + s1 = peg$c47; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c48); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c49(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c50) { + s1 = peg$c50; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c51); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c52(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c53) { + s1 = peg$c53; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c54); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c55(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c56) { + s1 = peg$c56; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c57); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c58(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c59) { + s1 = peg$c59; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c60); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c61(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c62) { + s1 = peg$c62; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c63); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c64(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c65) { + s1 = peg$c65; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c66); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c67(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c68) { + s1 = peg$c68; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c69); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c70(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseStringLiteral(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c70(s1); + } + s0 = s1; + } + } + } + } + } + } + } + } + } + } + + return s0; + } + + function peg$parseIntegerLiteral() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + if (peg$c72.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c73); + } + } + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = []; + if (peg$c74.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c75); + } + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + if (peg$c74.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c75); + } + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + if (peg$c72.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c73); + } + } + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c76(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c71); + } + } + + return s0; + } + + function peg$parseStringLiteral() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c78; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c79); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseDoubleStringChar(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseDoubleStringChar(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c78; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c79); + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c80(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 39) { + s1 = peg$c81; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c82); + } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseSingleStringChar(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseSingleStringChar(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s3 = peg$c81; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c82); + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c80(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parsecc(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = void 0; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseUnquotedStringChar(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseUnquotedStringChar(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c80(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c77); + } + } + + return s0; + } + + function peg$parseDoubleStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + if (peg$c83.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c84); + } + } + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = void 0; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c85); + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c86(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c87; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c88); + } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseEscapeSequence(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c86(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parseSingleStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + if (peg$c89.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c90); + } + } + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = void 0; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c85); + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c86(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c87; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c88); + } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseEscapeSequence(); + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c86(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parseUnquotedStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parsews(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = void 0; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c85); + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c86(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseEscapeSequence() { + var s0, s1; + + if (peg$c91.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c92); + } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 110) { + s1 = peg$c93; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c94); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c95(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 114) { + s1 = peg$c96; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c97); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c98(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 116) { + s1 = peg$c99; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { + peg$fail(peg$c100); + } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c101(); + } + s0 = s1; + } + } + } + + return s0; + } + + var flowutils = require("../flow/utils.js"); + + function or(first, second) { + // Add explicit function names to ease debugging. + function orFilter() { + return first.apply(this, arguments) || second.apply(this, arguments); + } + orFilter.desc = first.desc + " or " + second.desc; + return orFilter; + } + function and(first, second) { + function andFilter() { + return first.apply(this, arguments) && second.apply(this, arguments); + } + andFilter.desc = first.desc + " and " + second.desc; + return andFilter; + } + function not(expr) { + function notFilter() { + return !expr.apply(this, arguments); + } + notFilter.desc = "not " + expr.desc; + return notFilter; + } + function binding(expr) { + function bindingFilter() { + return expr.apply(this, arguments); + } + bindingFilter.desc = "(" + expr.desc + ")"; + return bindingFilter; + } + function trueFilter(flow) { + return true; + } + trueFilter.desc = "true"; + function falseFilter(flow) { + return false; + } + falseFilter.desc = "false"; + + var ASSET_TYPES = [new RegExp("text/javascript"), new RegExp("application/x-javascript"), new RegExp("application/javascript"), new RegExp("text/css"), new RegExp("image/.*"), new RegExp("application/x-shockwave-flash")]; + function assetFilter(flow) { + if (flow.response) { + var ct = flowutils.ResponseUtils.getContentType(flow.response); + var i = ASSET_TYPES.length; + while (i--) { + if (ASSET_TYPES[i].test(ct)) { + return true; + } + } + } + return false; + } + assetFilter.desc = "is asset"; + function responseCode(code) { + function responseCodeFilter(flow) { + return flow.response && flow.response.status_code === code; + } + responseCodeFilter.desc = "resp. code is " + code; + return responseCodeFilter; + } + function domain(regex) { + regex = new RegExp(regex, "i"); + function domainFilter(flow) { + return flow.request && regex.test(flow.request.host); + } + domainFilter.desc = "domain matches " + regex; + return domainFilter; + } + function errorFilter(flow) { + return !!flow.error; + } + errorFilter.desc = "has error"; + function header(regex) { + regex = new RegExp(regex, "i"); + function headerFilter(flow) { + return flow.request && flowutils.RequestUtils.match_header(flow.request, regex) || flow.response && flowutils.ResponseUtils.match_header(flow.response, regex); + } + headerFilter.desc = "header matches " + regex; + return headerFilter; + } + function requestHeader(regex) { + regex = new RegExp(regex, "i"); + function requestHeaderFilter(flow) { + return flow.request && flowutils.RequestUtils.match_header(flow.request, regex); + } + requestHeaderFilter.desc = "req. header matches " + regex; + return requestHeaderFilter; + } + function responseHeader(regex) { + regex = new RegExp(regex, "i"); + function responseHeaderFilter(flow) { + return flow.response && flowutils.ResponseUtils.match_header(flow.response, regex); + } + responseHeaderFilter.desc = "resp. header matches " + regex; + return responseHeaderFilter; + } + function method(regex) { + regex = new RegExp(regex, "i"); + function methodFilter(flow) { + return flow.request && regex.test(flow.request.method); + } + methodFilter.desc = "method matches " + regex; + return methodFilter; + } + function noResponseFilter(flow) { + return flow.request && !flow.response; + } + noResponseFilter.desc = "has no response"; + function responseFilter(flow) { + return !!flow.response; + } + responseFilter.desc = "has response"; + + function contentType(regex) { + regex = new RegExp(regex, "i"); + function contentTypeFilter(flow) { + return flow.request && regex.test(flowutils.RequestUtils.getContentType(flow.request)) || flow.response && regex.test(flowutils.ResponseUtils.getContentType(flow.response)); + } + contentTypeFilter.desc = "content type matches " + regex; + return contentTypeFilter; + } + function requestContentType(regex) { + regex = new RegExp(regex, "i"); + function requestContentTypeFilter(flow) { + return flow.request && regex.test(flowutils.RequestUtils.getContentType(flow.request)); + } + requestContentTypeFilter.desc = "req. content type matches " + regex; + return requestContentTypeFilter; + } + function responseContentType(regex) { + regex = new RegExp(regex, "i"); + function responseContentTypeFilter(flow) { + return flow.response && regex.test(flowutils.ResponseUtils.getContentType(flow.response)); + } + responseContentTypeFilter.desc = "resp. content type matches " + regex; + return responseContentTypeFilter; + } + function url(regex) { + regex = new RegExp(regex, "i"); + function urlFilter(flow) { + return flow.request && regex.test(flowutils.RequestUtils.pretty_url(flow.request)); + } + urlFilter.desc = "url matches " + regex; + return urlFilter; + } + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail({ type: "end", description: "end of input" }); + } + + throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, peg$maxFailPos < input.length ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)); + } + } + + return { + SyntaxError: peg$SyntaxError, + parse: peg$parse + }; +}(); + +},{"../flow/utils.js":62}],62:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isValidHttpVersion = exports.parseUrl = exports.ResponseUtils = exports.RequestUtils = exports.MessageUtils = undefined; + +var _lodash = require("lodash"); + +var _lodash2 = _interopRequireDefault(_lodash); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var defaultPorts = { + "http": 80, + "https": 443 +}; + +var MessageUtils = exports.MessageUtils = { + getContentType: function getContentType(message) { + var ct = this.get_first_header(message, /^Content-Type$/i); + if (ct) { + return ct.split(";")[0].trim(); + } + }, + get_first_header: function get_first_header(message, regex) { + //FIXME: Cache Invalidation. + if (!message._headerLookups) Object.defineProperty(message, "_headerLookups", { + value: {}, + configurable: false, + enumerable: false, + writable: false + }); + if (!(regex in message._headerLookups)) { + var header; + for (var i = 0; i < message.headers.length; i++) { + if (!!message.headers[i][0].match(regex)) { + header = message.headers[i]; + break; + } + } + message._headerLookups[regex] = header ? header[1] : undefined; + } + return message._headerLookups[regex]; + }, + match_header: function match_header(message, regex) { + var headers = message.headers; + var i = headers.length; + while (i--) { + if (regex.test(headers[i].join(" "))) { + return headers[i]; + } + } + return false; + }, + getContentURL: function getContentURL(flow, message, view) { + if (message === flow.request) { + message = "request"; + } else if (message === flow.response) { + message = "response"; + } + return "/flows/" + flow.id + "/" + message + "/content" + (view ? "/" + view : ''); + } +}; + +var RequestUtils = exports.RequestUtils = _lodash2.default.extend(MessageUtils, { + pretty_host: function pretty_host(request) { + //FIXME: Add hostheader + return request.host; + }, + pretty_url: function pretty_url(request) { + var port = ""; + if (defaultPorts[request.scheme] !== request.port) { + port = ":" + request.port; + } + return request.scheme + "://" + this.pretty_host(request) + port + request.path; + } +}); + +var ResponseUtils = exports.ResponseUtils = _lodash2.default.extend(MessageUtils, {}); + +var parseUrl_regex = /^(?:(https?):\/\/)?([^\/:]+)?(?::(\d+))?(\/.*)?$/i; +var parseUrl = exports.parseUrl = function parseUrl(url) { + //there are many correct ways to parse a URL, + //however, a mitmproxy user may also wish to generate a not-so-correct URL. ;-) + var parts = parseUrl_regex.exec(url); + if (!parts) { + return false; + } + + var scheme = parts[1], + host = parts[2], + port = parseInt(parts[3]), + path = parts[4]; + if (scheme) { + port = port || defaultPorts[scheme]; + } + var ret = {}; + if (scheme) { + ret.scheme = scheme; + } + if (host) { + ret.host = host; + } + if (port) { + ret.port = port; + } + if (path) { + ret.path = path; + } + return ret; +}; + +var isValidHttpVersion_regex = /^HTTP\/\d+(\.\d+)*$/i; +var isValidHttpVersion = exports.isValidHttpVersion = function isValidHttpVersion(httpVersion) { + return isValidHttpVersion_regex.test(httpVersion); +}; + +},{"lodash":"lodash"}],63:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.pure = exports.formatTimeStamp = exports.formatTimeDelta = exports.formatSize = exports.Key = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; + +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; }; + +exports.reverseString = reverseString; +exports.fetchApi = fetchApi; +exports.getDiff = getDiff; + +var _lodash = require('lodash'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _shallowequal = require('shallowequal'); + +var _shallowequal2 = _interopRequireDefault(_shallowequal); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +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; } + +window._ = _lodash2.default; +window.React = _react2.default; + +var Key = exports.Key = { + UP: 38, + DOWN: 40, + PAGE_UP: 33, + PAGE_DOWN: 34, + HOME: 36, + END: 35, + LEFT: 37, + RIGHT: 39, + ENTER: 13, + ESC: 27, + TAB: 9, + SPACE: 32, + BACKSPACE: 8, + SHIFT: 16 +}; +// Add A-Z +for (var i = 65; i <= 90; i++) { + Key[String.fromCharCode(i)] = i; +} + +var formatSize = exports.formatSize = function formatSize(bytes) { + if (bytes === 0) return "0"; + var prefix = ["b", "kb", "mb", "gb", "tb"]; + for (var i = 0; i < prefix.length; i++) { + if (Math.pow(1024, i + 1) > bytes) { + break; + } + } + var precision; + if (bytes % Math.pow(1024, i) === 0) precision = 0;else precision = 1; + return (bytes / Math.pow(1024, i)).toFixed(precision) + prefix[i]; +}; + +var formatTimeDelta = exports.formatTimeDelta = function formatTimeDelta(milliseconds) { + var time = milliseconds; + var prefix = ["ms", "s", "min", "h"]; + var div = [1000, 60, 60]; + var i = 0; + while (Math.abs(time) >= div[i] && i < div.length) { + time = time / div[i]; + i++; + } + return Math.round(time) + prefix[i]; +}; + +var formatTimeStamp = exports.formatTimeStamp = function formatTimeStamp(seconds) { + var ts = new Date(seconds * 1000).toISOString(); + return ts.replace("T", " ").replace("Z", ""); +}; + +// At some places, we need to sort strings alphabetically descending, +// but we can only provide a key function. +// This beauty "reverses" a JS string. +var end = String.fromCharCode(0xffff); +function reverseString(s) { + return String.fromCharCode.apply(String, _lodash2.default.map(s.split(""), function (c) { + return 0xffff - c.charCodeAt(0); + })) + end; +} + +function getCookie(name) { + var r = document.cookie.match(new RegExp("\\b" + name + "=([^;]*)\\b")); + return r ? r[1] : undefined; +} +var xsrf = '_xsrf=' + getCookie("_xsrf"); + +function fetchApi(url) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + if (options.method && options.method !== "GET") { + if (url.indexOf("?") === -1) { + url += "?" + xsrf; + } else { + url += "&" + xsrf; + } + } + + return fetch(url, _extends({ + credentials: 'same-origin' + }, options)); +} + +fetchApi.put = function (url, json, options) { + return fetchApi(url, _extends({ + method: "PUT", + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(json) + }, options)); +}; + +function getDiff(obj1, obj2) { + var result = _extends({}, obj2); + for (var key in obj1) { + if (_lodash2.default.isEqual(obj2[key], obj1[key])) result[key] = undefined;else if (!(Array.isArray(obj2[key]) && Array.isArray(obj1[key])) && _typeof(obj2[key]) == 'object' && _typeof(obj1[key]) == 'object') result[key] = getDiff(obj1[key], obj2[key]); + } + return result; +} + +var pure = exports.pure = function pure(renderFn) { + var _class, _temp; + + return _temp = _class = function (_React$Component) { + _inherits(_class, _React$Component); + + function _class() { + _classCallCheck(this, _class); + + return _possibleConstructorReturn(this, Object.getPrototypeOf(_class).apply(this, arguments)); + } + + _createClass(_class, [{ + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate(nextProps) { + return !(0, _shallowequal2.default)(this.props, nextProps); + } + }, { + key: 'render', + value: function render() { + return renderFn(this.props); + } + }]); + + return _class; + }(_react2.default.Component), _class.displayName = renderFn.name, _temp; +}; + +},{"lodash":"lodash","react":"react","shallowequal":"shallowequal"}]},{},[3]) //# sourceMappingURL=app.js.map diff --git a/mitmproxy/web/static/vendor.js b/mitmproxy/web/static/vendor.js index 6ed8dacb2..7bdd0e3dd 100644 --- a/mitmproxy/web/static/vendor.js +++ b/mitmproxy/web/static/vendor.js @@ -1,779 +1,55157 @@ require=(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;o0&&"number"!=typeof e[0]))}function objEquiv(e,t,r){var n,i;if(isUndefinedOrNull(e)||isUndefinedOrNull(t))return!1;if(e.prototype!==t.prototype)return!1;if(isArguments(e))return!!isArguments(t)&&(e=pSlice.call(e),t=pSlice.call(t),deepEqual(e,t,r));if(isBuffer(e)){if(!isBuffer(t))return!1;if(e.length!==t.length)return!1;for(n=0;n=0;n--)if(u[n]!=o[n])return!1;for(n=u.length-1;n>=0;n--)if(i=u[n],!deepEqual(e[i],t[i],r))return!1;return typeof e==typeof t}var pSlice=Array.prototype.slice,objectKeys=require("./lib/keys.js"),isArguments=require("./lib/is_arguments.js"),deepEqual=module.exports=function(e,t,r){return r||(r={}),e===t||(e instanceof Date&&t instanceof Date?e.getTime()===t.getTime():!e||!t||"object"!=typeof e&&"object"!=typeof t?r.strict?e===t:e==t:objEquiv(e,t,r))}; +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE -},{"./lib/is_arguments.js":2,"./lib/keys.js":3}],2:[function(require,module,exports){ -function supported(t){return"[object Arguments]"==Object.prototype.toString.call(t)}function unsupported(t){return t&&"object"==typeof t&&"number"==typeof t.length&&Object.prototype.hasOwnProperty.call(t,"callee")&&!Object.prototype.propertyIsEnumerable.call(t,"callee")||!1}var supportsArgumentsClass="[object Arguments]"==function(){return Object.prototype.toString.call(arguments)}();exports=module.exports=supportsArgumentsClass?supported:unsupported,exports.supported=supported,exports.unsupported=unsupported; +// This is CodeMirror (http://codemirror.net), a code editor +// implemented in JavaScript on top of the browser's DOM. +// +// You can find some technical background for some of the code below +// at http://marijnhaverbeke.nl/blog/#cm-internals . -},{}],3:[function(require,module,exports){ -function shim(e){var s=[];for(var t in e)s.push(t);return s}exports=module.exports="function"==typeof Object.keys?Object.keys:shim,exports.shim=shim; +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + module.exports = mod(); + else if (typeof define == "function" && define.amd) // AMD + return define([], mod); + else // Plain browser env + (this || window).CodeMirror = mod(); +})(function() { + "use strict"; + + // BROWSER SNIFFING + + // Kludges for bugs and behavior differences that can't be feature + // detected are enabled based on userAgent etc sniffing. + var userAgent = navigator.userAgent; + var platform = navigator.platform; + + var gecko = /gecko\/\d/i.test(userAgent); + var ie_upto10 = /MSIE \d/.test(userAgent); + var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); + var ie = ie_upto10 || ie_11up; + var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]); + var webkit = /WebKit\//.test(userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); + var chrome = /Chrome\//.test(userAgent); + var presto = /Opera\//.test(userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); + var phantom = /PhantomJS/.test(userAgent); + + var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); + // This is woefully incomplete. Suggestions for alternative methods welcome. + var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); + var mac = ios || /Mac/.test(platform); + var chromeOS = /\bCrOS\b/.test(userAgent); + var windows = /win/i.test(platform); + + var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); + if (presto_version) presto_version = Number(presto_version[1]); + if (presto_version && presto_version >= 15) { presto = false; webkit = true; } + // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); + var captureRightClick = gecko || (ie && ie_version >= 9); + + // Optimize some code when these features are not used. + var sawReadOnlySpans = false, sawCollapsedSpans = false; + + // EDITOR CONSTRUCTOR + + // A CodeMirror instance represents an editor. This is the object + // that user code is usually dealing with. + + function CodeMirror(place, options) { + if (!(this instanceof CodeMirror)) return new CodeMirror(place, options); + + this.options = options = options ? copyObj(options) : {}; + // Determine effective options based on given values and defaults. + copyObj(defaults, options, false); + setGuttersForLineNumbers(options); + + var doc = options.value; + if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator); + this.doc = doc; + + var input = new CodeMirror.inputStyles[options.inputStyle](this); + var display = this.display = new Display(place, doc, input); + display.wrapper.CodeMirror = this; + updateGutters(this); + themeChanged(this); + if (options.lineWrapping) + this.display.wrapper.className += " CodeMirror-wrap"; + if (options.autofocus && !mobile) display.input.focus(); + initScrollbars(this); + + this.state = { + keyMaps: [], // stores maps added by addKeyMap + overlays: [], // highlighting overlays, as added by addOverlay + modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info + overwrite: false, + delayingBlurEvent: false, + focused: false, + suppressEdits: false, // used to disable editing during key handlers when in readOnly mode + pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll + selectingText: false, + draggingText: false, + highlight: new Delayed(), // stores highlight worker timeout + keySeq: null, // Unfinished key sequence + specialChars: null + }; + + var cm = this; + + // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20); + + registerEventHandlers(this); + ensureGlobalHandlers(); + + startOperation(this); + this.curOp.forceUpdate = true; + attachDoc(this, doc); + + if ((options.autofocus && !mobile) || cm.hasFocus()) + setTimeout(bind(onFocus, this), 20); + else + onBlur(this); + + for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) + optionHandlers[opt](this, options[opt], Init); + maybeUpdateLineNumberWidth(this); + if (options.finishInit) options.finishInit(this); + for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); + endOperation(this); + // Suppress optimizelegibility in Webkit, since it breaks text + // measuring on line wrapping boundaries. + if (webkit && options.lineWrapping && + getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") + display.lineDiv.style.textRendering = "auto"; + } + + // DISPLAY CONSTRUCTOR + + // The display handles the DOM integration, both for input reading + // and content drawing. It holds references to DOM nodes and + // display-related state. + + function Display(place, doc, input) { + var d = this; + this.input = input; + + // Covers bottom-right square when both scrollbars are present. + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + d.scrollbarFiller.setAttribute("cm-not-content", "true"); + // Covers bottom of gutter when coverGutterNextToScrollbar is on + // and h scrollbar is present. + d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); + d.gutterFiller.setAttribute("cm-not-content", "true"); + // Will contain the actual code, positioned to cover the viewport. + d.lineDiv = elt("div", null, "CodeMirror-code"); + // Elements are added to these to represent selection and cursors. + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + d.cursorDiv = elt("div", null, "CodeMirror-cursors"); + // A visibility: hidden element used to find the size of things. + d.measure = elt("div", null, "CodeMirror-measure"); + // When lines outside of the viewport are measured, they are drawn in this. + d.lineMeasure = elt("div", null, "CodeMirror-measure"); + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], + null, "position: relative; outline: none"); + // Moved around its parent to cover visible view. + d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative"); + // Set to the height of the document, allowing scrolling. + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + d.sizerWidth = null; + // Behavior of elts with overflow: auto and padding is + // inconsistent across browsers. This is used to ensure the + // scrollable area is big enough. + d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); + // Will contain the gutters, if any. + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; + // Actual scrollable element. + d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); + d.scroller.setAttribute("tabIndex", "-1"); + // The element in which the editor lives. + d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); + + // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) + if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } + if (!webkit && !(gecko && mobile)) d.scroller.draggable = true; + + if (place) { + if (place.appendChild) place.appendChild(d.wrapper); + else place(d.wrapper); + } + + // Current rendered range (may be bigger than the view window). + d.viewFrom = d.viewTo = doc.first; + d.reportedViewFrom = d.reportedViewTo = doc.first; + // Information about the rendered lines. + d.view = []; + d.renderedView = null; + // Holds info about a single rendered line when it was rendered + // for measurement, while not in view. + d.externalMeasured = null; + // Empty space (in pixels) above the view + d.viewOffset = 0; + d.lastWrapHeight = d.lastWrapWidth = 0; + d.updateLineNumbers = null; + + d.nativeBarWidth = d.barHeight = d.barWidth = 0; + d.scrollbarsClipped = false; + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; + // Set to true when a non-horizontal-scrolling line widget is + // added. As an optimization, line widget aligning is skipped when + // this is false. + d.alignWidgets = false; + + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + d.maxLine = null; + d.maxLineLength = 0; + d.maxLineChanged = false; + + // Used for measuring wheel scrolling granularity + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; + + // True when shift is held down. + d.shift = false; + + // Used to track whether anything happened since the context menu + // was opened. + d.selForContextMenu = null; + + d.activeTouch = null; + + input.init(d); + } + + // STATE UPDATES + + // Used to get the editor into a consistent state again when options change. + + function loadMode(cm) { + cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); + resetModeState(cm); + } + + function resetModeState(cm) { + cm.doc.iter(function(line) { + if (line.stateAfter) line.stateAfter = null; + if (line.styles) line.styles = null; + }); + cm.doc.frontier = cm.doc.first; + startWorker(cm, 100); + cm.state.modeGen++; + if (cm.curOp) regChange(cm); + } + + function wrappingChanged(cm) { + if (cm.options.lineWrapping) { + addClass(cm.display.wrapper, "CodeMirror-wrap"); + cm.display.sizer.style.minWidth = ""; + cm.display.sizerWidth = null; + } else { + rmClass(cm.display.wrapper, "CodeMirror-wrap"); + findMaxLine(cm); + } + estimateLineHeights(cm); + regChange(cm); + clearCaches(cm); + setTimeout(function(){updateScrollbars(cm);}, 100); + } + + // Returns a function that estimates the height of a line, to use as + // first approximation until the line becomes visible (and is thus + // properly measurable). + function estimateHeight(cm) { + var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; + var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); + return function(line) { + if (lineIsHidden(cm.doc, line)) return 0; + + var widgetsHeight = 0; + if (line.widgets) for (var i = 0; i < line.widgets.length; i++) { + if (line.widgets[i].height) widgetsHeight += line.widgets[i].height; + } + + if (wrapping) + return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th; + else + return widgetsHeight + th; + }; + } + + function estimateLineHeights(cm) { + var doc = cm.doc, est = estimateHeight(cm); + doc.iter(function(line) { + var estHeight = est(line); + if (estHeight != line.height) updateLineHeight(line, estHeight); + }); + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + clearCaches(cm); + } + + function guttersChanged(cm) { + updateGutters(cm); + regChange(cm); + setTimeout(function(){alignHorizontally(cm);}, 20); + } + + // Rebuild the gutter elements, ensure the margin to the left of the + // code matches their width. + function updateGutters(cm) { + var gutters = cm.display.gutters, specs = cm.options.gutters; + removeChildren(gutters); + for (var i = 0; i < specs.length; ++i) { + var gutterClass = specs[i]; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); + if (gutterClass == "CodeMirror-linenumbers") { + cm.display.lineGutter = gElt; + gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; + } + } + gutters.style.display = i ? "" : "none"; + updateGutterSpace(cm); + } + + function updateGutterSpace(cm) { + var width = cm.display.gutters.offsetWidth; + cm.display.sizer.style.marginLeft = width + "px"; + } + + // Compute the character length of a line, taking into account + // collapsed ranges (see markText) that might hide parts, and join + // other lines onto it. + function lineLength(line) { + if (line.height == 0) return 0; + var len = line.text.length, merged, cur = line; + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(0, true); + cur = found.from.line; + len += found.from.ch - found.to.ch; + } + cur = line; + while (merged = collapsedSpanAtEnd(cur)) { + var found = merged.find(0, true); + len -= cur.text.length - found.from.ch; + cur = found.to.line; + len += cur.text.length - found.to.ch; + } + return len; + } + + // Find the longest line in the document. + function findMaxLine(cm) { + var d = cm.display, doc = cm.doc; + d.maxLine = getLine(doc, doc.first); + d.maxLineLength = lineLength(d.maxLine); + d.maxLineChanged = true; + doc.iter(function(line) { + var len = lineLength(line); + if (len > d.maxLineLength) { + d.maxLineLength = len; + d.maxLine = line; + } + }); + } + + // Make sure the gutters options contains the element + // "CodeMirror-linenumbers" when the lineNumbers option is true. + function setGuttersForLineNumbers(options) { + var found = indexOf(options.gutters, "CodeMirror-linenumbers"); + if (found == -1 && options.lineNumbers) { + options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]); + } else if (found > -1 && !options.lineNumbers) { + options.gutters = options.gutters.slice(0); + options.gutters.splice(found, 1); + } + } + + // SCROLLBARS + + // Prepare DOM reads needed to update the scrollbars. Done in one + // shot to minimize update/measure roundtrips. + function measureForScrollbars(cm) { + var d = cm.display, gutterW = d.gutters.offsetWidth; + var docH = Math.round(cm.doc.height + paddingVert(cm.display)); + return { + clientHeight: d.scroller.clientHeight, + viewHeight: d.wrapper.clientHeight, + scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, + viewWidth: d.wrapper.clientWidth, + barLeft: cm.options.fixedGutter ? gutterW : 0, + docHeight: docH, + scrollHeight: docH + scrollGap(cm) + d.barHeight, + nativeBarWidth: d.nativeBarWidth, + gutterWidth: gutterW + }; + } + + function NativeScrollbars(place, scroll, cm) { + this.cm = cm; + var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); + var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); + place(vert); place(horiz); + + on(vert, "scroll", function() { + if (vert.clientHeight) scroll(vert.scrollTop, "vertical"); + }); + on(horiz, "scroll", function() { + if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal"); + }); + + this.checkedZeroWidth = false; + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; + } + + NativeScrollbars.prototype = copyObj({ + update: function(measure) { + var needsH = measure.scrollWidth > measure.clientWidth + 1; + var needsV = measure.scrollHeight > measure.clientHeight + 1; + var sWidth = measure.nativeBarWidth; + + if (needsV) { + this.vert.style.display = "block"; + this.vert.style.bottom = needsH ? sWidth + "px" : "0"; + var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); + // A bug in IE8 can cause this value to be negative, so guard it. + this.vert.firstChild.style.height = + Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; + } else { + this.vert.style.display = ""; + this.vert.firstChild.style.height = "0"; + } + + if (needsH) { + this.horiz.style.display = "block"; + this.horiz.style.right = needsV ? sWidth + "px" : "0"; + this.horiz.style.left = measure.barLeft + "px"; + var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); + this.horiz.firstChild.style.width = + (measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; + } else { + this.horiz.style.display = ""; + this.horiz.firstChild.style.width = "0"; + } + + if (!this.checkedZeroWidth && measure.clientHeight > 0) { + if (sWidth == 0) this.zeroWidthHack(); + this.checkedZeroWidth = true; + } + + return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}; + }, + setScrollLeft: function(pos) { + if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos; + if (this.disableHoriz) this.enableZeroWidthBar(this.horiz, this.disableHoriz); + }, + setScrollTop: function(pos) { + if (this.vert.scrollTop != pos) this.vert.scrollTop = pos; + if (this.disableVert) this.enableZeroWidthBar(this.vert, this.disableVert); + }, + zeroWidthHack: function() { + var w = mac && !mac_geMountainLion ? "12px" : "18px"; + this.horiz.style.height = this.vert.style.width = w; + this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"; + this.disableHoriz = new Delayed; + this.disableVert = new Delayed; + }, + enableZeroWidthBar: function(bar, delay) { + bar.style.pointerEvents = "auto"; + function maybeDisable() { + // To find out whether the scrollbar is still visible, we + // check whether the element under the pixel in the bottom + // left corner of the scrollbar box is the scrollbar box + // itself (when the bar is still visible) or its filler child + // (when the bar is hidden). If it is still visible, we keep + // it enabled, if it's hidden, we disable pointer events. + var box = bar.getBoundingClientRect(); + var elt = document.elementFromPoint(box.left + 1, box.bottom - 1); + if (elt != bar) bar.style.pointerEvents = "none"; + else delay.set(1000, maybeDisable); + } + delay.set(1000, maybeDisable); + }, + clear: function() { + var parent = this.horiz.parentNode; + parent.removeChild(this.horiz); + parent.removeChild(this.vert); + } + }, NativeScrollbars.prototype); + + function NullScrollbars() {} + + NullScrollbars.prototype = copyObj({ + update: function() { return {bottom: 0, right: 0}; }, + setScrollLeft: function() {}, + setScrollTop: function() {}, + clear: function() {} + }, NullScrollbars.prototype); + + CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; + + function initScrollbars(cm) { + if (cm.display.scrollbars) { + cm.display.scrollbars.clear(); + if (cm.display.scrollbars.addClass) + rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); + } + + cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) { + cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); + // Prevent clicks in the scrollbars from killing focus + on(node, "mousedown", function() { + if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0); + }); + node.setAttribute("cm-not-content", "true"); + }, function(pos, axis) { + if (axis == "horizontal") setScrollLeft(cm, pos); + else setScrollTop(cm, pos); + }, cm); + if (cm.display.scrollbars.addClass) + addClass(cm.display.wrapper, cm.display.scrollbars.addClass); + } + + function updateScrollbars(cm, measure) { + if (!measure) measure = measureForScrollbars(cm); + var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; + updateScrollbarsInner(cm, measure); + for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { + if (startWidth != cm.display.barWidth && cm.options.lineWrapping) + updateHeightsInViewport(cm); + updateScrollbarsInner(cm, measureForScrollbars(cm)); + startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; + } + } + + // Re-synchronize the fake scrollbars with the actual size of the + // content. + function updateScrollbarsInner(cm, measure) { + var d = cm.display; + var sizes = d.scrollbars.update(measure); + + d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; + d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; + d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent" + + if (sizes.right && sizes.bottom) { + d.scrollbarFiller.style.display = "block"; + d.scrollbarFiller.style.height = sizes.bottom + "px"; + d.scrollbarFiller.style.width = sizes.right + "px"; + } else d.scrollbarFiller.style.display = ""; + if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { + d.gutterFiller.style.display = "block"; + d.gutterFiller.style.height = sizes.bottom + "px"; + d.gutterFiller.style.width = measure.gutterWidth + "px"; + } else d.gutterFiller.style.display = ""; + } + + // Compute the lines that are visible in a given viewport (defaults + // the the current scroll position). viewport may contain top, + // height, and ensure (see op.scrollToPos) properties. + function visibleLines(display, doc, viewport) { + var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; + top = Math.floor(top - paddingTop(display)); + var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; + + var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); + // Ensure is a {from: {line, ch}, to: {line, ch}} object, and + // forces those lines into the viewport (if possible). + if (viewport && viewport.ensure) { + var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; + if (ensureFrom < from) { + from = ensureFrom; + to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); + } else if (Math.min(ensureTo, doc.lastLine()) >= to) { + from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); + to = ensureTo; + } + } + return {from: from, to: Math.max(to, from + 1)}; + } + + // LINE NUMBERS + + // Re-align line numbers and gutter marks to compensate for + // horizontal scrolling. + function alignHorizontally(cm) { + var display = cm.display, view = display.view; + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return; + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; + var gutterW = display.gutters.offsetWidth, left = comp + "px"; + for (var i = 0; i < view.length; i++) if (!view[i].hidden) { + if (cm.options.fixedGutter && view[i].gutter) + view[i].gutter.style.left = left; + var align = view[i].alignable; + if (align) for (var j = 0; j < align.length; j++) + align[j].style.left = left; + } + if (cm.options.fixedGutter) + display.gutters.style.left = (comp + gutterW) + "px"; + } + + // Used to ensure that the line number gutter is still the right + // size for the current document size. Returns true when an update + // is needed. + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) return false; + var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + updateGutterSpace(cm); + return true; + } + return false; + } + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)); + } + + // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, + // but using getBoundingClientRect to get a sub-pixel-accurate + // result. + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left; + } + + // DISPLAY DRAWING + + function DisplayUpdate(cm, viewport, force) { + var display = cm.display; + + this.viewport = viewport; + // Store some values that we'll need later (but don't want to force a relayout for) + this.visible = visibleLines(display, cm.doc, viewport); + this.editorIsHidden = !display.wrapper.offsetWidth; + this.wrapperHeight = display.wrapper.clientHeight; + this.wrapperWidth = display.wrapper.clientWidth; + this.oldDisplayWidth = displayWidth(cm); + this.force = force; + this.dims = getDimensions(cm); + this.events = []; + } + + DisplayUpdate.prototype.signal = function(emitter, type) { + if (hasHandler(emitter, type)) + this.events.push(arguments); + }; + DisplayUpdate.prototype.finish = function() { + for (var i = 0; i < this.events.length; i++) + signal.apply(null, this.events[i]); + }; + + function maybeClipScrollbars(cm) { + var display = cm.display; + if (!display.scrollbarsClipped && display.scroller.offsetWidth) { + display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; + display.heightForcer.style.height = scrollGap(cm) + "px"; + display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; + display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; + display.scrollbarsClipped = true; + } + } + + // Does the actual updating of the line display. Bails out + // (returning false) when there is nothing to be done and forced is + // false. + function updateDisplayIfNeeded(cm, update) { + var display = cm.display, doc = cm.doc; + + if (update.editorIsHidden) { + resetView(cm); + return false; + } + + // Bail out if the visible area is already rendered and nothing changed. + if (!update.force && + update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && + display.renderedView == display.view && countDirtyView(cm) == 0) + return false; + + if (maybeUpdateLineNumberWidth(cm)) { + resetView(cm); + update.dims = getDimensions(cm); + } + + // Compute a suitable new viewport (from & to) + var end = doc.first + doc.size; + var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); + var to = Math.min(end, update.visible.to + cm.options.viewportMargin); + if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom); + if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo); + if (sawCollapsedSpans) { + from = visualLineNo(cm.doc, from); + to = visualLineEndNo(cm.doc, to); + } + + var different = from != display.viewFrom || to != display.viewTo || + display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; + adjustView(cm, from, to); + + display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); + // Position the mover div to align with the current scroll position + cm.display.mover.style.top = display.viewOffset + "px"; + + var toUpdate = countDirtyView(cm); + if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) + return false; + + // For big changes, we hide the enclosing element during the + // update, since that speeds up the operations on most browsers. + var focused = activeElt(); + if (toUpdate > 4) display.lineDiv.style.display = "none"; + patchDisplay(cm, display.updateLineNumbers, update.dims); + if (toUpdate > 4) display.lineDiv.style.display = ""; + display.renderedView = display.view; + // There might have been a widget with a focused element that got + // hidden or updated, if so re-focus it. + if (focused && activeElt() != focused && focused.offsetHeight) focused.focus(); + + // Prevent selection and cursors from interfering with the scroll + // width and height. + removeChildren(display.cursorDiv); + removeChildren(display.selectionDiv); + display.gutters.style.height = display.sizer.style.minHeight = 0; + + if (different) { + display.lastWrapHeight = update.wrapperHeight; + display.lastWrapWidth = update.wrapperWidth; + startWorker(cm, 400); + } + + display.updateLineNumbers = null; + + return true; + } + + function postUpdateDisplay(cm, update) { + var viewport = update.viewport; + + for (var first = true;; first = false) { + if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { + // Clip forced viewport to actual scrollable area. + if (viewport && viewport.top != null) + viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; + // Updated line heights might result in the drawn area not + // actually covering the viewport. Keep looping until it does. + update.visible = visibleLines(cm.display, cm.doc, viewport); + if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) + break; + } + if (!updateDisplayIfNeeded(cm, update)) break; + updateHeightsInViewport(cm); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + } + + update.signal(cm, "update", cm); + if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { + update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); + cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; + } + } + + function updateDisplaySimple(cm, viewport) { + var update = new DisplayUpdate(cm, viewport); + if (updateDisplayIfNeeded(cm, update)) { + updateHeightsInViewport(cm); + postUpdateDisplay(cm, update); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.finish(); + } + } + + function setDocumentHeight(cm, measure) { + cm.display.sizer.style.minHeight = measure.docHeight + "px"; + cm.display.heightForcer.style.top = measure.docHeight + "px"; + cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; + } + + // Read the actual heights of the rendered lines, and update their + // stored heights to match. + function updateHeightsInViewport(cm) { + var display = cm.display; + var prevBottom = display.lineDiv.offsetTop; + for (var i = 0; i < display.view.length; i++) { + var cur = display.view[i], height; + if (cur.hidden) continue; + if (ie && ie_version < 8) { + var bot = cur.node.offsetTop + cur.node.offsetHeight; + height = bot - prevBottom; + prevBottom = bot; + } else { + var box = cur.node.getBoundingClientRect(); + height = box.bottom - box.top; + } + var diff = cur.line.height - height; + if (height < 2) height = textHeight(display); + if (diff > .001 || diff < -.001) { + updateLineHeight(cur.line, height); + updateWidgetHeight(cur.line); + if (cur.rest) for (var j = 0; j < cur.rest.length; j++) + updateWidgetHeight(cur.rest[j]); + } + } + } + + // Read and store the height of line widgets associated with the + // given line. + function updateWidgetHeight(line) { + if (line.widgets) for (var i = 0; i < line.widgets.length; ++i) + line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight; + } + + // Do a bulk-read of the DOM positions and sizes needed to draw the + // view, so that we don't interleave reading and writing to the DOM. + function getDimensions(cm) { + var d = cm.display, left = {}, width = {}; + var gutterLeft = d.gutters.clientLeft; + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft; + width[cm.options.gutters[i]] = n.clientWidth; + } + return {fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth}; + } + + // Sync the actual display DOM structure with display.view, removing + // nodes for lines that are no longer in view, and creating the ones + // that are not there yet, and updating the ones that are out of + // date. + function patchDisplay(cm, updateNumbersFrom, dims) { + var display = cm.display, lineNumbers = cm.options.lineNumbers; + var container = display.lineDiv, cur = container.firstChild; + + function rm(node) { + var next = node.nextSibling; + // Works around a throw-scroll bug in OS X Webkit + if (webkit && mac && cm.display.currentWheelTarget == node) + node.style.display = "none"; + else + node.parentNode.removeChild(node); + return next; + } + + var view = display.view, lineN = display.viewFrom; + // Loop over the elements in the view, syncing cur (the DOM nodes + // in display.lineDiv) with the view as we go. + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (lineView.hidden) { + } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet + var node = buildLineElement(cm, lineView, lineN, dims); + container.insertBefore(node, cur); + } else { // Already drawn + while (cur != lineView.node) cur = rm(cur); + var updateNumber = lineNumbers && updateNumbersFrom != null && + updateNumbersFrom <= lineN && lineView.lineNumber; + if (lineView.changes) { + if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false; + updateLineForChanges(cm, lineView, lineN, dims); + } + if (updateNumber) { + removeChildren(lineView.lineNumber); + lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); + } + cur = lineView.node.nextSibling; + } + lineN += lineView.size; + } + while (cur) cur = rm(cur); + } + + // When an aspect of a line changes, a string is added to + // lineView.changes. This updates the relevant part of the line's + // DOM structure. + function updateLineForChanges(cm, lineView, lineN, dims) { + for (var j = 0; j < lineView.changes.length; j++) { + var type = lineView.changes[j]; + if (type == "text") updateLineText(cm, lineView); + else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims); + else if (type == "class") updateLineClasses(lineView); + else if (type == "widget") updateLineWidgets(cm, lineView, dims); + } + lineView.changes = null; + } + + // Lines with gutter elements, widgets or a background class need to + // be wrapped, and have the extra elements added to the wrapper div + function ensureLineWrapped(lineView) { + if (lineView.node == lineView.text) { + lineView.node = elt("div", null, null, "position: relative"); + if (lineView.text.parentNode) + lineView.text.parentNode.replaceChild(lineView.node, lineView.text); + lineView.node.appendChild(lineView.text); + if (ie && ie_version < 8) lineView.node.style.zIndex = 2; + } + return lineView.node; + } + + function updateLineBackground(lineView) { + var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; + if (cls) cls += " CodeMirror-linebackground"; + if (lineView.background) { + if (cls) lineView.background.className = cls; + else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } + } else if (cls) { + var wrap = ensureLineWrapped(lineView); + lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); + } + } + + // Wrapper around buildLineContent which will reuse the structure + // in display.externalMeasured when possible. + function getLineContent(cm, lineView) { + var ext = cm.display.externalMeasured; + if (ext && ext.line == lineView.line) { + cm.display.externalMeasured = null; + lineView.measure = ext.measure; + return ext.built; + } + return buildLineContent(cm, lineView); + } + + // Redraw the line's text. Interacts with the background and text + // classes because the mode may output tokens that influence these + // classes. + function updateLineText(cm, lineView) { + var cls = lineView.text.className; + var built = getLineContent(cm, lineView); + if (lineView.text == lineView.node) lineView.node = built.pre; + lineView.text.parentNode.replaceChild(built.pre, lineView.text); + lineView.text = built.pre; + if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { + lineView.bgClass = built.bgClass; + lineView.textClass = built.textClass; + updateLineClasses(lineView); + } else if (cls) { + lineView.text.className = cls; + } + } + + function updateLineClasses(lineView) { + updateLineBackground(lineView); + if (lineView.line.wrapClass) + ensureLineWrapped(lineView).className = lineView.line.wrapClass; + else if (lineView.node != lineView.text) + lineView.node.className = ""; + var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; + lineView.text.className = textClass || ""; + } + + function updateLineGutter(cm, lineView, lineN, dims) { + if (lineView.gutter) { + lineView.node.removeChild(lineView.gutter); + lineView.gutter = null; + } + if (lineView.gutterBackground) { + lineView.node.removeChild(lineView.gutterBackground); + lineView.gutterBackground = null; + } + if (lineView.line.gutterClass) { + var wrap = ensureLineWrapped(lineView); + lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, + "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + + "px; width: " + dims.gutterTotalWidth + "px"); + wrap.insertBefore(lineView.gutterBackground, lineView.text); + } + var markers = lineView.line.gutterMarkers; + if (cm.options.lineNumbers || markers) { + var wrap = ensureLineWrapped(lineView); + var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " + + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"); + cm.display.input.setUneditable(gutterWrap); + wrap.insertBefore(gutterWrap, lineView.text); + if (lineView.line.gutterClass) + gutterWrap.className += " " + lineView.line.gutterClass; + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) + lineView.lineNumber = gutterWrap.appendChild( + elt("div", lineNumberFor(cm.options, lineN), + "CodeMirror-linenumber CodeMirror-gutter-elt", + "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " + + cm.display.lineNumInnerWidth + "px")); + if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) { + var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; + if (found) + gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + + dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); + } + } + } + + function updateLineWidgets(cm, lineView, dims) { + if (lineView.alignable) lineView.alignable = null; + for (var node = lineView.node.firstChild, next; node; node = next) { + var next = node.nextSibling; + if (node.className == "CodeMirror-linewidget") + lineView.node.removeChild(node); + } + insertLineWidgets(cm, lineView, dims); + } + + // Build a line's DOM representation from scratch + function buildLineElement(cm, lineView, lineN, dims) { + var built = getLineContent(cm, lineView); + lineView.text = lineView.node = built.pre; + if (built.bgClass) lineView.bgClass = built.bgClass; + if (built.textClass) lineView.textClass = built.textClass; + + updateLineClasses(lineView); + updateLineGutter(cm, lineView, lineN, dims); + insertLineWidgets(cm, lineView, dims); + return lineView.node; + } + + // A lineView may contain multiple logical lines (when merged by + // collapsed spans). The widgets for all of them need to be drawn. + function insertLineWidgets(cm, lineView, dims) { + insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); + if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) + insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); + } + + function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { + if (!line.widgets) return; + var wrap = ensureLineWrapped(lineView); + for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); + if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true"); + positionLineWidget(widget, node, lineView, dims); + cm.display.input.setUneditable(node); + if (allowAbove && widget.above) + wrap.insertBefore(node, lineView.gutter || lineView.text); + else + wrap.appendChild(node); + signalLater(widget, "redraw"); + } + } + + function positionLineWidget(widget, node, lineView, dims) { + if (widget.noHScroll) { + (lineView.alignable || (lineView.alignable = [])).push(node); + var width = dims.wrapperWidth; + node.style.left = dims.fixedPos + "px"; + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth; + node.style.paddingLeft = dims.gutterTotalWidth + "px"; + } + node.style.width = width + "px"; + } + if (widget.coverGutter) { + node.style.zIndex = 5; + node.style.position = "relative"; + if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px"; + } + } + + // POSITION OBJECT + + // A Pos instance represents a position within the text. + var Pos = CodeMirror.Pos = function(line, ch) { + if (!(this instanceof Pos)) return new Pos(line, ch); + this.line = line; this.ch = ch; + }; + + // Compare two positions, return 0 if they are the same, a negative + // number when a is less, and a positive number otherwise. + var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; }; + + function copyPos(x) {return Pos(x.line, x.ch);} + function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; } + function minPos(a, b) { return cmp(a, b) < 0 ? a : b; } + + // INPUT HANDLING + + function ensureFocus(cm) { + if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); } + } + + // This will be set to a {lineWise: bool, text: [string]} object, so + // that, when pasting, we know what kind of selections the copied + // text was made out of. + var lastCopied = null; + + function applyTextInput(cm, inserted, deleted, sel, origin) { + var doc = cm.doc; + cm.display.shift = false; + if (!sel) sel = doc.sel; + + var paste = cm.state.pasteIncoming || origin == "paste"; + var textLines = doc.splitLines(inserted), multiPaste = null + // When pasing N lines into N selections, insert one line per selection + if (paste && sel.ranges.length > 1) { + if (lastCopied && lastCopied.text.join("\n") == inserted) { + if (sel.ranges.length % lastCopied.text.length == 0) { + multiPaste = []; + for (var i = 0; i < lastCopied.text.length; i++) + multiPaste.push(doc.splitLines(lastCopied.text[i])); + } + } else if (textLines.length == sel.ranges.length) { + multiPaste = map(textLines, function(l) { return [l]; }); + } + } + + // Normal behavior is to insert the new text into every selection + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range = sel.ranges[i]; + var from = range.from(), to = range.to(); + if (range.empty()) { + if (deleted && deleted > 0) // Handle deletion + from = Pos(from.line, from.ch - deleted); + else if (cm.state.overwrite && !paste) // Handle overwrite + to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); + else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) + from = to = Pos(from.line, 0) + } + var updateInput = cm.curOp.updateInput; + var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines, + origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")}; + makeChange(cm.doc, changeEvent); + signalLater(cm, "inputRead", cm, changeEvent); + } + if (inserted && !paste) + triggerElectric(cm, inserted); + + ensureCursorVisible(cm); + cm.curOp.updateInput = updateInput; + cm.curOp.typing = true; + cm.state.pasteIncoming = cm.state.cutIncoming = false; + } + + function handlePaste(e, cm) { + var pasted = e.clipboardData && e.clipboardData.getData("text/plain"); + if (pasted) { + e.preventDefault(); + if (!cm.isReadOnly() && !cm.options.disableInput) + runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); }); + return true; + } + } + + function triggerElectric(cm, inserted) { + // When an 'electric' character is inserted, immediately trigger a reindent + if (!cm.options.electricChars || !cm.options.smartIndent) return; + var sel = cm.doc.sel; + + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range = sel.ranges[i]; + if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue; + var mode = cm.getModeAt(range.head); + var indented = false; + if (mode.electricChars) { + for (var j = 0; j < mode.electricChars.length; j++) + if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { + indented = indentLine(cm, range.head.line, "smart"); + break; + } + } else if (mode.electricInput) { + if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) + indented = indentLine(cm, range.head.line, "smart"); + } + if (indented) signalLater(cm, "electricInput", cm, range.head.line); + } + } + + function copyableRanges(cm) { + var text = [], ranges = []; + for (var i = 0; i < cm.doc.sel.ranges.length; i++) { + var line = cm.doc.sel.ranges[i].head.line; + var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; + ranges.push(lineRange); + text.push(cm.getRange(lineRange.anchor, lineRange.head)); + } + return {text: text, ranges: ranges}; + } + + function disableBrowserMagic(field) { + field.setAttribute("autocorrect", "off"); + field.setAttribute("autocapitalize", "off"); + field.setAttribute("spellcheck", "false"); + } + + // TEXTAREA INPUT STYLE + + function TextareaInput(cm) { + this.cm = cm; + // See input.poll and input.reset + this.prevInput = ""; + + // Flag that indicates whether we expect input to appear real soon + // now (after some event like 'keypress' or 'input') and are + // polling intensively. + this.pollingFast = false; + // Self-resetting timeout for the poller + this.polling = new Delayed(); + // Tracks when input.reset has punted to just putting a short + // string into the textarea instead of the full selection. + this.inaccurateSelection = false; + // Used to work around IE issue with selection being forgotten when focus moves away from textarea + this.hasSelection = false; + this.composing = null; + }; + + function hiddenTextarea() { + var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"); + var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); + // The textarea is kept positioned near the cursor to prevent the + // fact that it'll be scrolled into view on input from scrolling + // our fake cursor out of view. On webkit, when wrap=off, paste is + // very slow. So make the area wide instead. + if (webkit) te.style.width = "1000px"; + else te.setAttribute("wrap", "off"); + // If border: 0; -- iOS fails to open keyboard (issue #1287) + if (ios) te.style.border = "1px solid black"; + disableBrowserMagic(te); + return div; + } + + TextareaInput.prototype = copyObj({ + init: function(display) { + var input = this, cm = this.cm; + + // Wraps and hides input textarea + var div = this.wrapper = hiddenTextarea(); + // The semihidden textarea that is focused when the editor is + // focused, and receives input. + var te = this.textarea = div.firstChild; + display.wrapper.insertBefore(div, display.wrapper.firstChild); + + // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) + if (ios) te.style.width = "0px"; + + on(te, "input", function() { + if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null; + input.poll(); + }); + + on(te, "paste", function(e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return + + cm.state.pasteIncoming = true; + input.fastPoll(); + }); + + function prepareCopyCut(e) { + if (signalDOMEvent(cm, e)) return + if (cm.somethingSelected()) { + lastCopied = {lineWise: false, text: cm.getSelections()}; + if (input.inaccurateSelection) { + input.prevInput = ""; + input.inaccurateSelection = false; + te.value = lastCopied.text.join("\n"); + selectInput(te); + } + } else if (!cm.options.lineWiseCopyCut) { + return; + } else { + var ranges = copyableRanges(cm); + lastCopied = {lineWise: true, text: ranges.text}; + if (e.type == "cut") { + cm.setSelections(ranges.ranges, null, sel_dontScroll); + } else { + input.prevInput = ""; + te.value = ranges.text.join("\n"); + selectInput(te); + } + } + if (e.type == "cut") cm.state.cutIncoming = true; + } + on(te, "cut", prepareCopyCut); + on(te, "copy", prepareCopyCut); + + on(display.scroller, "paste", function(e) { + if (eventInWidget(display, e) || signalDOMEvent(cm, e)) return; + cm.state.pasteIncoming = true; + input.focus(); + }); + + // Prevent normal selection in the editor (we handle our own) + on(display.lineSpace, "selectstart", function(e) { + if (!eventInWidget(display, e)) e_preventDefault(e); + }); + + on(te, "compositionstart", function() { + var start = cm.getCursor("from"); + if (input.composing) input.composing.range.clear() + input.composing = { + start: start, + range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) + }; + }); + on(te, "compositionend", function() { + if (input.composing) { + input.poll(); + input.composing.range.clear(); + input.composing = null; + } + }); + }, + + prepareSelection: function() { + // Redraw the selection and/or cursor + var cm = this.cm, display = cm.display, doc = cm.doc; + var result = prepareSelection(cm); + + // Move the hidden textarea near the cursor to prevent scrolling artifacts + if (cm.options.moveInputWithCursor) { + var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); + var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); + result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)); + result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)); + } + + return result; + }, + + showSelection: function(drawn) { + var cm = this.cm, display = cm.display; + removeChildrenAndAdd(display.cursorDiv, drawn.cursors); + removeChildrenAndAdd(display.selectionDiv, drawn.selection); + if (drawn.teTop != null) { + this.wrapper.style.top = drawn.teTop + "px"; + this.wrapper.style.left = drawn.teLeft + "px"; + } + }, + + // Reset the input to correspond to the selection (or to be empty, + // when not typing and nothing is selected) + reset: function(typing) { + if (this.contextMenuPending) return; + var minimal, selected, cm = this.cm, doc = cm.doc; + if (cm.somethingSelected()) { + this.prevInput = ""; + var range = doc.sel.primary(); + minimal = hasCopyEvent && + (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000); + var content = minimal ? "-" : selected || cm.getSelection(); + this.textarea.value = content; + if (cm.state.focused) selectInput(this.textarea); + if (ie && ie_version >= 9) this.hasSelection = content; + } else if (!typing) { + this.prevInput = this.textarea.value = ""; + if (ie && ie_version >= 9) this.hasSelection = null; + } + this.inaccurateSelection = minimal; + }, + + getField: function() { return this.textarea; }, + + supportsTouch: function() { return false; }, + + focus: function() { + if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { + try { this.textarea.focus(); } + catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM + } + }, + + blur: function() { this.textarea.blur(); }, + + resetPosition: function() { + this.wrapper.style.top = this.wrapper.style.left = 0; + }, + + receivedFocus: function() { this.slowPoll(); }, + + // Poll for input changes, using the normal rate of polling. This + // runs as long as the editor is focused. + slowPoll: function() { + var input = this; + if (input.pollingFast) return; + input.polling.set(this.cm.options.pollInterval, function() { + input.poll(); + if (input.cm.state.focused) input.slowPoll(); + }); + }, + + // When an event has just come in that is likely to add or change + // something in the input textarea, we poll faster, to ensure that + // the change appears on the screen quickly. + fastPoll: function() { + var missed = false, input = this; + input.pollingFast = true; + function p() { + var changed = input.poll(); + if (!changed && !missed) {missed = true; input.polling.set(60, p);} + else {input.pollingFast = false; input.slowPoll();} + } + input.polling.set(20, p); + }, + + // Read input from the textarea, and update the document to match. + // When something is selected, it is present in the textarea, and + // selected (unless it is huge, in which case a placeholder is + // used). When nothing is selected, the cursor sits after previously + // seen text (can be empty), which is stored in prevInput (we must + // not reset the textarea when typing, because that breaks IME). + poll: function() { + var cm = this.cm, input = this.textarea, prevInput = this.prevInput; + // Since this is called a *lot*, try to bail out as cheaply as + // possible when it is clear that nothing happened. hasSelection + // will be the case when there is a lot of text in the textarea, + // in which case reading its value would be expensive. + if (this.contextMenuPending || !cm.state.focused || + (hasSelection(input) && !prevInput && !this.composing) || + cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) + return false; + + var text = input.value; + // If nothing changed, bail. + if (text == prevInput && !cm.somethingSelected()) return false; + // Work around nonsensical selection resetting in IE9/10, and + // inexplicable appearance of private area unicode characters on + // some key combos in Mac (#2689). + if (ie && ie_version >= 9 && this.hasSelection === text || + mac && /[\uf700-\uf7ff]/.test(text)) { + cm.display.input.reset(); + return false; + } + + if (cm.doc.sel == cm.display.selForContextMenu) { + var first = text.charCodeAt(0); + if (first == 0x200b && !prevInput) prevInput = "\u200b"; + if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); } + } + // Find the part of the input that is actually new + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same; + + var self = this; + runInOp(cm, function() { + applyTextInput(cm, text.slice(same), prevInput.length - same, + null, self.composing ? "*compose" : null); + + // Don't leave long text in the textarea, since it makes further polling slow + if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = ""; + else self.prevInput = text; + + if (self.composing) { + self.composing.range.clear(); + self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"), + {className: "CodeMirror-composing"}); + } + }); + return true; + }, + + ensurePolled: function() { + if (this.pollingFast && this.poll()) this.pollingFast = false; + }, + + onKeyPress: function() { + if (ie && ie_version >= 9) this.hasSelection = null; + this.fastPoll(); + }, + + onContextMenu: function(e) { + var input = this, cm = input.cm, display = cm.display, te = input.textarea; + var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; + if (!pos || presto) return; // Opera is difficult. + + // Reset the current text selection only if the click is done outside of the selection + // and 'resetSelectionOnContextMenu' option is true. + var reset = cm.options.resetSelectionOnContextMenu; + if (reset && cm.doc.sel.contains(pos) == -1) + operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); + + var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; + input.wrapper.style.cssText = "position: absolute" + var wrapperBox = input.wrapper.getBoundingClientRect() + te.style.cssText = "position: absolute; width: 30px; height: 30px; top: " + (e.clientY - wrapperBox.top - 5) + + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px; z-index: 1000; background: " + + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + + "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712) + display.input.focus(); + if (webkit) window.scrollTo(null, oldScrollY); + display.input.reset(); + // Adds "Select all" to context menu in FF + if (!cm.somethingSelected()) te.value = input.prevInput = " "; + input.contextMenuPending = true; + display.selForContextMenu = cm.doc.sel; + clearTimeout(display.detectingSelectAll); + + // Select-all will be greyed out if there's nothing to select, so + // this adds a zero-width space so that we can later check whether + // it got selected. + function prepareSelectAllHack() { + if (te.selectionStart != null) { + var selected = cm.somethingSelected(); + var extval = "\u200b" + (selected ? te.value : ""); + te.value = "\u21da"; // Used to catch context-menu undo + te.value = extval; + input.prevInput = selected ? "" : "\u200b"; + te.selectionStart = 1; te.selectionEnd = extval.length; + // Re-set this, in case some other handler touched the + // selection in the meantime. + display.selForContextMenu = cm.doc.sel; + } + } + function rehide() { + input.contextMenuPending = false; + input.wrapper.style.cssText = oldWrapperCSS + te.style.cssText = oldCSS; + if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); + + // Try to detect the user choosing select-all + if (te.selectionStart != null) { + if (!ie || (ie && ie_version < 9)) prepareSelectAllHack(); + var i = 0, poll = function() { + if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && + te.selectionEnd > 0 && input.prevInput == "\u200b") + operation(cm, commands.selectAll)(cm); + else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500); + else display.input.reset(); + }; + display.detectingSelectAll = setTimeout(poll, 200); + } + } + + if (ie && ie_version >= 9) prepareSelectAllHack(); + if (captureRightClick) { + e_stop(e); + var mouseup = function() { + off(window, "mouseup", mouseup); + setTimeout(rehide, 20); + }; + on(window, "mouseup", mouseup); + } else { + setTimeout(rehide, 50); + } + }, + + readOnlyChanged: function(val) { + if (!val) this.reset(); + }, + + setUneditable: nothing, + + needsContentAttribute: false + }, TextareaInput.prototype); + + // CONTENTEDITABLE INPUT STYLE + + function ContentEditableInput(cm) { + this.cm = cm; + this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; + this.polling = new Delayed(); + this.gracePeriod = false; + } + + ContentEditableInput.prototype = copyObj({ + init: function(display) { + var input = this, cm = input.cm; + var div = input.div = display.lineDiv; + disableBrowserMagic(div); + + on(div, "paste", function(e) { + if (!signalDOMEvent(cm, e)) handlePaste(e, cm); + }) + + on(div, "compositionstart", function(e) { + var data = e.data; + input.composing = {sel: cm.doc.sel, data: data, startData: data}; + if (!data) return; + var prim = cm.doc.sel.primary(); + var line = cm.getLine(prim.head.line); + var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length)); + if (found > -1 && found <= prim.head.ch) + input.composing.sel = simpleSelection(Pos(prim.head.line, found), + Pos(prim.head.line, found + data.length)); + }); + on(div, "compositionupdate", function(e) { + input.composing.data = e.data; + }); + on(div, "compositionend", function(e) { + var ours = input.composing; + if (!ours) return; + if (e.data != ours.startData && !/\u200b/.test(e.data)) + ours.data = e.data; + // Need a small delay to prevent other code (input event, + // selection polling) from doing damage when fired right after + // compositionend. + setTimeout(function() { + if (!ours.handled) + input.applyComposition(ours); + if (input.composing == ours) + input.composing = null; + }, 50); + }); + + on(div, "touchstart", function() { + input.forceCompositionEnd(); + }); + + on(div, "input", function() { + if (input.composing) return; + if (cm.isReadOnly() || !input.pollContent()) + runInOp(input.cm, function() {regChange(cm);}); + }); + + function onCopyCut(e) { + if (signalDOMEvent(cm, e)) return + if (cm.somethingSelected()) { + lastCopied = {lineWise: false, text: cm.getSelections()}; + if (e.type == "cut") cm.replaceSelection("", null, "cut"); + } else if (!cm.options.lineWiseCopyCut) { + return; + } else { + var ranges = copyableRanges(cm); + lastCopied = {lineWise: true, text: ranges.text}; + if (e.type == "cut") { + cm.operation(function() { + cm.setSelections(ranges.ranges, 0, sel_dontScroll); + cm.replaceSelection("", null, "cut"); + }); + } + } + // iOS exposes the clipboard API, but seems to discard content inserted into it + if (e.clipboardData && !ios) { + e.preventDefault(); + e.clipboardData.clearData(); + e.clipboardData.setData("text/plain", lastCopied.text.join("\n")); + } else { + // Old-fashioned briefly-focus-a-textarea hack + var kludge = hiddenTextarea(), te = kludge.firstChild; + cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); + te.value = lastCopied.text.join("\n"); + var hadFocus = document.activeElement; + selectInput(te); + setTimeout(function() { + cm.display.lineSpace.removeChild(kludge); + hadFocus.focus(); + }, 50); + } + } + on(div, "copy", onCopyCut); + on(div, "cut", onCopyCut); + }, + + prepareSelection: function() { + var result = prepareSelection(this.cm, false); + result.focus = this.cm.state.focused; + return result; + }, + + showSelection: function(info, takeFocus) { + if (!info || !this.cm.display.view.length) return; + if (info.focus || takeFocus) this.showPrimarySelection(); + this.showMultipleSelections(info); + }, + + showPrimarySelection: function() { + var sel = window.getSelection(), prim = this.cm.doc.sel.primary(); + var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset); + var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset); + if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && + cmp(minPos(curAnchor, curFocus), prim.from()) == 0 && + cmp(maxPos(curAnchor, curFocus), prim.to()) == 0) + return; + + var start = posToDOM(this.cm, prim.from()); + var end = posToDOM(this.cm, prim.to()); + if (!start && !end) return; + + var view = this.cm.display.view; + var old = sel.rangeCount && sel.getRangeAt(0); + if (!start) { + start = {node: view[0].measure.map[2], offset: 0}; + } else if (!end) { // FIXME dangerously hacky + var measure = view[view.length - 1].measure; + var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; + end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}; + } + + try { var rng = range(start.node, start.offset, end.offset, end.node); } + catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible + if (rng) { + if (!gecko && this.cm.state.focused) { + sel.collapse(start.node, start.offset); + if (!rng.collapsed) sel.addRange(rng); + } else { + sel.removeAllRanges(); + sel.addRange(rng); + } + if (old && sel.anchorNode == null) sel.addRange(old); + else if (gecko) this.startGracePeriod(); + } + this.rememberSelection(); + }, + + startGracePeriod: function() { + var input = this; + clearTimeout(this.gracePeriod); + this.gracePeriod = setTimeout(function() { + input.gracePeriod = false; + if (input.selectionChanged()) + input.cm.operation(function() { input.cm.curOp.selectionChanged = true; }); + }, 20); + }, + + showMultipleSelections: function(info) { + removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); + removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); + }, + + rememberSelection: function() { + var sel = window.getSelection(); + this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; + this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; + }, + + selectionInEditor: function() { + var sel = window.getSelection(); + if (!sel.rangeCount) return false; + var node = sel.getRangeAt(0).commonAncestorContainer; + return contains(this.div, node); + }, + + focus: function() { + if (this.cm.options.readOnly != "nocursor") this.div.focus(); + }, + blur: function() { this.div.blur(); }, + getField: function() { return this.div; }, + + supportsTouch: function() { return true; }, + + receivedFocus: function() { + var input = this; + if (this.selectionInEditor()) + this.pollSelection(); + else + runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; }); + + function poll() { + if (input.cm.state.focused) { + input.pollSelection(); + input.polling.set(input.cm.options.pollInterval, poll); + } + } + this.polling.set(this.cm.options.pollInterval, poll); + }, + + selectionChanged: function() { + var sel = window.getSelection(); + return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || + sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset; + }, + + pollSelection: function() { + if (!this.composing && !this.gracePeriod && this.selectionChanged()) { + var sel = window.getSelection(), cm = this.cm; + this.rememberSelection(); + var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var head = domToPos(cm, sel.focusNode, sel.focusOffset); + if (anchor && head) runInOp(cm, function() { + setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); + if (anchor.bad || head.bad) cm.curOp.selectionChanged = true; + }); + } + }, + + pollContent: function() { + var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); + var from = sel.from(), to = sel.to(); + if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false; + + var fromIndex; + if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { + var fromLine = lineNo(display.view[0].line); + var fromNode = display.view[0].node; + } else { + var fromLine = lineNo(display.view[fromIndex].line); + var fromNode = display.view[fromIndex - 1].node.nextSibling; + } + var toIndex = findViewIndex(cm, to.line); + if (toIndex == display.view.length - 1) { + var toLine = display.viewTo - 1; + var toNode = display.lineDiv.lastChild; + } else { + var toLine = lineNo(display.view[toIndex + 1].line) - 1; + var toNode = display.view[toIndex + 1].node.previousSibling; + } + + var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); + var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); + while (newText.length > 1 && oldText.length > 1) { + if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } + else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } + else break; + } + + var cutFront = 0, cutEnd = 0; + var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); + while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) + ++cutFront; + var newBot = lst(newText), oldBot = lst(oldText); + var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), + oldBot.length - (oldText.length == 1 ? cutFront : 0)); + while (cutEnd < maxCutEnd && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) + ++cutEnd; + + newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd); + newText[0] = newText[0].slice(cutFront); + + var chFrom = Pos(fromLine, cutFront); + var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); + if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { + replaceRange(cm.doc, newText, chFrom, chTo, "+input"); + return true; + } + }, + + ensurePolled: function() { + this.forceCompositionEnd(); + }, + reset: function() { + this.forceCompositionEnd(); + }, + forceCompositionEnd: function() { + if (!this.composing || this.composing.handled) return; + this.applyComposition(this.composing); + this.composing.handled = true; + this.div.blur(); + this.div.focus(); + }, + applyComposition: function(composing) { + if (this.cm.isReadOnly()) + operation(this.cm, regChange)(this.cm) + else if (composing.data && composing.data != composing.startData) + operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel); + }, + + setUneditable: function(node) { + node.contentEditable = "false" + }, + + onKeyPress: function(e) { + e.preventDefault(); + if (!this.cm.isReadOnly()) + operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); + }, + + readOnlyChanged: function(val) { + this.div.contentEditable = String(val != "nocursor") + }, + + onContextMenu: nothing, + resetPosition: nothing, + + needsContentAttribute: true + }, ContentEditableInput.prototype); + + function posToDOM(cm, pos) { + var view = findViewForLine(cm, pos.line); + if (!view || view.hidden) return null; + var line = getLine(cm.doc, pos.line); + var info = mapFromLineView(view, line, pos.line); + + var order = getOrder(line), side = "left"; + if (order) { + var partPos = getBidiPartAt(order, pos.ch); + side = partPos % 2 ? "right" : "left"; + } + var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); + result.offset = result.collapse == "right" ? result.end : result.start; + return result; + } + + function badPos(pos, bad) { if (bad) pos.bad = true; return pos; } + + function domToPos(cm, node, offset) { + var lineNode; + if (node == cm.display.lineDiv) { + lineNode = cm.display.lineDiv.childNodes[offset]; + if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true); + node = null; offset = 0; + } else { + for (lineNode = node;; lineNode = lineNode.parentNode) { + if (!lineNode || lineNode == cm.display.lineDiv) return null; + if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break; + } + } + for (var i = 0; i < cm.display.view.length; i++) { + var lineView = cm.display.view[i]; + if (lineView.node == lineNode) + return locateNodeInLineView(lineView, node, offset); + } + } + + function locateNodeInLineView(lineView, node, offset) { + var wrapper = lineView.text.firstChild, bad = false; + if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true); + if (node == wrapper) { + bad = true; + node = wrapper.childNodes[offset]; + offset = 0; + if (!node) { + var line = lineView.rest ? lst(lineView.rest) : lineView.line; + return badPos(Pos(lineNo(line), line.text.length), bad); + } + } + + var textNode = node.nodeType == 3 ? node : null, topNode = node; + if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { + textNode = node.firstChild; + if (offset) offset = textNode.nodeValue.length; + } + while (topNode.parentNode != wrapper) topNode = topNode.parentNode; + var measure = lineView.measure, maps = measure.maps; + + function find(textNode, topNode, offset) { + for (var i = -1; i < (maps ? maps.length : 0); i++) { + var map = i < 0 ? measure.map : maps[i]; + for (var j = 0; j < map.length; j += 3) { + var curNode = map[j + 2]; + if (curNode == textNode || curNode == topNode) { + var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); + var ch = map[j] + offset; + if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)]; + return Pos(line, ch); + } + } + } + } + var found = find(textNode, topNode, offset); + if (found) return badPos(found, bad); + + // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems + for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { + found = find(after, after.firstChild, 0); + if (found) + return badPos(Pos(found.line, found.ch - dist), bad); + else + dist += after.textContent.length; + } + for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) { + found = find(before, before.firstChild, -1); + if (found) + return badPos(Pos(found.line, found.ch + dist), bad); + else + dist += after.textContent.length; + } + } + + function domTextBetween(cm, from, to, fromLine, toLine) { + var text = "", closing = false, lineSep = cm.doc.lineSeparator(); + function recognizeMarker(id) { return function(marker) { return marker.id == id; }; } + function walk(node) { + if (node.nodeType == 1) { + var cmText = node.getAttribute("cm-text"); + if (cmText != null) { + if (cmText == "") cmText = node.textContent.replace(/\u200b/g, ""); + text += cmText; + return; + } + var markerID = node.getAttribute("cm-marker"), range; + if (markerID) { + var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); + if (found.length && (range = found[0].find())) + text += getBetween(cm.doc, range.from, range.to).join(lineSep); + return; + } + if (node.getAttribute("contenteditable") == "false") return; + for (var i = 0; i < node.childNodes.length; i++) + walk(node.childNodes[i]); + if (/^(pre|div|p)$/i.test(node.nodeName)) + closing = true; + } else if (node.nodeType == 3) { + var val = node.nodeValue; + if (!val) return; + if (closing) { + text += lineSep; + closing = false; + } + text += val; + } + } + for (;;) { + walk(from); + if (from == to) break; + from = from.nextSibling; + } + return text; + } + + CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; + + // SELECTION / CURSOR + + // Selection objects are immutable. A new one is created every time + // the selection changes. A selection is one or more non-overlapping + // (and non-touching) ranges, sorted, and an integer that indicates + // which one is the primary selection (the one that's scrolled into + // view, that getCursor returns, etc). + function Selection(ranges, primIndex) { + this.ranges = ranges; + this.primIndex = primIndex; + } + + Selection.prototype = { + primary: function() { return this.ranges[this.primIndex]; }, + equals: function(other) { + if (other == this) return true; + if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false; + for (var i = 0; i < this.ranges.length; i++) { + var here = this.ranges[i], there = other.ranges[i]; + if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false; + } + return true; + }, + deepCopy: function() { + for (var out = [], i = 0; i < this.ranges.length; i++) + out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); + return new Selection(out, this.primIndex); + }, + somethingSelected: function() { + for (var i = 0; i < this.ranges.length; i++) + if (!this.ranges[i].empty()) return true; + return false; + }, + contains: function(pos, end) { + if (!end) end = pos; + for (var i = 0; i < this.ranges.length; i++) { + var range = this.ranges[i]; + if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) + return i; + } + return -1; + } + }; + + function Range(anchor, head) { + this.anchor = anchor; this.head = head; + } + + Range.prototype = { + from: function() { return minPos(this.anchor, this.head); }, + to: function() { return maxPos(this.anchor, this.head); }, + empty: function() { + return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch; + } + }; + + // Take an unsorted, potentially overlapping set of ranges, and + // build a selection out of it. 'Consumes' ranges array (modifying + // it). + function normalizeSelection(ranges, primIndex) { + var prim = ranges[primIndex]; + ranges.sort(function(a, b) { return cmp(a.from(), b.from()); }); + primIndex = indexOf(ranges, prim); + for (var i = 1; i < ranges.length; i++) { + var cur = ranges[i], prev = ranges[i - 1]; + if (cmp(prev.to(), cur.from()) >= 0) { + var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); + var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; + if (i <= primIndex) --primIndex; + ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); + } + } + return new Selection(ranges, primIndex); + } + + function simpleSelection(anchor, head) { + return new Selection([new Range(anchor, head || anchor)], 0); + } + + // Most of the external API clips given positions to make sure they + // actually exist within the document. + function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));} + function clipPos(doc, pos) { + if (pos.line < doc.first) return Pos(doc.first, 0); + var last = doc.first + doc.size - 1; + if (pos.line > last) return Pos(last, getLine(doc, last).text.length); + return clipToLen(pos, getLine(doc, pos.line).text.length); + } + function clipToLen(pos, linelen) { + var ch = pos.ch; + if (ch == null || ch > linelen) return Pos(pos.line, linelen); + else if (ch < 0) return Pos(pos.line, 0); + else return pos; + } + function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;} + function clipPosArray(doc, array) { + for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]); + return out; + } + + // SELECTION UPDATES + + // The 'scroll' parameter given to many of these indicated whether + // the new cursor position should be scrolled into view after + // modifying the selection. + + // If shift is held or the extend flag is set, extends a range to + // include a given position (and optionally a second position). + // Otherwise, simply returns the range between the given positions. + // Used for cursor motion and such. + function extendRange(doc, range, head, other) { + if (doc.cm && doc.cm.display.shift || doc.extend) { + var anchor = range.anchor; + if (other) { + var posBefore = cmp(head, anchor) < 0; + if (posBefore != (cmp(other, anchor) < 0)) { + anchor = head; + head = other; + } else if (posBefore != (cmp(head, other) < 0)) { + head = other; + } + } + return new Range(anchor, head); + } else { + return new Range(other || head, head); + } + } + + // Extend the primary selection range, discard the rest. + function extendSelection(doc, head, other, options) { + setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options); + } + + // Extend all selections (pos is an array of selections with length + // equal the number of selections) + function extendSelections(doc, heads, options) { + for (var out = [], i = 0; i < doc.sel.ranges.length; i++) + out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null); + var newSel = normalizeSelection(out, doc.sel.primIndex); + setSelection(doc, newSel, options); + } + + // Updates a single range in the selection. + function replaceOneSelection(doc, i, range, options) { + var ranges = doc.sel.ranges.slice(0); + ranges[i] = range; + setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options); + } + + // Reset the selection to a single range. + function setSimpleSelection(doc, anchor, head, options) { + setSelection(doc, simpleSelection(anchor, head), options); + } + + // Give beforeSelectionChange handlers a change to influence a + // selection update. + function filterSelectionChange(doc, sel, options) { + var obj = { + ranges: sel.ranges, + update: function(ranges) { + this.ranges = []; + for (var i = 0; i < ranges.length; i++) + this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), + clipPos(doc, ranges[i].head)); + }, + origin: options && options.origin + }; + signal(doc, "beforeSelectionChange", doc, obj); + if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj); + if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1); + else return sel; + } + + function setSelectionReplaceHistory(doc, sel, options) { + var done = doc.history.done, last = lst(done); + if (last && last.ranges) { + done[done.length - 1] = sel; + setSelectionNoUndo(doc, sel, options); + } else { + setSelection(doc, sel, options); + } + } + + // Set a new selection. + function setSelection(doc, sel, options) { + setSelectionNoUndo(doc, sel, options); + addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); + } + + function setSelectionNoUndo(doc, sel, options) { + if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) + sel = filterSelectionChange(doc, sel, options); + + var bias = options && options.bias || + (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); + setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); + + if (!(options && options.scroll === false) && doc.cm) + ensureCursorVisible(doc.cm); + } + + function setSelectionInner(doc, sel) { + if (sel.equals(doc.sel)) return; + + doc.sel = sel; + + if (doc.cm) { + doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true; + signalCursorActivity(doc.cm); + } + signalLater(doc, "cursorActivity", doc); + } + + // Verify that the selection does not partially select any atomic + // marked ranges. + function reCheckSelection(doc) { + setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll); + } + + // Return a selection that does not partially select any atomic + // ranges. + function skipAtomicInSelection(doc, sel, bias, mayClear) { + var out; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; + var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); + var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear); + if (out || newAnchor != range.anchor || newHead != range.head) { + if (!out) out = sel.ranges.slice(0, i); + out[i] = new Range(newAnchor, newHead); + } + } + return out ? normalizeSelection(out, sel.primIndex) : sel; + } + + function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { + var line = getLine(doc, pos.line); + if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], m = sp.marker; + if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && + (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + if (mayClear) { + signal(m, "beforeCursorEnter"); + if (m.explicitlyCleared) { + if (!line.markedSpans) break; + else {--i; continue;} + } + } + if (!m.atomic) continue; + + if (oldPos) { + var near = m.find(dir < 0 ? 1 : -1), diff; + if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) + near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); + if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) + return skipAtomicInner(doc, near, pos, dir, mayClear); + } + + var far = m.find(dir < 0 ? -1 : 1); + if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) + far = movePos(doc, far, dir, far.line == pos.line ? line : null); + return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null; + } + } + return pos; + } + + // Ensure a given position is not inside an atomic range. + function skipAtomic(doc, pos, oldPos, bias, mayClear) { + var dir = bias || 1; + var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || + skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)); + if (!found) { + doc.cantEdit = true; + return Pos(doc.first, 0); + } + return found; + } + + function movePos(doc, pos, dir, line) { + if (dir < 0 && pos.ch == 0) { + if (pos.line > doc.first) return clipPos(doc, Pos(pos.line - 1)); + else return null; + } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { + if (pos.line < doc.first + doc.size - 1) return Pos(pos.line + 1, 0); + else return null; + } else { + return new Pos(pos.line, pos.ch + dir); + } + } + + // SELECTION DRAWING + + function updateSelection(cm) { + cm.display.input.showSelection(cm.display.input.prepareSelection()); + } + + function prepareSelection(cm, primary) { + var doc = cm.doc, result = {}; + var curFragment = result.cursors = document.createDocumentFragment(); + var selFragment = result.selection = document.createDocumentFragment(); + + for (var i = 0; i < doc.sel.ranges.length; i++) { + if (primary === false && i == doc.sel.primIndex) continue; + var range = doc.sel.ranges[i]; + if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) continue; + var collapsed = range.empty(); + if (collapsed || cm.options.showCursorWhenSelecting) + drawSelectionCursor(cm, range.head, curFragment); + if (!collapsed) + drawSelectionRange(cm, range, selFragment); + } + return result; + } + + // Draws a cursor for the given range + function drawSelectionCursor(cm, head, output) { + var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); + + var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); + cursor.style.left = pos.left + "px"; + cursor.style.top = pos.top + "px"; + cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; + + if (pos.other) { + // Secondary cursor, shown when on a 'jump' in bi-directional text + var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); + otherCursor.style.display = ""; + otherCursor.style.left = pos.other.left + "px"; + otherCursor.style.top = pos.other.top + "px"; + otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; + } + } + + // Draws the given range as a highlighted selection + function drawSelectionRange(cm, range, output) { + var display = cm.display, doc = cm.doc; + var fragment = document.createDocumentFragment(); + var padding = paddingH(cm.display), leftSide = padding.left; + var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; + + function add(left, top, width, bottom) { + if (top < 0) top = 0; + top = Math.round(top); + bottom = Math.round(bottom); + fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + + "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) + + "px; height: " + (bottom - top) + "px")); + } + + function drawForLine(line, fromArg, toArg) { + var lineObj = getLine(doc, line); + var lineLen = lineObj.text.length; + var start, end; + function coords(ch, bias) { + return charCoords(cm, Pos(line, ch), "div", lineObj, bias); + } + + iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) { + var leftPos = coords(from, "left"), rightPos, left, right; + if (from == to) { + rightPos = leftPos; + left = right = leftPos.left; + } else { + rightPos = coords(to - 1, "right"); + if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; } + left = leftPos.left; + right = rightPos.right; + } + if (fromArg == null && from == 0) left = leftSide; + if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part + add(left, leftPos.top, null, leftPos.bottom); + left = leftSide; + if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); + } + if (toArg == null && to == lineLen) right = rightSide; + if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) + start = leftPos; + if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) + end = rightPos; + if (left < leftSide + 1) left = leftSide; + add(left, rightPos.top, right - left, rightPos.bottom); + }); + return {start: start, end: end}; + } + + var sFrom = range.from(), sTo = range.to(); + if (sFrom.line == sTo.line) { + drawForLine(sFrom.line, sFrom.ch, sTo.ch); + } else { + var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); + var singleVLine = visualLine(fromLine) == visualLine(toLine); + var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; + var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; + if (singleVLine) { + if (leftEnd.top < rightStart.top - 2) { + add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); + add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); + } else { + add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); + } + } + if (leftEnd.bottom < rightStart.top) + add(leftSide, leftEnd.bottom, null, rightStart.top); + } + + output.appendChild(fragment); + } + + // Cursor-blinking + function restartBlink(cm) { + if (!cm.state.focused) return; + var display = cm.display; + clearInterval(display.blinker); + var on = true; + display.cursorDiv.style.visibility = ""; + if (cm.options.cursorBlinkRate > 0) + display.blinker = setInterval(function() { + display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; + }, cm.options.cursorBlinkRate); + else if (cm.options.cursorBlinkRate < 0) + display.cursorDiv.style.visibility = "hidden"; + } + + // HIGHLIGHT WORKER + + function startWorker(cm, time) { + if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo) + cm.state.highlight.set(time, bind(highlightWorker, cm)); + } + + function highlightWorker(cm) { + var doc = cm.doc; + if (doc.frontier < doc.first) doc.frontier = doc.first; + if (doc.frontier >= cm.display.viewTo) return; + var end = +new Date + cm.options.workTime; + var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); + var changedLines = []; + + doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) { + if (doc.frontier >= cm.display.viewFrom) { // Visible + var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength; + var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true); + line.styles = highlighted.styles; + var oldCls = line.styleClasses, newCls = highlighted.classes; + if (newCls) line.styleClasses = newCls; + else if (oldCls) line.styleClasses = null; + var ischange = !oldStyles || oldStyles.length != line.styles.length || + oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); + for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; + if (ischange) changedLines.push(doc.frontier); + line.stateAfter = tooLong ? state : copyState(doc.mode, state); + } else { + if (line.text.length <= cm.options.maxHighlightLength) + processLine(cm, line.text, state); + line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; + } + ++doc.frontier; + if (+new Date > end) { + startWorker(cm, cm.options.workDelay); + return true; + } + }); + if (changedLines.length) runInOp(cm, function() { + for (var i = 0; i < changedLines.length; i++) + regLineChange(cm, changedLines[i], "text"); + }); + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(cm, n, precise) { + var minindent, minline, doc = cm.doc; + var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); + for (var search = n; search > lim; --search) { + if (search <= doc.first) return doc.first; + var line = getLine(doc, search - 1); + if (line.stateAfter && (!precise || search <= doc.frontier)) return search; + var indented = countColumn(line.text, null, cm.options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline; + } + + function getStateBefore(cm, n, precise) { + var doc = cm.doc, display = cm.display; + if (!doc.mode.startState) return true; + var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter; + if (!state) state = startState(doc.mode); + else state = copyState(doc.mode, state); + doc.iter(pos, n, function(line) { + processLine(cm, line.text, state); + var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo; + line.stateAfter = save ? copyState(doc.mode, state) : null; + ++pos; + }); + if (precise) doc.frontier = pos; + return state; + } + + // POSITION MEASUREMENT + + function paddingTop(display) {return display.lineSpace.offsetTop;} + function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;} + function paddingH(display) { + if (display.cachedPaddingH) return display.cachedPaddingH; + var e = removeChildrenAndAdd(display.measure, elt("pre", "x")); + var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; + var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; + if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data; + return data; + } + + function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; } + function displayWidth(cm) { + return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth; + } + function displayHeight(cm) { + return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight; + } + + // Ensure the lineView.wrapping.heights array is populated. This is + // an array of bottom offsets for the lines that make up a drawn + // line. When lineWrapping is on, there might be more than one + // height. + function ensureLineHeights(cm, lineView, rect) { + var wrapping = cm.options.lineWrapping; + var curWidth = wrapping && displayWidth(cm); + if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { + var heights = lineView.measure.heights = []; + if (wrapping) { + lineView.measure.width = curWidth; + var rects = lineView.text.firstChild.getClientRects(); + for (var i = 0; i < rects.length - 1; i++) { + var cur = rects[i], next = rects[i + 1]; + if (Math.abs(cur.bottom - next.bottom) > 2) + heights.push((cur.bottom + next.top) / 2 - rect.top); + } + } + heights.push(rect.bottom - rect.top); + } + } + + // Find a line map (mapping character offsets to text nodes) and a + // measurement cache for the given line number. (A line view might + // contain multiple lines when collapsed ranges are present.) + function mapFromLineView(lineView, line, lineN) { + if (lineView.line == line) + return {map: lineView.measure.map, cache: lineView.measure.cache}; + for (var i = 0; i < lineView.rest.length; i++) + if (lineView.rest[i] == line) + return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]}; + for (var i = 0; i < lineView.rest.length; i++) + if (lineNo(lineView.rest[i]) > lineN) + return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true}; + } + + // Render a line into the hidden node display.externalMeasured. Used + // when measurement is needed for a line that's not in the viewport. + function updateExternalMeasurement(cm, line) { + line = visualLine(line); + var lineN = lineNo(line); + var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); + view.lineN = lineN; + var built = view.built = buildLineContent(cm, view); + view.text = built.pre; + removeChildrenAndAdd(cm.display.lineMeasure, built.pre); + return view; + } + + // Get a {top, bottom, left, right} box (in line-local coordinates) + // for a given character. + function measureChar(cm, line, ch, bias) { + return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias); + } + + // Find a line view that corresponds to the given line number. + function findViewForLine(cm, lineN) { + if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) + return cm.display.view[findViewIndex(cm, lineN)]; + var ext = cm.display.externalMeasured; + if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) + return ext; + } + + // Measurement can be split in two steps, the set-up work that + // applies to the whole line, and the measurement of the actual + // character. Functions like coordsChar, that need to do a lot of + // measurements in a row, can thus ensure that the set-up work is + // only done once. + function prepareMeasureForLine(cm, line) { + var lineN = lineNo(line); + var view = findViewForLine(cm, lineN); + if (view && !view.text) { + view = null; + } else if (view && view.changes) { + updateLineForChanges(cm, view, lineN, getDimensions(cm)); + cm.curOp.forceUpdate = true; + } + if (!view) + view = updateExternalMeasurement(cm, line); + + var info = mapFromLineView(view, line, lineN); + return { + line: line, view: view, rect: null, + map: info.map, cache: info.cache, before: info.before, + hasHeights: false + }; + } + + // Given a prepared measurement object, measures the position of an + // actual character (or fetches it from the cache). + function measureCharPrepared(cm, prepared, ch, bias, varHeight) { + if (prepared.before) ch = -1; + var key = ch + (bias || ""), found; + if (prepared.cache.hasOwnProperty(key)) { + found = prepared.cache[key]; + } else { + if (!prepared.rect) + prepared.rect = prepared.view.text.getBoundingClientRect(); + if (!prepared.hasHeights) { + ensureLineHeights(cm, prepared.view, prepared.rect); + prepared.hasHeights = true; + } + found = measureCharInner(cm, prepared, ch, bias); + if (!found.bogus) prepared.cache[key] = found; + } + return {left: found.left, right: found.right, + top: varHeight ? found.rtop : found.top, + bottom: varHeight ? found.rbottom : found.bottom}; + } + + var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; + + function nodeAndOffsetInLineMap(map, ch, bias) { + var node, start, end, collapse; + // First, search the line map for the text node corresponding to, + // or closest to, the target character. + for (var i = 0; i < map.length; i += 3) { + var mStart = map[i], mEnd = map[i + 1]; + if (ch < mStart) { + start = 0; end = 1; + collapse = "left"; + } else if (ch < mEnd) { + start = ch - mStart; + end = start + 1; + } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { + end = mEnd - mStart; + start = end - 1; + if (ch >= mEnd) collapse = "right"; + } + if (start != null) { + node = map[i + 2]; + if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) + collapse = bias; + if (bias == "left" && start == 0) + while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { + node = map[(i -= 3) + 2]; + collapse = "left"; + } + if (bias == "right" && start == mEnd - mStart) + while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { + node = map[(i += 3) + 2]; + collapse = "right"; + } + break; + } + } + return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}; + } + + function getUsefulRect(rects, bias) { + var rect = nullRect + if (bias == "left") for (var i = 0; i < rects.length; i++) { + if ((rect = rects[i]).left != rect.right) break + } else for (var i = rects.length - 1; i >= 0; i--) { + if ((rect = rects[i]).left != rect.right) break + } + return rect + } + + function measureCharInner(cm, prepared, ch, bias) { + var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); + var node = place.node, start = place.start, end = place.end, collapse = place.collapse; + + var rect; + if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. + for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned + while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start; + while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end; + if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) + rect = node.parentNode.getBoundingClientRect(); + else + rect = getUsefulRect(range(node, start, end).getClientRects(), bias) + if (rect.left || rect.right || start == 0) break; + end = start; + start = start - 1; + collapse = "right"; + } + if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); + } else { // If it is a widget, simply get the box for the whole widget. + if (start > 0) collapse = bias = "right"; + var rects; + if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) + rect = rects[bias == "right" ? rects.length - 1 : 0]; + else + rect = node.getBoundingClientRect(); + } + if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { + var rSpan = node.parentNode.getClientRects()[0]; + if (rSpan) + rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; + else + rect = nullRect; + } + + var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; + var mid = (rtop + rbot) / 2; + var heights = prepared.view.measure.heights; + for (var i = 0; i < heights.length - 1; i++) + if (mid < heights[i]) break; + var top = i ? heights[i - 1] : 0, bot = heights[i]; + var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, + right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, + top: top, bottom: bot}; + if (!rect.left && !rect.right) result.bogus = true; + if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } + + return result; + } + + // Work around problem with bounding client rects on ranges being + // returned incorrectly when zoomed on IE10 and below. + function maybeUpdateRectForZooming(measure, rect) { + if (!window.screen || screen.logicalXDPI == null || + screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) + return rect; + var scaleX = screen.logicalXDPI / screen.deviceXDPI; + var scaleY = screen.logicalYDPI / screen.deviceYDPI; + return {left: rect.left * scaleX, right: rect.right * scaleX, + top: rect.top * scaleY, bottom: rect.bottom * scaleY}; + } + + function clearLineMeasurementCacheFor(lineView) { + if (lineView.measure) { + lineView.measure.cache = {}; + lineView.measure.heights = null; + if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) + lineView.measure.caches[i] = {}; + } + } + + function clearLineMeasurementCache(cm) { + cm.display.externalMeasure = null; + removeChildren(cm.display.lineMeasure); + for (var i = 0; i < cm.display.view.length; i++) + clearLineMeasurementCacheFor(cm.display.view[i]); + } + + function clearCaches(cm) { + clearLineMeasurementCache(cm); + cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; + if (!cm.options.lineWrapping) cm.display.maxLineChanged = true; + cm.display.lineNumChars = null; + } + + function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; } + function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; } + + // Converts a {top, bottom, left, right} box from line-local + // coordinates into another coordinate system. Context may be one of + // "line", "div" (display.lineDiv), "local"/null (editor), "window", + // or "page". + function intoCoordSystem(cm, lineObj, rect, context) { + if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) { + var size = widgetHeight(lineObj.widgets[i]); + rect.top += size; rect.bottom += size; + } + if (context == "line") return rect; + if (!context) context = "local"; + var yOff = heightAtLine(lineObj); + if (context == "local") yOff += paddingTop(cm.display); + else yOff -= cm.display.viewOffset; + if (context == "page" || context == "window") { + var lOff = cm.display.lineSpace.getBoundingClientRect(); + yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); + var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); + rect.left += xOff; rect.right += xOff; + } + rect.top += yOff; rect.bottom += yOff; + return rect; + } + + // Coverts a box from "div" coords to another coordinate system. + // Context may be "window", "page", "div", or "local"/null. + function fromCoordSystem(cm, coords, context) { + if (context == "div") return coords; + var left = coords.left, top = coords.top; + // First move into "page" coordinate system + if (context == "page") { + left -= pageScrollX(); + top -= pageScrollY(); + } else if (context == "local" || !context) { + var localBox = cm.display.sizer.getBoundingClientRect(); + left += localBox.left; + top += localBox.top; + } + + var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); + return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}; + } + + function charCoords(cm, pos, context, lineObj, bias) { + if (!lineObj) lineObj = getLine(cm.doc, pos.line); + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context); + } + + // Returns a box for a given cursor position, which may have an + // 'other' property containing the position of the secondary cursor + // on a bidi boundary. + function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { + lineObj = lineObj || getLine(cm.doc, pos.line); + if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj); + function get(ch, right) { + var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); + if (right) m.left = m.right; else m.right = m.left; + return intoCoordSystem(cm, lineObj, m, context); + } + function getBidi(ch, partPos) { + var part = order[partPos], right = part.level % 2; + if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) { + part = order[--partPos]; + ch = bidiRight(part) - (part.level % 2 ? 0 : 1); + right = true; + } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) { + part = order[++partPos]; + ch = bidiLeft(part) - part.level % 2; + right = false; + } + if (right && ch == part.to && ch > part.from) return get(ch - 1); + return get(ch, right); + } + var order = getOrder(lineObj), ch = pos.ch; + if (!order) return get(ch); + var partPos = getBidiPartAt(order, ch); + var val = getBidi(ch, partPos); + if (bidiOther != null) val.other = getBidi(ch, bidiOther); + return val; + } + + // Used to cheaply estimate the coordinates for a position. Used for + // intermediate scroll updates. + function estimateCoords(cm, pos) { + var left = 0, pos = clipPos(cm.doc, pos); + if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch; + var lineObj = getLine(cm.doc, pos.line); + var top = heightAtLine(lineObj) + paddingTop(cm.display); + return {left: left, right: left, top: top, bottom: top + lineObj.height}; + } + + // Positions returned by coordsChar contain some extra information. + // xRel is the relative x position of the input coordinates compared + // to the found position (so xRel > 0 means the coordinates are to + // the right of the character position, for example). When outside + // is true, that means the coordinates lie outside the line's + // vertical range. + function PosWithInfo(line, ch, outside, xRel) { + var pos = Pos(line, ch); + pos.xRel = xRel; + if (outside) pos.outside = true; + return pos; + } + + // Compute the character position closest to the given coordinates. + // Input must be lineSpace-local ("div" coordinate system). + function coordsChar(cm, x, y) { + var doc = cm.doc; + y += cm.display.viewOffset; + if (y < 0) return PosWithInfo(doc.first, 0, true, -1); + var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; + if (lineN > last) + return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1); + if (x < 0) x = 0; + + var lineObj = getLine(doc, lineN); + for (;;) { + var found = coordsCharInner(cm, lineObj, lineN, x, y); + var merged = collapsedSpanAtEnd(lineObj); + var mergedPos = merged && merged.find(0, true); + if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) + lineN = lineNo(lineObj = mergedPos.to.line); + else + return found; + } + } + + function coordsCharInner(cm, lineObj, lineNo, x, y) { + var innerOff = y - heightAtLine(lineObj); + var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth; + var preparedMeasure = prepareMeasureForLine(cm, lineObj); + + function getX(ch) { + var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure); + wrongLine = true; + if (innerOff > sp.bottom) return sp.left - adjust; + else if (innerOff < sp.top) return sp.left + adjust; + else wrongLine = false; + return sp.left; + } + + var bidi = getOrder(lineObj), dist = lineObj.text.length; + var from = lineLeft(lineObj), to = lineRight(lineObj); + var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine; + + if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1); + // Do a binary search between these bounds. + for (;;) { + if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { + var ch = x < fromX || x - fromX <= toX - x ? from : to; + var outside = ch == from ? fromOutside : toOutside + var xDiff = x - (ch == from ? fromX : toX); + // This is a kludge to handle the case where the coordinates + // are after a line-wrapped line. We should replace it with a + // more general handling of cursor positions around line + // breaks. (Issue #4078) + if (toOutside && !bidi && !/\s/.test(lineObj.text.charAt(ch)) && xDiff > 0 && + ch < lineObj.text.length && preparedMeasure.view.measure.heights.length > 1) { + var charSize = measureCharPrepared(cm, preparedMeasure, ch, "right"); + if (innerOff <= charSize.bottom && innerOff >= charSize.top && Math.abs(x - charSize.right) < xDiff) { + outside = false + ch++ + xDiff = x - charSize.right + } + } + while (isExtendingChar(lineObj.text.charAt(ch))) ++ch; + var pos = PosWithInfo(lineNo, ch, outside, xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0); + return pos; + } + var step = Math.ceil(dist / 2), middle = from + step; + if (bidi) { + middle = from; + for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1); + } + var middleX = getX(middle); + if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;} + else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;} + } + } + + var measureText; + // Compute the default text height. + function textHeight(display) { + if (display.cachedTextHeight != null) return display.cachedTextHeight; + if (measureText == null) { + measureText = elt("pre"); + // Measure a bunch of lines, for browsers that compute + // fractional heights. + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")); + measureText.appendChild(elt("br")); + } + measureText.appendChild(document.createTextNode("x")); + } + removeChildrenAndAdd(display.measure, measureText); + var height = measureText.offsetHeight / 50; + if (height > 3) display.cachedTextHeight = height; + removeChildren(display.measure); + return height || 1; + } + + // Compute the default character width. + function charWidth(display) { + if (display.cachedCharWidth != null) return display.cachedCharWidth; + var anchor = elt("span", "xxxxxxxxxx"); + var pre = elt("pre", [anchor]); + removeChildrenAndAdd(display.measure, pre); + var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; + if (width > 2) display.cachedCharWidth = width; + return width || 10; + } + + // OPERATIONS + + // Operations are used to wrap a series of changes to the editor + // state in such a way that each change won't have to update the + // cursor and display (which would be awkward, slow, and + // error-prone). Instead, display updates are batched and then all + // combined and executed at once. + + var operationGroup = null; + + var nextOpId = 0; + // Start a new operation. + function startOperation(cm) { + cm.curOp = { + cm: cm, + viewChanged: false, // Flag that indicates that lines might need to be redrawn + startHeight: cm.doc.height, // Used to detect need to update scrollbar + forceUpdate: false, // Used to force a redraw + updateInput: null, // Whether to reset the input textarea + typing: false, // Whether this reset should be careful to leave existing text (for compositing) + changeObjs: null, // Accumulated changes, for firing change events + cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on + cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already + selectionChanged: false, // Whether the selection needs to be redrawn + updateMaxLine: false, // Set when the widest line needs to be determined anew + scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet + scrollToPos: null, // Used to scroll to a specific position + focus: false, + id: ++nextOpId // Unique ID + }; + if (operationGroup) { + operationGroup.ops.push(cm.curOp); + } else { + cm.curOp.ownsGroup = operationGroup = { + ops: [cm.curOp], + delayedCallbacks: [] + }; + } + } + + function fireCallbacksForOps(group) { + // Calls delayed callbacks and cursorActivity handlers until no + // new ones appear + var callbacks = group.delayedCallbacks, i = 0; + do { + for (; i < callbacks.length; i++) + callbacks[i].call(null); + for (var j = 0; j < group.ops.length; j++) { + var op = group.ops[j]; + if (op.cursorActivityHandlers) + while (op.cursorActivityCalled < op.cursorActivityHandlers.length) + op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); + } + } while (i < callbacks.length); + } + + // Finish an operation, updating the display and signalling delayed events + function endOperation(cm) { + var op = cm.curOp, group = op.ownsGroup; + if (!group) return; + + try { fireCallbacksForOps(group); } + finally { + operationGroup = null; + for (var i = 0; i < group.ops.length; i++) + group.ops[i].cm.curOp = null; + endOperations(group); + } + } + + // The DOM updates done when an operation finishes are batched so + // that the minimum number of relayouts are required. + function endOperations(group) { + var ops = group.ops; + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_R1(ops[i]); + for (var i = 0; i < ops.length; i++) // Write DOM (maybe) + endOperation_W1(ops[i]); + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_R2(ops[i]); + for (var i = 0; i < ops.length; i++) // Write DOM (maybe) + endOperation_W2(ops[i]); + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_finish(ops[i]); + } + + function endOperation_R1(op) { + var cm = op.cm, display = cm.display; + maybeClipScrollbars(cm); + if (op.updateMaxLine) findMaxLine(cm); + + op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || + op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || + op.scrollToPos.to.line >= display.viewTo) || + display.maxLineChanged && cm.options.lineWrapping; + op.update = op.mustUpdate && + new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); + } + + function endOperation_W1(op) { + op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); + } + + function endOperation_R2(op) { + var cm = op.cm, display = cm.display; + if (op.updatedDisplay) updateHeightsInViewport(cm); + + op.barMeasure = measureForScrollbars(cm); + + // If the max line changed since it was last measured, measure it, + // and ensure the document's width matches it. + // updateDisplay_W2 will use these properties to do the actual resizing + if (display.maxLineChanged && !cm.options.lineWrapping) { + op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; + cm.display.sizerWidth = op.adjustWidthTo; + op.barMeasure.scrollWidth = + Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); + op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); + } + + if (op.updatedDisplay || op.selectionChanged) + op.preparedSelection = display.input.prepareSelection(op.focus); + } + + function endOperation_W2(op) { + var cm = op.cm; + + if (op.adjustWidthTo != null) { + cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; + if (op.maxScrollLeft < cm.doc.scrollLeft) + setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); + cm.display.maxLineChanged = false; + } + + var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()) + if (op.preparedSelection) + cm.display.input.showSelection(op.preparedSelection, takeFocus); + if (op.updatedDisplay || op.startHeight != cm.doc.height) + updateScrollbars(cm, op.barMeasure); + if (op.updatedDisplay) + setDocumentHeight(cm, op.barMeasure); + + if (op.selectionChanged) restartBlink(cm); + + if (cm.state.focused && op.updateInput) + cm.display.input.reset(op.typing); + if (takeFocus) ensureFocus(op.cm); + } + + function endOperation_finish(op) { + var cm = op.cm, display = cm.display, doc = cm.doc; + + if (op.updatedDisplay) postUpdateDisplay(cm, op.update); + + // Abort mouse wheel delta measurement, when scrolling explicitly + if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) + display.wheelStartX = display.wheelStartY = null; + + // Propagate the scroll position to the actual DOM scroller + if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) { + doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)); + display.scrollbars.setScrollTop(doc.scrollTop); + display.scroller.scrollTop = doc.scrollTop; + } + if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) { + doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft)); + display.scrollbars.setScrollLeft(doc.scrollLeft); + display.scroller.scrollLeft = doc.scrollLeft; + alignHorizontally(cm); + } + // If we need to scroll a specific position into view, do so. + if (op.scrollToPos) { + var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), + clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); + if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords); + } + + // Fire events for markers that are hidden/unidden by editing or + // undoing + var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; + if (hidden) for (var i = 0; i < hidden.length; ++i) + if (!hidden[i].lines.length) signal(hidden[i], "hide"); + if (unhidden) for (var i = 0; i < unhidden.length; ++i) + if (unhidden[i].lines.length) signal(unhidden[i], "unhide"); + + if (display.wrapper.offsetHeight) + doc.scrollTop = cm.display.scroller.scrollTop; + + // Fire change events, and delayed event handlers + if (op.changeObjs) + signal(cm, "changes", cm, op.changeObjs); + if (op.update) + op.update.finish(); + } + + // Run the given function in an operation + function runInOp(cm, f) { + if (cm.curOp) return f(); + startOperation(cm); + try { return f(); } + finally { endOperation(cm); } + } + // Wraps a function in an operation. Returns the wrapped function. + function operation(cm, f) { + return function() { + if (cm.curOp) return f.apply(cm, arguments); + startOperation(cm); + try { return f.apply(cm, arguments); } + finally { endOperation(cm); } + }; + } + // Used to add methods to editor and doc instances, wrapping them in + // operations. + function methodOp(f) { + return function() { + if (this.curOp) return f.apply(this, arguments); + startOperation(this); + try { return f.apply(this, arguments); } + finally { endOperation(this); } + }; + } + function docMethodOp(f) { + return function() { + var cm = this.cm; + if (!cm || cm.curOp) return f.apply(this, arguments); + startOperation(cm); + try { return f.apply(this, arguments); } + finally { endOperation(cm); } + }; + } + + // VIEW TRACKING + + // These objects are used to represent the visible (currently drawn) + // part of the document. A LineView may correspond to multiple + // logical lines, if those are connected by collapsed ranges. + function LineView(doc, line, lineN) { + // The starting line + this.line = line; + // Continuing lines, if any + this.rest = visualLineContinued(line); + // Number of logical lines in this visual line + this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; + this.node = this.text = null; + this.hidden = lineIsHidden(doc, line); + } + + // Create a range of LineView objects for the given lines. + function buildViewArray(cm, from, to) { + var array = [], nextPos; + for (var pos = from; pos < to; pos = nextPos) { + var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); + nextPos = pos + view.size; + array.push(view); + } + return array; + } + + // Updates the display.view data structure for a given change to the + // document. From and to are in pre-change coordinates. Lendiff is + // the amount of lines added or subtracted by the change. This is + // used for changes that span multiple lines, or change the way + // lines are divided into visual lines. regLineChange (below) + // registers single-line changes. + function regChange(cm, from, to, lendiff) { + if (from == null) from = cm.doc.first; + if (to == null) to = cm.doc.first + cm.doc.size; + if (!lendiff) lendiff = 0; + + var display = cm.display; + if (lendiff && to < display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers > from)) + display.updateLineNumbers = from; + + cm.curOp.viewChanged = true; + + if (from >= display.viewTo) { // Change after + if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) + resetView(cm); + } else if (to <= display.viewFrom) { // Change before + if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { + resetView(cm); + } else { + display.viewFrom += lendiff; + display.viewTo += lendiff; + } + } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap + resetView(cm); + } else if (from <= display.viewFrom) { // Top overlap + var cut = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cut) { + display.view = display.view.slice(cut.index); + display.viewFrom = cut.lineN; + display.viewTo += lendiff; + } else { + resetView(cm); + } + } else if (to >= display.viewTo) { // Bottom overlap + var cut = viewCuttingPoint(cm, from, from, -1); + if (cut) { + display.view = display.view.slice(0, cut.index); + display.viewTo = cut.lineN; + } else { + resetView(cm); + } + } else { // Gap in the middle + var cutTop = viewCuttingPoint(cm, from, from, -1); + var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cutTop && cutBot) { + display.view = display.view.slice(0, cutTop.index) + .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) + .concat(display.view.slice(cutBot.index)); + display.viewTo += lendiff; + } else { + resetView(cm); + } + } + + var ext = display.externalMeasured; + if (ext) { + if (to < ext.lineN) + ext.lineN += lendiff; + else if (from < ext.lineN + ext.size) + display.externalMeasured = null; + } + } + + // Register a change to a single line. Type must be one of "text", + // "gutter", "class", "widget" + function regLineChange(cm, line, type) { + cm.curOp.viewChanged = true; + var display = cm.display, ext = cm.display.externalMeasured; + if (ext && line >= ext.lineN && line < ext.lineN + ext.size) + display.externalMeasured = null; + + if (line < display.viewFrom || line >= display.viewTo) return; + var lineView = display.view[findViewIndex(cm, line)]; + if (lineView.node == null) return; + var arr = lineView.changes || (lineView.changes = []); + if (indexOf(arr, type) == -1) arr.push(type); + } + + // Clear the view. + function resetView(cm) { + cm.display.viewFrom = cm.display.viewTo = cm.doc.first; + cm.display.view = []; + cm.display.viewOffset = 0; + } + + // Find the view element corresponding to a given line. Return null + // when the line isn't visible. + function findViewIndex(cm, n) { + if (n >= cm.display.viewTo) return null; + n -= cm.display.viewFrom; + if (n < 0) return null; + var view = cm.display.view; + for (var i = 0; i < view.length; i++) { + n -= view[i].size; + if (n < 0) return i; + } + } + + function viewCuttingPoint(cm, oldN, newN, dir) { + var index = findViewIndex(cm, oldN), diff, view = cm.display.view; + if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) + return {index: index, lineN: newN}; + for (var i = 0, n = cm.display.viewFrom; i < index; i++) + n += view[i].size; + if (n != oldN) { + if (dir > 0) { + if (index == view.length - 1) return null; + diff = (n + view[index].size) - oldN; + index++; + } else { + diff = n - oldN; + } + oldN += diff; newN += diff; + } + while (visualLineNo(cm.doc, newN) != newN) { + if (index == (dir < 0 ? 0 : view.length - 1)) return null; + newN += dir * view[index - (dir < 0 ? 1 : 0)].size; + index += dir; + } + return {index: index, lineN: newN}; + } + + // Force the view to cover a given range, adding empty view element + // or clipping off existing ones as needed. + function adjustView(cm, from, to) { + var display = cm.display, view = display.view; + if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { + display.view = buildViewArray(cm, from, to); + display.viewFrom = from; + } else { + if (display.viewFrom > from) + display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); + else if (display.viewFrom < from) + display.view = display.view.slice(findViewIndex(cm, from)); + display.viewFrom = from; + if (display.viewTo < to) + display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); + else if (display.viewTo > to) + display.view = display.view.slice(0, findViewIndex(cm, to)); + } + display.viewTo = to; + } + + // Count the number of lines in the view whose DOM representation is + // out of date (or nonexistent). + function countDirtyView(cm) { + var view = cm.display.view, dirty = 0; + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty; + } + return dirty; + } + + // EVENT HANDLERS + + // Attach the necessary event handlers when initializing the editor + function registerEventHandlers(cm) { + var d = cm.display; + on(d.scroller, "mousedown", operation(cm, onMouseDown)); + // Older IE's will not fire a second mousedown for a double click + if (ie && ie_version < 11) + on(d.scroller, "dblclick", operation(cm, function(e) { + if (signalDOMEvent(cm, e)) return; + var pos = posFromMouse(cm, e); + if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; + e_preventDefault(e); + var word = cm.findWordAt(pos); + extendSelection(cm.doc, word.anchor, word.head); + })); + else + on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); }); + // Some browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for these browsers. + if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); + + // Used to suppress mouse event handling when a touch happens + var touchFinished, prevTouch = {end: 0}; + function finishTouch() { + if (d.activeTouch) { + touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000); + prevTouch = d.activeTouch; + prevTouch.end = +new Date; + } + }; + function isMouseLikeTouchEvent(e) { + if (e.touches.length != 1) return false; + var touch = e.touches[0]; + return touch.radiusX <= 1 && touch.radiusY <= 1; + } + function farAway(touch, other) { + if (other.left == null) return true; + var dx = other.left - touch.left, dy = other.top - touch.top; + return dx * dx + dy * dy > 20 * 20; + } + on(d.scroller, "touchstart", function(e) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) { + clearTimeout(touchFinished); + var now = +new Date; + d.activeTouch = {start: now, moved: false, + prev: now - prevTouch.end <= 300 ? prevTouch : null}; + if (e.touches.length == 1) { + d.activeTouch.left = e.touches[0].pageX; + d.activeTouch.top = e.touches[0].pageY; + } + } + }); + on(d.scroller, "touchmove", function() { + if (d.activeTouch) d.activeTouch.moved = true; + }); + on(d.scroller, "touchend", function(e) { + var touch = d.activeTouch; + if (touch && !eventInWidget(d, e) && touch.left != null && + !touch.moved && new Date - touch.start < 300) { + var pos = cm.coordsChar(d.activeTouch, "page"), range; + if (!touch.prev || farAway(touch, touch.prev)) // Single tap + range = new Range(pos, pos); + else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap + range = cm.findWordAt(pos); + else // Triple tap + range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); + cm.setSelection(range.anchor, range.head); + cm.focus(); + e_preventDefault(e); + } + finishTouch(); + }); + on(d.scroller, "touchcancel", finishTouch); + + // Sync scrolling between fake scrollbars and real scrollable + // area, ensure viewport is updated when scrolling. + on(d.scroller, "scroll", function() { + if (d.scroller.clientHeight) { + setScrollTop(cm, d.scroller.scrollTop); + setScrollLeft(cm, d.scroller.scrollLeft, true); + signal(cm, "scroll", cm); + } + }); + + // Listen to wheel events in order to try and update the viewport on time. + on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); + on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); + + // Prevent wrapper from ever scrolling + on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); + + d.dragFunctions = { + enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);}, + over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, + start: function(e){onDragStart(cm, e);}, + drop: operation(cm, onDrop), + leave: function(e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }} + }; + + var inp = d.input.getField(); + on(inp, "keyup", function(e) { onKeyUp.call(cm, e); }); + on(inp, "keydown", operation(cm, onKeyDown)); + on(inp, "keypress", operation(cm, onKeyPress)); + on(inp, "focus", bind(onFocus, cm)); + on(inp, "blur", bind(onBlur, cm)); + } + + function dragDropChanged(cm, value, old) { + var wasOn = old && old != CodeMirror.Init; + if (!value != !wasOn) { + var funcs = cm.display.dragFunctions; + var toggle = value ? on : off; + toggle(cm.display.scroller, "dragstart", funcs.start); + toggle(cm.display.scroller, "dragenter", funcs.enter); + toggle(cm.display.scroller, "dragover", funcs.over); + toggle(cm.display.scroller, "dragleave", funcs.leave); + toggle(cm.display.scroller, "drop", funcs.drop); + } + } + + // Called when the window resizes + function onResize(cm) { + var d = cm.display; + if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth) + return; + // Might be a text scaling operation, clear size caches. + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + d.scrollbarsClipped = false; + cm.setSize(); + } + + // MOUSE EVENTS + + // Return true when the given mouse event happened in a widget + function eventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { + if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || + (n.parentNode == display.sizer && n != display.mover)) + return true; + } + } + + // Given a mouse event, find the corresponding position. If liberal + // is false, it checks whether a gutter or scrollbar was clicked, + // and returns null if it was. forRect is used by rectangular + // selections, and tries to estimate a character position even for + // coordinates beyond the right of the text. + function posFromMouse(cm, e, liberal, forRect) { + var display = cm.display; + if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null; + + var x, y, space = display.lineSpace.getBoundingClientRect(); + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX - space.left; y = e.clientY - space.top; } + catch (e) { return null; } + var coords = coordsChar(cm, x, y), line; + if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { + var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; + coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); + } + return coords; + } + + // A mouse down can be a single click, double click, triple click, + // start of selection drag, start of text drag, new cursor + // (ctrl-click), rectangle drag (alt-drag), or xwin + // middle-click-paste. Or it might be a click on something we should + // not interfere with, such as a scrollbar or widget. + function onMouseDown(e) { + var cm = this, display = cm.display; + if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) return; + display.shift = e.shiftKey; + + if (eventInWidget(display, e)) { + if (!webkit) { + // Briefly turn off draggability, to allow widgets to do + // normal dragging things. + display.scroller.draggable = false; + setTimeout(function(){display.scroller.draggable = true;}, 100); + } + return; + } + if (clickInGutter(cm, e)) return; + var start = posFromMouse(cm, e); + window.focus(); + + switch (e_button(e)) { + case 1: + // #3261: make sure, that we're not starting a second selection + if (cm.state.selectingText) + cm.state.selectingText(e); + else if (start) + leftButtonDown(cm, e, start); + else if (e_target(e) == display.scroller) + e_preventDefault(e); + break; + case 2: + if (webkit) cm.state.lastMiddleDown = +new Date; + if (start) extendSelection(cm.doc, start); + setTimeout(function() {display.input.focus();}, 20); + e_preventDefault(e); + break; + case 3: + if (captureRightClick) onContextMenu(cm, e); + else delayBlurEvent(cm); + break; + } + } + + var lastClick, lastDoubleClick; + function leftButtonDown(cm, e, start) { + if (ie) setTimeout(bind(ensureFocus, cm), 0); + else cm.curOp.focus = activeElt(); + + var now = +new Date, type; + if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) { + type = "triple"; + } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) { + type = "double"; + lastDoubleClick = {time: now, pos: start}; + } else { + type = "single"; + lastClick = {time: now, pos: start}; + } + + var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained; + if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && + type == "single" && (contained = sel.contains(start)) > -1 && + (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) && + (cmp(contained.to(), start) > 0 || start.xRel < 0)) + leftButtonStartDrag(cm, e, start, modifier); + else + leftButtonSelect(cm, e, start, type, modifier); + } + + // Start a text drag. When it ends, see if any dragging actually + // happen, and treat as a click if it didn't. + function leftButtonStartDrag(cm, e, start, modifier) { + var display = cm.display, startTime = +new Date; + var dragEnd = operation(cm, function(e2) { + if (webkit) display.scroller.draggable = false; + cm.state.draggingText = false; + off(document, "mouseup", dragEnd); + off(display.scroller, "drop", dragEnd); + if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { + e_preventDefault(e2); + if (!modifier && +new Date - 200 < startTime) + extendSelection(cm.doc, start); + // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) + if (webkit || ie && ie_version == 9) + setTimeout(function() {document.body.focus(); display.input.focus();}, 20); + else + display.input.focus(); + } + }); + // Let the drag handler handle this. + if (webkit) display.scroller.draggable = true; + cm.state.draggingText = dragEnd; + dragEnd.copy = mac ? e.altKey : e.ctrlKey + // IE's approach to draggable + if (display.scroller.dragDrop) display.scroller.dragDrop(); + on(document, "mouseup", dragEnd); + on(display.scroller, "drop", dragEnd); + } + + // Normal selection, as opposed to text dragging. + function leftButtonSelect(cm, e, start, type, addNew) { + var display = cm.display, doc = cm.doc; + e_preventDefault(e); + + var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; + if (addNew && !e.shiftKey) { + ourIndex = doc.sel.contains(start); + if (ourIndex > -1) + ourRange = ranges[ourIndex]; + else + ourRange = new Range(start, start); + } else { + ourRange = doc.sel.primary(); + ourIndex = doc.sel.primIndex; + } + + if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) { + type = "rect"; + if (!addNew) ourRange = new Range(start, start); + start = posFromMouse(cm, e, true, true); + ourIndex = -1; + } else if (type == "double") { + var word = cm.findWordAt(start); + if (cm.display.shift || doc.extend) + ourRange = extendRange(doc, ourRange, word.anchor, word.head); + else + ourRange = word; + } else if (type == "triple") { + var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0))); + if (cm.display.shift || doc.extend) + ourRange = extendRange(doc, ourRange, line.anchor, line.head); + else + ourRange = line; + } else { + ourRange = extendRange(doc, ourRange, start); + } + + if (!addNew) { + ourIndex = 0; + setSelection(doc, new Selection([ourRange], 0), sel_mouse); + startSel = doc.sel; + } else if (ourIndex == -1) { + ourIndex = ranges.length; + setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex), + {scroll: false, origin: "*mouse"}); + } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) { + setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), + {scroll: false, origin: "*mouse"}); + startSel = doc.sel; + } else { + replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); + } + + var lastPos = start; + function extendTo(pos) { + if (cmp(lastPos, pos) == 0) return; + lastPos = pos; + + if (type == "rect") { + var ranges = [], tabSize = cm.options.tabSize; + var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); + var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); + var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); + for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); + line <= end; line++) { + var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); + if (left == right) + ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); + else if (text.length > leftPos) + ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); + } + if (!ranges.length) ranges.push(new Range(start, start)); + setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), + {origin: "*mouse", scroll: false}); + cm.scrollIntoView(pos); + } else { + var oldRange = ourRange; + var anchor = oldRange.anchor, head = pos; + if (type != "single") { + if (type == "double") + var range = cm.findWordAt(pos); + else + var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))); + if (cmp(range.anchor, anchor) > 0) { + head = range.head; + anchor = minPos(oldRange.from(), range.anchor); + } else { + head = range.anchor; + anchor = maxPos(oldRange.to(), range.head); + } + } + var ranges = startSel.ranges.slice(0); + ranges[ourIndex] = new Range(clipPos(doc, anchor), head); + setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse); + } + } + + var editorSize = display.wrapper.getBoundingClientRect(); + // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + var counter = 0; + + function extend(e) { + var curCount = ++counter; + var cur = posFromMouse(cm, e, true, type == "rect"); + if (!cur) return; + if (cmp(cur, lastPos) != 0) { + cm.curOp.focus = activeElt(); + extendTo(cur); + var visible = visibleLines(display, doc); + if (cur.line >= visible.to || cur.line < visible.from) + setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; + if (outside) setTimeout(operation(cm, function() { + if (counter != curCount) return; + display.scroller.scrollTop += outside; + extend(e); + }), 50); + } + } + + function done(e) { + cm.state.selectingText = false; + counter = Infinity; + e_preventDefault(e); + display.input.focus(); + off(document, "mousemove", move); + off(document, "mouseup", up); + doc.history.lastSelOrigin = null; + } + + var move = operation(cm, function(e) { + if (!e_button(e)) done(e); + else extend(e); + }); + var up = operation(cm, done); + cm.state.selectingText = up; + on(document, "mousemove", move); + on(document, "mouseup", up); + } + + // Determines whether an event happened in the gutter, and fires the + // handlers for the corresponding event. + function gutterEvent(cm, e, type, prevent) { + try { var mX = e.clientX, mY = e.clientY; } + catch(e) { return false; } + if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false; + if (prevent) e_preventDefault(e); + + var display = cm.display; + var lineBox = display.lineDiv.getBoundingClientRect(); + + if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e); + mY -= lineBox.top - display.viewOffset; + + for (var i = 0; i < cm.options.gutters.length; ++i) { + var g = display.gutters.childNodes[i]; + if (g && g.getBoundingClientRect().right >= mX) { + var line = lineAtHeight(cm.doc, mY); + var gutter = cm.options.gutters[i]; + signal(cm, type, cm, line, gutter, e); + return e_defaultPrevented(e); + } + } + } + + function clickInGutter(cm, e) { + return gutterEvent(cm, e, "gutterClick", true); + } + + // Kludge to work around strange IE behavior where it'll sometimes + // re-fire a series of drag-related events right after the drop (#1551) + var lastDrop = 0; + + function onDrop(e) { + var cm = this; + clearDragCursor(cm); + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) + return; + e_preventDefault(e); + if (ie) lastDrop = +new Date; + var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; + if (!pos || cm.isReadOnly()) return; + // Might be a file drop, in which case we simply extract the text + // and insert it. + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0; + var loadFile = function(file, i) { + if (cm.options.allowDropFileTypes && + indexOf(cm.options.allowDropFileTypes, file.type) == -1) + return; + + var reader = new FileReader; + reader.onload = operation(cm, function() { + var content = reader.result; + if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = ""; + text[i] = content; + if (++read == n) { + pos = clipPos(cm.doc, pos); + var change = {from: pos, to: pos, + text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), + origin: "paste"}; + makeChange(cm.doc, change); + setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); + } + }); + reader.readAsText(file); + }; + for (var i = 0; i < n; ++i) loadFile(files[i], i); + } else { // Normal drop + // Don't do a replace if the drop happened inside of the selected text. + if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { + cm.state.draggingText(e); + // Ensure the editor is re-focused + setTimeout(function() {cm.display.input.focus();}, 20); + return; + } + try { + var text = e.dataTransfer.getData("Text"); + if (text) { + if (cm.state.draggingText && !cm.state.draggingText.copy) + var selected = cm.listSelections(); + setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); + if (selected) for (var i = 0; i < selected.length; ++i) + replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag"); + cm.replaceSelection(text, "around", "paste"); + cm.display.input.focus(); + } + } + catch(e){} + } + } + + function onDragStart(cm, e) { + if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; } + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return; + + e.dataTransfer.setData("Text", cm.getSelection()); + e.dataTransfer.effectAllowed = "copyMove" + + // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + if (e.dataTransfer.setDragImage && !safari) { + var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + if (presto) { + img.width = img.height = 1; + cm.display.wrapper.appendChild(img); + // Force a relayout, or Opera won't use our image for some obscure reason + img._top = img.offsetTop; + } + e.dataTransfer.setDragImage(img, 0, 0); + if (presto) img.parentNode.removeChild(img); + } + } + + function onDragOver(cm, e) { + var pos = posFromMouse(cm, e); + if (!pos) return; + var frag = document.createDocumentFragment(); + drawSelectionCursor(cm, pos, frag); + if (!cm.display.dragCursor) { + cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); + cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); + } + removeChildrenAndAdd(cm.display.dragCursor, frag); + } + + function clearDragCursor(cm) { + if (cm.display.dragCursor) { + cm.display.lineSpace.removeChild(cm.display.dragCursor); + cm.display.dragCursor = null; + } + } + + // SCROLL EVENTS + + // Sync the scrollable area and scrollbars, ensure the viewport + // covers the visible area. + function setScrollTop(cm, val) { + if (Math.abs(cm.doc.scrollTop - val) < 2) return; + cm.doc.scrollTop = val; + if (!gecko) updateDisplaySimple(cm, {top: val}); + if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; + cm.display.scrollbars.setScrollTop(val); + if (gecko) updateDisplaySimple(cm); + startWorker(cm, 100); + } + // Sync scroller and scrollbar, ensure the gutter elements are + // aligned. + function setScrollLeft(cm, val, isScroller) { + if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return; + val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); + cm.doc.scrollLeft = val; + alignHorizontally(cm); + if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val; + cm.display.scrollbars.setScrollLeft(val); + } + + // Since the delta values reported on mouse wheel events are + // unstandardized between browsers and even browser versions, and + // generally horribly unpredictable, this code starts by measuring + // the scroll effect that the first few mouse wheel events have, + // and, from that, detects the way it can convert deltas to pixel + // offsets afterwards. + // + // The reason we want to know the amount a wheel event will scroll + // is that it gives us a chance to update the display before the + // actual scrolling happens, reducing flickering. + + var wheelSamples = 0, wheelPixelsPerUnit = null; + // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + if (ie) wheelPixelsPerUnit = -.53; + else if (gecko) wheelPixelsPerUnit = 15; + else if (chrome) wheelPixelsPerUnit = -.7; + else if (safari) wheelPixelsPerUnit = -1/3; + + var wheelEventDelta = function(e) { + var dx = e.wheelDeltaX, dy = e.wheelDeltaY; + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail; + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail; + else if (dy == null) dy = e.wheelDelta; + return {x: dx, y: dy}; + }; + CodeMirror.wheelEventPixels = function(e) { + var delta = wheelEventDelta(e); + delta.x *= wheelPixelsPerUnit; + delta.y *= wheelPixelsPerUnit; + return delta; + }; + + function onScrollWheel(cm, e) { + var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; + + var display = cm.display, scroll = display.scroller; + // Quit if there's nothing to scroll here + var canScrollX = scroll.scrollWidth > scroll.clientWidth; + var canScrollY = scroll.scrollHeight > scroll.clientHeight; + if (!(dx && canScrollX || dy && canScrollY)) return; + + // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + if (dy && mac && webkit) { + outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { + for (var i = 0; i < view.length; i++) { + if (view[i].node == cur) { + cm.display.currentWheelTarget = cur; + break outer; + } + } + } + } + + // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { + if (dy && canScrollY) + setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); + setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))); + // Only prevent default scrolling if vertical scrolling is + // actually possible. Otherwise, it causes vertical scroll + // jitter on OSX trackpads when deltaX is small and deltaY + // is large (issue #3579) + if (!dy || (dy && canScrollY)) + e_preventDefault(e); + display.wheelStartX = null; // Abort measurement, if in progress + return; + } + + // 'Project' the visible viewport to cover the area that is being + // scrolled into view (if we know enough to estimate it). + if (dy && wheelPixelsPerUnit != null) { + var pixels = dy * wheelPixelsPerUnit; + var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; + if (pixels < 0) top = Math.max(0, top + pixels - 50); + else bot = Math.min(cm.doc.height, bot + pixels + 50); + updateDisplaySimple(cm, {top: top, bottom: bot}); + } + + if (wheelSamples < 20) { + if (display.wheelStartX == null) { + display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; + display.wheelDX = dx; display.wheelDY = dy; + setTimeout(function() { + if (display.wheelStartX == null) return; + var movedX = scroll.scrollLeft - display.wheelStartX; + var movedY = scroll.scrollTop - display.wheelStartY; + var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || + (movedX && display.wheelDX && movedX / display.wheelDX); + display.wheelStartX = display.wheelStartY = null; + if (!sample) return; + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); + ++wheelSamples; + }, 200); + } else { + display.wheelDX += dx; display.wheelDY += dy; + } + } + } + + // KEY EVENTS + + // Run a handler that was bound to a key. + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + if (!bound) return false; + } + // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + cm.display.input.ensurePolled(); + var prevShift = cm.display.shift, done = false; + try { + if (cm.isReadOnly()) cm.state.suppressEdits = true; + if (dropShift) cm.display.shift = false; + done = bound(cm) != Pass; + } finally { + cm.display.shift = prevShift; + cm.state.suppressEdits = false; + } + return done; + } + + function lookupKeyForEditor(cm, name, handle) { + for (var i = 0; i < cm.state.keyMaps.length; i++) { + var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); + if (result) return result; + } + return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) + || lookupKey(name, cm.options.keyMap, handle, cm); + } + + var stopSeq = new Delayed; + function dispatchKey(cm, name, e, handle) { + var seq = cm.state.keySeq; + if (seq) { + if (isModifierKey(name)) return "handled"; + stopSeq.set(50, function() { + if (cm.state.keySeq == seq) { + cm.state.keySeq = null; + cm.display.input.reset(); + } + }); + name = seq + " " + name; + } + var result = lookupKeyForEditor(cm, name, handle); + + if (result == "multi") + cm.state.keySeq = name; + if (result == "handled") + signalLater(cm, "keyHandled", cm, name, e); + + if (result == "handled" || result == "multi") { + e_preventDefault(e); + restartBlink(cm); + } + + if (seq && !result && /\'$/.test(name)) { + e_preventDefault(e); + return true; + } + return !!result; + } + + // Handle a key from the keydown event. + function handleKeyBinding(cm, e) { + var name = keyName(e, true); + if (!name) return false; + + if (e.shiftKey && !cm.state.keySeq) { + // First try to resolve full name (including 'Shift-'). Failing + // that, see if there is a cursor-motion command (starting with + // 'go') bound to the keyname without 'Shift-'. + return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);}) + || dispatchKey(cm, name, e, function(b) { + if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) + return doHandleBinding(cm, b); + }); + } else { + return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); }); + } + } + + // Handle a key from the keypress event + function handleCharBinding(cm, e, ch) { + return dispatchKey(cm, "'" + ch + "'", e, + function(b) { return doHandleBinding(cm, b, true); }); + } + + var lastStoppedKey = null; + function onKeyDown(e) { + var cm = this; + cm.curOp.focus = activeElt(); + if (signalDOMEvent(cm, e)) return; + // IE does strange things with escape. + if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false; + var code = e.keyCode; + cm.display.shift = code == 16 || e.shiftKey; + var handled = handleKeyBinding(cm, e); + if (presto) { + lastStoppedKey = handled ? code : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) + cm.replaceSelection("", null, "cut"); + } + + // Turn mouse into crosshair when Alt is held on Mac. + if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) + showCrossHair(cm); + } + + function showCrossHair(cm) { + var lineDiv = cm.display.lineDiv; + addClass(lineDiv, "CodeMirror-crosshair"); + + function up(e) { + if (e.keyCode == 18 || !e.altKey) { + rmClass(lineDiv, "CodeMirror-crosshair"); + off(document, "keyup", up); + off(document, "mouseover", up); + } + } + on(document, "keyup", up); + on(document, "mouseover", up); + } + + function onKeyUp(e) { + if (e.keyCode == 16) this.doc.sel.shift = false; + signalDOMEvent(this, e); + } + + function onKeyPress(e) { + var cm = this; + if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return; + var keyCode = e.keyCode, charCode = e.charCode; + if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} + if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return; + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); + if (handleCharBinding(cm, e, ch)) return; + cm.display.input.onKeyPress(e); + } + + // FOCUS/BLUR EVENTS + + function delayBlurEvent(cm) { + cm.state.delayingBlurEvent = true; + setTimeout(function() { + if (cm.state.delayingBlurEvent) { + cm.state.delayingBlurEvent = false; + onBlur(cm); + } + }, 100); + } + + function onFocus(cm) { + if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false; + + if (cm.options.readOnly == "nocursor") return; + if (!cm.state.focused) { + signal(cm, "focus", cm); + cm.state.focused = true; + addClass(cm.display.wrapper, "CodeMirror-focused"); + // This test prevents this from firing when a context + // menu is closed (since the input reset would kill the + // select-all detection hack) + if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { + cm.display.input.reset(); + if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730 + } + cm.display.input.receivedFocus(); + } + restartBlink(cm); + } + function onBlur(cm) { + if (cm.state.delayingBlurEvent) return; + + if (cm.state.focused) { + signal(cm, "blur", cm); + cm.state.focused = false; + rmClass(cm.display.wrapper, "CodeMirror-focused"); + } + clearInterval(cm.display.blinker); + setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150); + } + + // CONTEXT MENU HANDLING + + // To make the context menu work, we need to briefly unhide the + // textarea (making it as unobtrusive as possible) to let the + // right-click take effect on it. + function onContextMenu(cm, e) { + if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return; + if (signalDOMEvent(cm, e, "contextmenu")) return; + cm.display.input.onContextMenu(e); + } + + function contextMenuInGutter(cm, e) { + if (!hasHandler(cm, "gutterContextMenu")) return false; + return gutterEvent(cm, e, "gutterContextMenu", false); + } + + // UPDATING + + // Compute the position of the end of a change (its 'to' property + // refers to the pre-change end). + var changeEnd = CodeMirror.changeEnd = function(change) { + if (!change.text) return change.to; + return Pos(change.from.line + change.text.length - 1, + lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)); + }; + + // Adjust a position to refer to the post-change position of the + // same text, or the end of the change if the change covers it. + function adjustForChange(pos, change) { + if (cmp(pos, change.from) < 0) return pos; + if (cmp(pos, change.to) <= 0) return changeEnd(change); + + var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; + if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch; + return Pos(line, ch); + } + + function computeSelAfterChange(doc, change) { + var out = []; + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i]; + out.push(new Range(adjustForChange(range.anchor, change), + adjustForChange(range.head, change))); + } + return normalizeSelection(out, doc.sel.primIndex); + } + + function offsetPos(pos, old, nw) { + if (pos.line == old.line) + return Pos(nw.line, pos.ch - old.ch + nw.ch); + else + return Pos(nw.line + (pos.line - old.line), pos.ch); + } + + // Used by replaceSelections to allow moving the selection to the + // start or around the replaced test. Hint may be "start" or "around". + function computeReplacedSel(doc, changes, hint) { + var out = []; + var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + var from = offsetPos(change.from, oldPrev, newPrev); + var to = offsetPos(changeEnd(change), oldPrev, newPrev); + oldPrev = change.to; + newPrev = to; + if (hint == "around") { + var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; + out[i] = new Range(inv ? to : from, inv ? from : to); + } else { + out[i] = new Range(from, from); + } + } + return new Selection(out, doc.sel.primIndex); + } + + // Allow "beforeChange" event handlers to influence a change + function filterChange(doc, change, update) { + var obj = { + canceled: false, + from: change.from, + to: change.to, + text: change.text, + origin: change.origin, + cancel: function() { this.canceled = true; } + }; + if (update) obj.update = function(from, to, text, origin) { + if (from) this.from = clipPos(doc, from); + if (to) this.to = clipPos(doc, to); + if (text) this.text = text; + if (origin !== undefined) this.origin = origin; + }; + signal(doc, "beforeChange", doc, obj); + if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj); + + if (obj.canceled) return null; + return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}; + } + + // Apply a change to a document, and add it to the document's + // history, and propagating it to all linked documents. + function makeChange(doc, change, ignoreReadOnly) { + if (doc.cm) { + if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly); + if (doc.cm.state.suppressEdits) return; + } + + if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { + change = filterChange(doc, change, true); + if (!change) return; + } + + // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); + if (split) { + for (var i = split.length - 1; i >= 0; --i) + makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}); + } else { + makeChangeInner(doc, change); + } + } + + function makeChangeInner(doc, change) { + if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return; + var selAfter = computeSelAfterChange(doc, change); + addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); + + makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); + var rebased = []; + + linkedDocs(doc, function(doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); + }); + } + + // Revert a change stored in a document's history. + function makeChangeFromHistory(doc, type, allowSelectionOnly) { + if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) return; + + var hist = doc.history, event, selAfter = doc.sel; + var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; + + // Verify that there is a useable event (so that ctrl-z won't + // needlessly clear selection events) + for (var i = 0; i < source.length; i++) { + event = source[i]; + if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) + break; + } + if (i == source.length) return; + hist.lastOrigin = hist.lastSelOrigin = null; + + for (;;) { + event = source.pop(); + if (event.ranges) { + pushSelectionToHistory(event, dest); + if (allowSelectionOnly && !event.equals(doc.sel)) { + setSelection(doc, event, {clearRedo: false}); + return; + } + selAfter = event; + } + else break; + } + + // Build up a reverse change object to add to the opposite history + // stack (redo when undoing, and vice versa). + var antiChanges = []; + pushSelectionToHistory(selAfter, dest); + dest.push({changes: antiChanges, generation: hist.generation}); + hist.generation = event.generation || ++hist.maxGeneration; + + var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); + + for (var i = event.changes.length - 1; i >= 0; --i) { + var change = event.changes[i]; + change.origin = type; + if (filter && !filterChange(doc, change, false)) { + source.length = 0; + return; + } + + antiChanges.push(historyChangeFromChange(doc, change)); + + var after = i ? computeSelAfterChange(doc, change) : lst(source); + makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); + if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); + var rebased = []; + + // Propagate to the linked documents + linkedDocs(doc, function(doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); + }); + } + } + + // Sub-views need their line numbers shifted when text is added + // above or below them in the parent document. + function shiftDoc(doc, distance) { + if (distance == 0) return; + doc.first += distance; + doc.sel = new Selection(map(doc.sel.ranges, function(range) { + return new Range(Pos(range.anchor.line + distance, range.anchor.ch), + Pos(range.head.line + distance, range.head.ch)); + }), doc.sel.primIndex); + if (doc.cm) { + regChange(doc.cm, doc.first, doc.first - distance, distance); + for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) + regLineChange(doc.cm, l, "gutter"); + } + } + + // More lower-level change function, handling only a single document + // (not linked ones). + function makeChangeSingleDoc(doc, change, selAfter, spans) { + if (doc.cm && !doc.cm.curOp) + return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans); + + if (change.to.line < doc.first) { + shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); + return; + } + if (change.from.line > doc.lastLine()) return; + + // Clip the change to the size of this doc + if (change.from.line < doc.first) { + var shift = change.text.length - 1 - (doc.first - change.from.line); + shiftDoc(doc, shift); + change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), + text: [lst(change.text)], origin: change.origin}; + } + var last = doc.lastLine(); + if (change.to.line > last) { + change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), + text: [change.text[0]], origin: change.origin}; + } + + change.removed = getBetween(doc, change.from, change.to); + + if (!selAfter) selAfter = computeSelAfterChange(doc, change); + if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans); + else updateDoc(doc, change, spans); + setSelectionNoUndo(doc, selAfter, sel_dontScroll); + } + + // Handle the interaction of a change to a document with the editor + // that this document is part of. + function makeChangeSingleDocInEditor(cm, change, spans) { + var doc = cm.doc, display = cm.display, from = change.from, to = change.to; + + var recomputeMaxLength = false, checkWidthStart = from.line; + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); + doc.iter(checkWidthStart, to.line + 1, function(line) { + if (line == display.maxLine) { + recomputeMaxLength = true; + return true; + } + }); + } + + if (doc.sel.contains(change.from, change.to) > -1) + signalCursorActivity(cm); + + updateDoc(doc, change, spans, estimateHeight(cm)); + + if (!cm.options.lineWrapping) { + doc.iter(checkWidthStart, from.line + change.text.length, function(line) { + var len = lineLength(line); + if (len > display.maxLineLength) { + display.maxLine = line; + display.maxLineLength = len; + display.maxLineChanged = true; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) cm.curOp.updateMaxLine = true; + } + + // Adjust frontier, schedule worker + doc.frontier = Math.min(doc.frontier, from.line); + startWorker(cm, 400); + + var lendiff = change.text.length - (to.line - from.line) - 1; + // Remember that these lines changed, for updating the display + if (change.full) + regChange(cm); + else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) + regLineChange(cm, from.line, "text"); + else + regChange(cm, from.line, to.line + 1, lendiff); + + var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); + if (changeHandler || changesHandler) { + var obj = { + from: from, to: to, + text: change.text, + removed: change.removed, + origin: change.origin + }; + if (changeHandler) signalLater(cm, "change", cm, obj); + if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); + } + cm.display.selForContextMenu = null; + } + + function replaceRange(doc, code, from, to, origin) { + if (!to) to = from; + if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; } + if (typeof code == "string") code = doc.splitLines(code); + makeChange(doc, {from: from, to: to, text: code, origin: origin}); + } + + // SCROLLING THINGS INTO VIEW + + // If an editor sits on the top or bottom of the window, partially + // scrolled out of view, this ensures that the cursor is visible. + function maybeScrollWindow(cm, coords) { + if (signalDOMEvent(cm, "scrollCursorIntoView")) return; + + var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; + if (coords.top + box.top < 0) doScroll = true; + else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; + if (doScroll != null && !phantom) { + var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " + + (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " + + (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " + + coords.left + "px; width: 2px;"); + cm.display.lineSpace.appendChild(scrollNode); + scrollNode.scrollIntoView(doScroll); + cm.display.lineSpace.removeChild(scrollNode); + } + } + + // Scroll a given position into view (immediately), verifying that + // it actually became visible (as line heights are accurately + // measured, the position of something may 'drift' during drawing). + function scrollPosIntoView(cm, pos, end, margin) { + if (margin == null) margin = 0; + for (var limit = 0; limit < 5; limit++) { + var changed = false, coords = cursorCoords(cm, pos); + var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); + var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left), + Math.min(coords.top, endCoords.top) - margin, + Math.max(coords.left, endCoords.left), + Math.max(coords.bottom, endCoords.bottom) + margin); + var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; + if (scrollPos.scrollTop != null) { + setScrollTop(cm, scrollPos.scrollTop); + if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true; + } + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true; + } + if (!changed) break; + } + return coords; + } + + // Scroll a given set of coordinates into view (immediately). + function scrollIntoView(cm, x1, y1, x2, y2) { + var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2); + if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop); + if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft); + } + + // Calculate a new scroll position needed to scroll the given + // rectangle into view. Returns an object with scrollTop and + // scrollLeft properties. When these are undefined, the + // vertical/horizontal position does not need to be adjusted. + function calculateScrollPos(cm, x1, y1, x2, y2) { + var display = cm.display, snapMargin = textHeight(cm.display); + if (y1 < 0) y1 = 0; + var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; + var screen = displayHeight(cm), result = {}; + if (y2 - y1 > screen) y2 = y1 + screen; + var docBottom = cm.doc.height + paddingVert(display); + var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin; + if (y1 < screentop) { + result.scrollTop = atTop ? 0 : y1; + } else if (y2 > screentop + screen) { + var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen); + if (newTop != screentop) result.scrollTop = newTop; + } + + var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; + var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0); + var tooWide = x2 - x1 > screenw; + if (tooWide) x2 = x1 + screenw; + if (x1 < 10) + result.scrollLeft = 0; + else if (x1 < screenleft) + result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)); + else if (x2 > screenw + screenleft - 3) + result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw; + return result; + } + + // Store a relative adjustment to the scroll position in the current + // operation (to be applied when the operation finishes). + function addToScrollPos(cm, left, top) { + if (left != null || top != null) resolveScrollToPos(cm); + if (left != null) + cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left; + if (top != null) + cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; + } + + // Make sure that at the end of the operation the current cursor is + // shown. + function ensureCursorVisible(cm) { + resolveScrollToPos(cm); + var cur = cm.getCursor(), from = cur, to = cur; + if (!cm.options.lineWrapping) { + from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur; + to = Pos(cur.line, cur.ch + 1); + } + cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true}; + } + + // When an operation has its scrollToPos property set, and another + // scroll action is applied before the end of the operation, this + // 'simulates' scrolling that position into view in a cheap way, so + // that the effect of intermediate scroll commands is not ignored. + function resolveScrollToPos(cm) { + var range = cm.curOp.scrollToPos; + if (range) { + cm.curOp.scrollToPos = null; + var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); + var sPos = calculateScrollPos(cm, Math.min(from.left, to.left), + Math.min(from.top, to.top) - range.margin, + Math.max(from.right, to.right), + Math.max(from.bottom, to.bottom) + range.margin); + cm.scrollTo(sPos.scrollLeft, sPos.scrollTop); + } + } + + // API UTILITIES + + // Indent the given line. The how parameter can be "smart", + // "add"/null, "subtract", or "prev". When aggressive is false + // (typically set to true for forced single-line indents), empty + // lines are not indented, and places where the mode returns Pass + // are left alone. + function indentLine(cm, n, how, aggressive) { + var doc = cm.doc, state; + if (how == null) how = "add"; + if (how == "smart") { + // Fall back to "prev" when the mode doesn't have an indentation + // method. + if (!doc.mode.indent) how = "prev"; + else state = getStateBefore(cm, n); + } + + var tabSize = cm.options.tabSize; + var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); + if (line.stateAfter) line.stateAfter = null; + var curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (!aggressive && !/\S/.test(line.text)) { + indentation = 0; + how = "not"; + } else if (how == "smart") { + indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + if (indentation == Pass || indentation > 150) { + if (!aggressive) return; + how = "prev"; + } + } + if (how == "prev") { + if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize); + else indentation = 0; + } else if (how == "add") { + indentation = curSpace + cm.options.indentUnit; + } else if (how == "subtract") { + indentation = curSpace - cm.options.indentUnit; + } else if (typeof how == "number") { + indentation = curSpace + how; + } + indentation = Math.max(0, indentation); + + var indentString = "", pos = 0; + if (cm.options.indentWithTabs) + for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} + if (pos < indentation) indentString += spaceStr(indentation - pos); + + if (indentString != curSpaceString) { + replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + line.stateAfter = null; + return true; + } else { + // Ensure that, if the cursor was in the whitespace at the start + // of the line, it is moved to the end of that space. + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i]; + if (range.head.line == n && range.head.ch < curSpaceString.length) { + var pos = Pos(n, curSpaceString.length); + replaceOneSelection(doc, i, new Range(pos, pos)); + break; + } + } + } + } + + // Utility for applying a change to a line by handle or number, + // returning the number and optionally registering the line as + // changed. + function changeLine(doc, handle, changeType, op) { + var no = handle, line = handle; + if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle)); + else no = lineNo(handle); + if (no == null) return null; + if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType); + return line; + } + + // Helper for deleting text near the selection(s), used to implement + // backspace, delete, and similar functionality. + function deleteNearSelection(cm, compute) { + var ranges = cm.doc.sel.ranges, kill = []; + // Build up a set of ranges to kill first, merging overlapping + // ranges. + for (var i = 0; i < ranges.length; i++) { + var toKill = compute(ranges[i]); + while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { + var replaced = kill.pop(); + if (cmp(replaced.from, toKill.from) < 0) { + toKill.from = replaced.from; + break; + } + } + kill.push(toKill); + } + // Next, remove those actual ranges. + runInOp(cm, function() { + for (var i = kill.length - 1; i >= 0; i--) + replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); + ensureCursorVisible(cm); + }); + } + + // Used for horizontal relative motion. Dir is -1 or 1 (left or + // right), unit can be "char", "column" (like char, but doesn't + // cross line boundaries), "word" (across next word), or "group" (to + // the start of next group of word or non-word-non-whitespace + // chars). The visually param controls whether, in right-to-left + // text, direction 1 means to move towards the next index in the + // string, or towards the character to the right of the current + // position. The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosH(doc, pos, dir, unit, visually) { + var line = pos.line, ch = pos.ch, origDir = dir; + var lineObj = getLine(doc, line); + function findNextLine() { + var l = line + dir; + if (l < doc.first || l >= doc.first + doc.size) return false + line = l; + return lineObj = getLine(doc, l); + } + function moveOnce(boundToLine) { + var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true); + if (next == null) { + if (!boundToLine && findNextLine()) { + if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj); + else ch = dir < 0 ? lineObj.text.length : 0; + } else return false + } else ch = next; + return true; + } + + if (unit == "char") { + moveOnce() + } else if (unit == "column") { + moveOnce(true) + } else if (unit == "word" || unit == "group") { + var sawType = null, group = unit == "group"; + var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); + for (var first = true;; first = false) { + if (dir < 0 && !moveOnce(!first)) break; + var cur = lineObj.text.charAt(ch) || "\n"; + var type = isWordChar(cur, helper) ? "w" + : group && cur == "\n" ? "n" + : !group || /\s/.test(cur) ? null + : "p"; + if (group && !first && !type) type = "s"; + if (sawType && sawType != type) { + if (dir < 0) {dir = 1; moveOnce();} + break; + } + + if (type) sawType = type; + if (dir > 0 && !moveOnce(!first)) break; + } + } + var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true); + if (!cmp(pos, result)) result.hitSide = true; + return result; + } + + // For relative vertical movement. Dir may be -1 or 1. Unit can be + // "page" or "line". The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosV(cm, pos, dir, unit) { + var doc = cm.doc, x = pos.left, y; + if (unit == "page") { + var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); + y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display)); + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3; + } + for (;;) { + var target = coordsChar(cm, x, y); + if (!target.outside) break; + if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; } + y += dir * 5; + } + return target; + } + + // EDITOR METHODS + + // The publicly visible API. Note that methodOp(f) means + // 'wrap f in an operation, performed on its `this` parameter'. + + // This is not the complete set of editor methods. Most of the + // methods defined on the Doc type are also injected into + // CodeMirror.prototype, for backwards compatibility and + // convenience. + + CodeMirror.prototype = { + constructor: CodeMirror, + focus: function(){window.focus(); this.display.input.focus();}, + + setOption: function(option, value) { + var options = this.options, old = options[option]; + if (options[option] == value && option != "mode") return; + options[option] = value; + if (optionHandlers.hasOwnProperty(option)) + operation(this, optionHandlers[option])(this, value, old); + }, + + getOption: function(option) {return this.options[option];}, + getDoc: function() {return this.doc;}, + + addKeyMap: function(map, bottom) { + this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); + }, + removeKeyMap: function(map) { + var maps = this.state.keyMaps; + for (var i = 0; i < maps.length; ++i) + if (maps[i] == map || maps[i].name == map) { + maps.splice(i, 1); + return true; + } + }, + + addOverlay: methodOp(function(spec, options) { + var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); + if (mode.startState) throw new Error("Overlays may not be stateful."); + this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque}); + this.state.modeGen++; + regChange(this); + }), + removeOverlay: methodOp(function(spec) { + var overlays = this.state.overlays; + for (var i = 0; i < overlays.length; ++i) { + var cur = overlays[i].modeSpec; + if (cur == spec || typeof spec == "string" && cur.name == spec) { + overlays.splice(i, 1); + this.state.modeGen++; + regChange(this); + return; + } + } + }), + + indentLine: methodOp(function(n, dir, aggressive) { + if (typeof dir != "string" && typeof dir != "number") { + if (dir == null) dir = this.options.smartIndent ? "smart" : "prev"; + else dir = dir ? "add" : "subtract"; + } + if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive); + }), + indentSelection: methodOp(function(how) { + var ranges = this.doc.sel.ranges, end = -1; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + if (!range.empty()) { + var from = range.from(), to = range.to(); + var start = Math.max(end, from.line); + end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; + for (var j = start; j < end; ++j) + indentLine(this, j, how); + var newRanges = this.doc.sel.ranges; + if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) + replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); + } else if (range.head.line > end) { + indentLine(this, range.head.line, how, true); + end = range.head.line; + if (i == this.doc.sel.primIndex) ensureCursorVisible(this); + } + } + }), + + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(pos, precise) { + return takeToken(this, pos, precise); + }, + + getLineTokens: function(line, precise) { + return takeToken(this, Pos(line), precise, true); + }, + + getTokenTypeAt: function(pos) { + pos = clipPos(this.doc, pos); + var styles = getLineStyles(this, getLine(this.doc, pos.line)); + var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; + var type; + if (ch == 0) type = styles[2]; + else for (;;) { + var mid = (before + after) >> 1; + if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid; + else if (styles[mid * 2 + 1] < ch) before = mid + 1; + else { type = styles[mid * 2 + 2]; break; } + } + var cut = type ? type.indexOf("cm-overlay ") : -1; + return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1); + }, + + getModeAt: function(pos) { + var mode = this.doc.mode; + if (!mode.innerMode) return mode; + return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode; + }, + + getHelper: function(pos, type) { + return this.getHelpers(pos, type)[0]; + }, + + getHelpers: function(pos, type) { + var found = []; + if (!helpers.hasOwnProperty(type)) return found; + var help = helpers[type], mode = this.getModeAt(pos); + if (typeof mode[type] == "string") { + if (help[mode[type]]) found.push(help[mode[type]]); + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]]; + if (val) found.push(val); + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]); + } else if (help[mode.name]) { + found.push(help[mode.name]); + } + for (var i = 0; i < help._global.length; i++) { + var cur = help._global[i]; + if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) + found.push(cur.val); + } + return found; + }, + + getStateAfter: function(line, precise) { + var doc = this.doc; + line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); + return getStateBefore(this, line + 1, precise); + }, + + cursorCoords: function(start, mode) { + var pos, range = this.doc.sel.primary(); + if (start == null) pos = range.head; + else if (typeof start == "object") pos = clipPos(this.doc, start); + else pos = start ? range.from() : range.to(); + return cursorCoords(this, pos, mode || "page"); + }, + + charCoords: function(pos, mode) { + return charCoords(this, clipPos(this.doc, pos), mode || "page"); + }, + + coordsChar: function(coords, mode) { + coords = fromCoordSystem(this, coords, mode || "page"); + return coordsChar(this, coords.left, coords.top); + }, + + lineAtHeight: function(height, mode) { + height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; + return lineAtHeight(this.doc, height + this.display.viewOffset); + }, + heightAtLine: function(line, mode) { + var end = false, lineObj; + if (typeof line == "number") { + var last = this.doc.first + this.doc.size - 1; + if (line < this.doc.first) line = this.doc.first; + else if (line > last) { line = last; end = true; } + lineObj = getLine(this.doc, line); + } else { + lineObj = line; + } + return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top + + (end ? this.doc.height - heightAtLine(lineObj) : 0); + }, + + defaultTextHeight: function() { return textHeight(this.display); }, + defaultCharWidth: function() { return charWidth(this.display); }, + + setGutterMarker: methodOp(function(line, gutterID, value) { + return changeLine(this.doc, line, "gutter", function(line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}); + markers[gutterID] = value; + if (!value && isEmpty(markers)) line.gutterMarkers = null; + return true; + }); + }), + + clearGutter: methodOp(function(gutterID) { + var cm = this, doc = cm.doc, i = doc.first; + doc.iter(function(line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + line.gutterMarkers[gutterID] = null; + regLineChange(cm, i, "gutter"); + if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null; + } + ++i; + }); + }), + + lineInfo: function(line) { + if (typeof line == "number") { + if (!isLine(this.doc, line)) return null; + var n = line; + line = getLine(this.doc, line); + if (!line) return null; + } else { + var n = lineNo(line); + if (n == null) return null; + } + return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, + textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, + widgets: line.widgets}; + }, + + getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};}, + + addWidget: function(pos, node, scroll, vert, horiz) { + var display = this.display; + pos = cursorCoords(this, clipPos(this.doc, pos)); + var top = pos.bottom, left = pos.left; + node.style.position = "absolute"; + node.setAttribute("cm-ignore-events", "true"); + this.display.input.setUneditable(node); + display.sizer.appendChild(node); + if (vert == "over") { + top = pos.top; + } else if (vert == "above" || vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); + // Default to positioning above (if specified and possible); otherwise default to positioning below + if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) + top = pos.top - node.offsetHeight; + else if (pos.bottom + node.offsetHeight <= vspace) + top = pos.bottom; + if (left + node.offsetWidth > hspace) + left = hspace - node.offsetWidth; + } + node.style.top = top + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") left = 0; + else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2; + node.style.left = left + "px"; + } + if (scroll) + scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); + }, + + triggerOnKeyDown: methodOp(onKeyDown), + triggerOnKeyPress: methodOp(onKeyPress), + triggerOnKeyUp: onKeyUp, + + execCommand: function(cmd) { + if (commands.hasOwnProperty(cmd)) + return commands[cmd].call(null, this); + }, + + triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), + + findPosH: function(from, amount, unit, visually) { + var dir = 1; + if (amount < 0) { dir = -1; amount = -amount; } + for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { + cur = findPosH(this.doc, cur, dir, unit, visually); + if (cur.hitSide) break; + } + return cur; + }, + + moveH: methodOp(function(dir, unit) { + var cm = this; + cm.extendSelectionsBy(function(range) { + if (cm.display.shift || cm.doc.extend || range.empty()) + return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually); + else + return dir < 0 ? range.from() : range.to(); + }, sel_move); + }), + + deleteH: methodOp(function(dir, unit) { + var sel = this.doc.sel, doc = this.doc; + if (sel.somethingSelected()) + doc.replaceSelection("", null, "+delete"); + else + deleteNearSelection(this, function(range) { + var other = findPosH(doc, range.head, dir, unit, false); + return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}; + }); + }), + + findPosV: function(from, amount, unit, goalColumn) { + var dir = 1, x = goalColumn; + if (amount < 0) { dir = -1; amount = -amount; } + for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { + var coords = cursorCoords(this, cur, "div"); + if (x == null) x = coords.left; + else coords.left = x; + cur = findPosV(this, coords, dir, unit); + if (cur.hitSide) break; + } + return cur; + }, + + moveV: methodOp(function(dir, unit) { + var cm = this, doc = this.doc, goals = []; + var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected(); + doc.extendSelectionsBy(function(range) { + if (collapse) + return dir < 0 ? range.from() : range.to(); + var headPos = cursorCoords(cm, range.head, "div"); + if (range.goalColumn != null) headPos.left = range.goalColumn; + goals.push(headPos.left); + var pos = findPosV(cm, headPos, dir, unit); + if (unit == "page" && range == doc.sel.primary()) + addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top); + return pos; + }, sel_move); + if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++) + doc.sel.ranges[i].goalColumn = goals[i]; + }), + + // Find the word at the given position (as returned by coordsChar). + findWordAt: function(pos) { + var doc = this.doc, line = getLine(doc, pos.line).text; + var start = pos.ch, end = pos.ch; + if (line) { + var helper = this.getHelper(pos, "wordChars"); + if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; + var startChar = line.charAt(start); + var check = isWordChar(startChar, helper) + ? function(ch) { return isWordChar(ch, helper); } + : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} + : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; + while (start > 0 && check(line.charAt(start - 1))) --start; + while (end < line.length && check(line.charAt(end))) ++end; + } + return new Range(Pos(pos.line, start), Pos(pos.line, end)); + }, + + toggleOverwrite: function(value) { + if (value != null && value == this.state.overwrite) return; + if (this.state.overwrite = !this.state.overwrite) + addClass(this.display.cursorDiv, "CodeMirror-overwrite"); + else + rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); + + signal(this, "overwriteToggle", this, this.state.overwrite); + }, + hasFocus: function() { return this.display.input.getField() == activeElt(); }, + isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit); }, + + scrollTo: methodOp(function(x, y) { + if (x != null || y != null) resolveScrollToPos(this); + if (x != null) this.curOp.scrollLeft = x; + if (y != null) this.curOp.scrollTop = y; + }), + getScrollInfo: function() { + var scroller = this.display.scroller; + return {left: scroller.scrollLeft, top: scroller.scrollTop, + height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, + width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, + clientHeight: displayHeight(this), clientWidth: displayWidth(this)}; + }, + + scrollIntoView: methodOp(function(range, margin) { + if (range == null) { + range = {from: this.doc.sel.primary().head, to: null}; + if (margin == null) margin = this.options.cursorScrollMargin; + } else if (typeof range == "number") { + range = {from: Pos(range, 0), to: null}; + } else if (range.from == null) { + range = {from: range, to: null}; + } + if (!range.to) range.to = range.from; + range.margin = margin || 0; + + if (range.from.line != null) { + resolveScrollToPos(this); + this.curOp.scrollToPos = range; + } else { + var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left), + Math.min(range.from.top, range.to.top) - range.margin, + Math.max(range.from.right, range.to.right), + Math.max(range.from.bottom, range.to.bottom) + range.margin); + this.scrollTo(sPos.scrollLeft, sPos.scrollTop); + } + }), + + setSize: methodOp(function(width, height) { + var cm = this; + function interpret(val) { + return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; + } + if (width != null) cm.display.wrapper.style.width = interpret(width); + if (height != null) cm.display.wrapper.style.height = interpret(height); + if (cm.options.lineWrapping) clearLineMeasurementCache(this); + var lineNo = cm.display.viewFrom; + cm.doc.iter(lineNo, cm.display.viewTo, function(line) { + if (line.widgets) for (var i = 0; i < line.widgets.length; i++) + if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; } + ++lineNo; + }); + cm.curOp.forceUpdate = true; + signal(cm, "refresh", this); + }), + + operation: function(f){return runInOp(this, f);}, + + refresh: methodOp(function() { + var oldHeight = this.display.cachedTextHeight; + regChange(this); + this.curOp.forceUpdate = true; + clearCaches(this); + this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop); + updateGutterSpace(this); + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) + estimateLineHeights(this); + signal(this, "refresh", this); + }), + + swapDoc: methodOp(function(doc) { + var old = this.doc; + old.cm = null; + attachDoc(this, doc); + clearCaches(this); + this.display.input.reset(); + this.scrollTo(doc.scrollLeft, doc.scrollTop); + this.curOp.forceScroll = true; + signalLater(this, "swapDoc", this, old); + return old; + }), + + getInputField: function(){return this.display.input.getField();}, + getWrapperElement: function(){return this.display.wrapper;}, + getScrollerElement: function(){return this.display.scroller;}, + getGutterElement: function(){return this.display.gutters;} + }; + eventMixin(CodeMirror); + + // OPTION DEFAULTS + + // The default configuration options. + var defaults = CodeMirror.defaults = {}; + // Functions to run when options are changed. + var optionHandlers = CodeMirror.optionHandlers = {}; + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt; + if (handle) optionHandlers[name] = + notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle; + } + + // Passed to option handlers when there is no old value. + var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}}; + + // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + option("value", "", function(cm, val) { + cm.setValue(val); + }, true); + option("mode", null, function(cm, val) { + cm.doc.modeOption = val; + loadMode(cm); + }, true); + + option("indentUnit", 2, loadMode, true); + option("indentWithTabs", false); + option("smartIndent", true); + option("tabSize", 4, function(cm) { + resetModeState(cm); + clearCaches(cm); + regChange(cm); + }, true); + option("lineSeparator", null, function(cm, val) { + cm.doc.lineSep = val; + if (!val) return; + var newBreaks = [], lineNo = cm.doc.first; + cm.doc.iter(function(line) { + for (var pos = 0;;) { + var found = line.text.indexOf(val, pos); + if (found == -1) break; + pos = found + val.length; + newBreaks.push(Pos(lineNo, found)); + } + lineNo++; + }); + for (var i = newBreaks.length - 1; i >= 0; i--) + replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) + }); + option("specialChars", /[\u0000-\u001f\u007f\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) { + cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); + if (old != CodeMirror.Init) cm.refresh(); + }); + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true); + option("electricChars", true); + option("inputStyle", mobile ? "contenteditable" : "textarea", function() { + throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME + }, true); + option("rtlMoveVisually", !windows); + option("wholeLineUpdateBefore", true); + + option("theme", "default", function(cm) { + themeChanged(cm); + guttersChanged(cm); + }, true); + option("keyMap", "default", function(cm, val, old) { + var next = getKeyMap(val); + var prev = old != CodeMirror.Init && getKeyMap(old); + if (prev && prev.detach) prev.detach(cm, next); + if (next.attach) next.attach(cm, prev || null); + }); + option("extraKeys", null); + + option("lineWrapping", false, wrappingChanged, true); + option("gutters", [], function(cm) { + setGuttersForLineNumbers(cm.options); + guttersChanged(cm); + }, true); + option("fixedGutter", true, function(cm, val) { + cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; + cm.refresh(); + }, true); + option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true); + option("scrollbarStyle", "native", function(cm) { + initScrollbars(cm); + updateScrollbars(cm); + cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); + cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); + }, true); + option("lineNumbers", false, function(cm) { + setGuttersForLineNumbers(cm.options); + guttersChanged(cm); + }, true); + option("firstLineNumber", 1, guttersChanged, true); + option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); + option("showCursorWhenSelecting", false, updateSelection, true); + + option("resetSelectionOnContextMenu", true); + option("lineWiseCopyCut", true); + + option("readOnly", false, function(cm, val) { + if (val == "nocursor") { + onBlur(cm); + cm.display.input.blur(); + cm.display.disabled = true; + } else { + cm.display.disabled = false; + } + cm.display.input.readOnlyChanged(val) + }); + option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true); + option("dragDrop", true, dragDropChanged); + option("allowDropFileTypes", null); + + option("cursorBlinkRate", 530); + option("cursorScrollMargin", 0); + option("cursorHeight", 1, updateSelection, true); + option("singleCursorHeightPerLine", true, updateSelection, true); + option("workTime", 100); + option("workDelay", 100); + option("flattenSpans", true, resetModeState, true); + option("addModeClass", false, resetModeState, true); + option("pollInterval", 100); + option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;}); + option("historyEventDelay", 1250); + option("viewportMargin", 10, function(cm){cm.refresh();}, true); + option("maxHighlightLength", 10000, resetModeState, true); + option("moveInputWithCursor", true, function(cm, val) { + if (!val) cm.display.input.resetPosition(); + }); + + option("tabindex", null, function(cm, val) { + cm.display.input.getField().tabIndex = val || ""; + }); + option("autofocus", null); + + // MODE DEFINITION AND QUERYING + + // Known modes, by name and by MIME + var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + CodeMirror.defineMode = function(name, mode) { + if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; + if (arguments.length > 2) + mode.dependencies = Array.prototype.slice.call(arguments, 2); + modes[name] = mode; + }; + + CodeMirror.defineMIME = function(mime, spec) { + mimeModes[mime] = spec; + }; + + // Given a MIME type, a {name, ...options} config object, or a name + // string, return a mode config object. + CodeMirror.resolveMode = function(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { + spec = mimeModes[spec]; + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + var found = mimeModes[spec.name]; + if (typeof found == "string") found = {name: found}; + spec = createObj(found, spec); + spec.name = found.name; + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { + return CodeMirror.resolveMode("application/xml"); + } + if (typeof spec == "string") return {name: spec}; + else return spec || {name: "null"}; + }; + + // Given a mode spec (anything that resolveMode accepts), find and + // initialize an actual mode object. + CodeMirror.getMode = function(options, spec) { + var spec = CodeMirror.resolveMode(spec); + var mfactory = modes[spec.name]; + if (!mfactory) return CodeMirror.getMode(options, "text/plain"); + var modeObj = mfactory(options, spec); + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) continue; + if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; + modeObj[prop] = exts[prop]; + } + } + modeObj.name = spec.name; + if (spec.helperType) modeObj.helperType = spec.helperType; + if (spec.modeProps) for (var prop in spec.modeProps) + modeObj[prop] = spec.modeProps[prop]; + + return modeObj; + }; + + // Minimal default mode. + CodeMirror.defineMode("null", function() { + return {token: function(stream) {stream.skipToEnd();}}; + }); + CodeMirror.defineMIME("text/plain", "null"); + + // This can be used to attach properties to mode objects from + // outside the actual mode definition. + var modeExtensions = CodeMirror.modeExtensions = {}; + CodeMirror.extendMode = function(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); + copyObj(properties, exts); + }; + + // EXTENSIONS + + CodeMirror.defineExtension = function(name, func) { + CodeMirror.prototype[name] = func; + }; + CodeMirror.defineDocExtension = function(name, func) { + Doc.prototype[name] = func; + }; + CodeMirror.defineOption = option; + + var initHooks = []; + CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; + + var helpers = CodeMirror.helpers = {}; + CodeMirror.registerHelper = function(type, name, value) { + if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []}; + helpers[type][name] = value; + }; + CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value); + helpers[type]._global.push({pred: predicate, val: value}); + }; + + // MODE STATE HANDLING + + // Utility functions for working with state. Exported because nested + // modes need to do this for their inner modes. + + var copyState = CodeMirror.copyState = function(mode, state) { + if (state === true) return state; + if (mode.copyState) return mode.copyState(state); + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) val = val.concat([]); + nstate[n] = val; + } + return nstate; + }; + + var startState = CodeMirror.startState = function(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true; + }; + + // Given a mode and a state (for that mode), find the inner mode and + // state at the position that the state refers to. + CodeMirror.innerMode = function(mode, state) { + while (mode.innerMode) { + var info = mode.innerMode(state); + if (!info || info.mode == mode) break; + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state}; + }; + + // STANDARD COMMANDS + + // Commands are parameter-less actions that can be performed on an + // editor, mostly used for keybindings. + var commands = CodeMirror.commands = { + selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);}, + singleSelection: function(cm) { + cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); + }, + killLine: function(cm) { + deleteNearSelection(cm, function(range) { + if (range.empty()) { + var len = getLine(cm.doc, range.head.line).text.length; + if (range.head.ch == len && range.head.line < cm.lastLine()) + return {from: range.head, to: Pos(range.head.line + 1, 0)}; + else + return {from: range.head, to: Pos(range.head.line, len)}; + } else { + return {from: range.from(), to: range.to()}; + } + }); + }, + deleteLine: function(cm) { + deleteNearSelection(cm, function(range) { + return {from: Pos(range.from().line, 0), + to: clipPos(cm.doc, Pos(range.to().line + 1, 0))}; + }); + }, + delLineLeft: function(cm) { + deleteNearSelection(cm, function(range) { + return {from: Pos(range.from().line, 0), to: range.from()}; + }); + }, + delWrappedLineLeft: function(cm) { + deleteNearSelection(cm, function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + var leftPos = cm.coordsChar({left: 0, top: top}, "div"); + return {from: leftPos, to: range.from()}; + }); + }, + delWrappedLineRight: function(cm) { + deleteNearSelection(cm, function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); + return {from: range.from(), to: rightPos }; + }); + }, + undo: function(cm) {cm.undo();}, + redo: function(cm) {cm.redo();}, + undoSelection: function(cm) {cm.undoSelection();}, + redoSelection: function(cm) {cm.redoSelection();}, + goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));}, + goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));}, + goLineStart: function(cm) { + cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); }, + {origin: "+move", bias: 1}); + }, + goLineStartSmart: function(cm) { + cm.extendSelectionsBy(function(range) { + return lineStartSmart(cm, range.head); + }, {origin: "+move", bias: 1}); + }, + goLineEnd: function(cm) { + cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); }, + {origin: "+move", bias: -1}); + }, + goLineRight: function(cm) { + cm.extendSelectionsBy(function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); + }, sel_move); + }, + goLineLeft: function(cm) { + cm.extendSelectionsBy(function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + return cm.coordsChar({left: 0, top: top}, "div"); + }, sel_move); + }, + goLineLeftSmart: function(cm) { + cm.extendSelectionsBy(function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + var pos = cm.coordsChar({left: 0, top: top}, "div"); + if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head); + return pos; + }, sel_move); + }, + goLineUp: function(cm) {cm.moveV(-1, "line");}, + goLineDown: function(cm) {cm.moveV(1, "line");}, + goPageUp: function(cm) {cm.moveV(-1, "page");}, + goPageDown: function(cm) {cm.moveV(1, "page");}, + goCharLeft: function(cm) {cm.moveH(-1, "char");}, + goCharRight: function(cm) {cm.moveH(1, "char");}, + goColumnLeft: function(cm) {cm.moveH(-1, "column");}, + goColumnRight: function(cm) {cm.moveH(1, "column");}, + goWordLeft: function(cm) {cm.moveH(-1, "word");}, + goGroupRight: function(cm) {cm.moveH(1, "group");}, + goGroupLeft: function(cm) {cm.moveH(-1, "group");}, + goWordRight: function(cm) {cm.moveH(1, "word");}, + delCharBefore: function(cm) {cm.deleteH(-1, "char");}, + delCharAfter: function(cm) {cm.deleteH(1, "char");}, + delWordBefore: function(cm) {cm.deleteH(-1, "word");}, + delWordAfter: function(cm) {cm.deleteH(1, "word");}, + delGroupBefore: function(cm) {cm.deleteH(-1, "group");}, + delGroupAfter: function(cm) {cm.deleteH(1, "group");}, + indentAuto: function(cm) {cm.indentSelection("smart");}, + indentMore: function(cm) {cm.indentSelection("add");}, + indentLess: function(cm) {cm.indentSelection("subtract");}, + insertTab: function(cm) {cm.replaceSelection("\t");}, + insertSoftTab: function(cm) { + var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].from(); + var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); + spaces.push(spaceStr(tabSize - col % tabSize)); + } + cm.replaceSelections(spaces); + }, + defaultTab: function(cm) { + if (cm.somethingSelected()) cm.indentSelection("add"); + else cm.execCommand("insertTab"); + }, + transposeChars: function(cm) { + runInOp(cm, function() { + var ranges = cm.listSelections(), newSel = []; + for (var i = 0; i < ranges.length; i++) { + var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; + if (line) { + if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1); + if (cur.ch > 0) { + cur = new Pos(cur.line, cur.ch + 1); + cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), + Pos(cur.line, cur.ch - 2), cur, "+transpose"); + } else if (cur.line > cm.doc.first) { + var prev = getLine(cm.doc, cur.line - 1).text; + if (prev) + cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + + prev.charAt(prev.length - 1), + Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose"); + } + } + newSel.push(new Range(cur, cur)); + } + cm.setSelections(newSel); + }); + }, + newlineAndIndent: function(cm) { + runInOp(cm, function() { + var len = cm.listSelections().length; + for (var i = 0; i < len; i++) { + var range = cm.listSelections()[i]; + cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input"); + cm.indentLine(range.from().line + 1, null, true); + } + ensureCursorVisible(cm); + }); + }, + openLine: function(cm) {cm.replaceSelection("\n", "start")}, + toggleOverwrite: function(cm) {cm.toggleOverwrite();} + }; + + + // STANDARD KEYMAPS + + var keyMap = CodeMirror.keyMap = {}; + + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", + "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", + "Esc": "singleSelection" + }; + // Note that the save and find-related commands aren't defined by + // default. User code or addons can define them. Unknown commands + // are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", + "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", + fallthrough: "basic" + }; + // Very basic readline/emacs-style bindings, which are standard on Mac. + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", + "Ctrl-O": "openLine" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", + "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", + "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", + "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", + fallthrough: ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + + // KEYMAP DISPATCH + + function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/), name = parts[parts.length - 1]; + var alt, ctrl, shift, cmd; + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i]; + if (/^(cmd|meta|m)$/i.test(mod)) cmd = true; + else if (/^a(lt)?$/i.test(mod)) alt = true; + else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true; + else if (/^s(hift)$/i.test(mod)) shift = true; + else throw new Error("Unrecognized modifier name: " + mod); + } + if (alt) name = "Alt-" + name; + if (ctrl) name = "Ctrl-" + name; + if (cmd) name = "Cmd-" + name; + if (shift) name = "Shift-" + name; + return name; + } + + // This is a kludge to keep keymaps mostly working as raw objects + // (backwards compatibility) while at the same time support features + // like normalization and multi-stroke key bindings. It compiles a + // new normalized keymap, and then updates the old object to reflect + // this. + CodeMirror.normalizeKeyMap = function(keymap) { + var copy = {}; + for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) { + var value = keymap[keyname]; + if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue; + if (value == "...") { delete keymap[keyname]; continue; } + + var keys = map(keyname.split(" "), normalizeKeyName); + for (var i = 0; i < keys.length; i++) { + var val, name; + if (i == keys.length - 1) { + name = keys.join(" "); + val = value; + } else { + name = keys.slice(0, i + 1).join(" "); + val = "..."; + } + var prev = copy[name]; + if (!prev) copy[name] = val; + else if (prev != val) throw new Error("Inconsistent bindings for " + name); + } + delete keymap[keyname]; + } + for (var prop in copy) keymap[prop] = copy[prop]; + return keymap; + }; + + var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) { + map = getKeyMap(map); + var found = map.call ? map.call(key, context) : map[key]; + if (found === false) return "nothing"; + if (found === "...") return "multi"; + if (found != null && handle(found)) return "handled"; + + if (map.fallthrough) { + if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") + return lookupKey(key, map.fallthrough, handle, context); + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle, context); + if (result) return result; + } + } + }; + + // Modifier key presses don't count as 'real' key presses for the + // purpose of keymap fallthrough. + var isModifierKey = CodeMirror.isModifierKey = function(value) { + var name = typeof value == "string" ? value : keyNames[value.keyCode]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; + }; + + // Look up the name of a key as indicated by an event object. + var keyName = CodeMirror.keyName = function(event, noShift) { + if (presto && event.keyCode == 34 && event["char"]) return false; + var base = keyNames[event.keyCode], name = base; + if (name == null || event.altGraphKey) return false; + if (event.altKey && base != "Alt") name = "Alt-" + name; + if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name; + if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name; + if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name; + return name; + }; + + function getKeyMap(val) { + return typeof val == "string" ? keyMap[val] : val; + } + + // FROMTEXTAREA + + CodeMirror.fromTextArea = function(textarea, options) { + options = options ? copyObj(options) : {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabIndex) + options.tabindex = textarea.tabIndex; + if (!options.placeholder && textarea.placeholder) + options.placeholder = textarea.placeholder; + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = activeElt(); + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() {textarea.value = cm.getValue();} + if (textarea.form) { + on(textarea.form, "submit", save); + // Deplorable hack to make the submit method do the right thing. + if (!options.leaveSubmitMethodAlone) { + var form = textarea.form, realSubmit = form.submit; + try { + var wrappedSubmit = form.submit = function() { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } catch(e) {} + } + } + + options.finishInit = function(cm) { + cm.save = save; + cm.getTextArea = function() { return textarea; }; + cm.toTextArea = function() { + cm.toTextArea = isNaN; // Prevent this from being ran twice + save(); + textarea.parentNode.removeChild(cm.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + off(textarea.form, "submit", save); + if (typeof textarea.form.submit == "function") + textarea.form.submit = realSubmit; + } + }; + }; + + textarea.style.display = "none"; + var cm = CodeMirror(function(node) { + textarea.parentNode.insertBefore(node, textarea.nextSibling); + }, options); + return cm; + }; + + // STRING STREAM + + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + var StringStream = CodeMirror.StringStream = function(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + }; + + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == this.lineStart;}, + peek: function() {return this.string.charAt(this.pos) || undefined;}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() { + if (this.lastColumnPos < this.start) { + this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); + this.lastColumnPos = this.start; + } + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); + }, + indentation: function() { + return countColumn(this.string, null, this.tabSize) - + (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); + }, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; + var substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) return null; + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } + }; + + // TEXTMARKERS + + // Created with markText and setBookmark methods. A TextMarker is a + // handle that can be used to clear or find a marked position in the + // document. Line objects hold arrays (markedSpans) containing + // {from, to, marker} object pointing to such marker objects, and + // indicating that such a marker is present on that line. Multiple + // lines may point to the same marker when it spans across lines. + // The spans will have null for their from/to properties when the + // marker continues beyond the start/end of the line. Markers have + // links back to the lines they currently touch. + + var nextMarkerId = 0; + + var TextMarker = CodeMirror.TextMarker = function(doc, type) { + this.lines = []; + this.type = type; + this.doc = doc; + this.id = ++nextMarkerId; + }; + eventMixin(TextMarker); + + // Clear the marker. + TextMarker.prototype.clear = function() { + if (this.explicitlyCleared) return; + var cm = this.doc.cm, withOp = cm && !cm.curOp; + if (withOp) startOperation(cm); + if (hasHandler(this, "clear")) { + var found = this.find(); + if (found) signalLater(this, "clear", found.from, found.to); + } + var min = null, max = null; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text"); + else if (cm) { + if (span.to != null) max = lineNo(line); + if (span.from != null) min = lineNo(line); + } + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) + updateLineHeight(line, textHeight(cm.display)); + } + if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) { + var visual = visualLine(this.lines[i]), len = lineLength(visual); + if (len > cm.display.maxLineLength) { + cm.display.maxLine = visual; + cm.display.maxLineLength = len; + cm.display.maxLineChanged = true; + } + } + + if (min != null && cm && this.collapsed) regChange(cm, min, max + 1); + this.lines.length = 0; + this.explicitlyCleared = true; + if (this.atomic && this.doc.cantEdit) { + this.doc.cantEdit = false; + if (cm) reCheckSelection(cm.doc); + } + if (cm) signalLater(cm, "markerCleared", cm, this); + if (withOp) endOperation(cm); + if (this.parent) this.parent.clear(); + }; + + // Find the position of the marker in the document. Returns a {from, + // to} object by default. Side can be passed to get a specific side + // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the + // Pos objects returned contain a line object, rather than a line + // number (used to prevent looking up the same line twice). + TextMarker.prototype.find = function(side, lineObj) { + if (side == null && this.type == "bookmark") side = 1; + var from, to; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.from != null) { + from = Pos(lineObj ? line : lineNo(line), span.from); + if (side == -1) return from; + } + if (span.to != null) { + to = Pos(lineObj ? line : lineNo(line), span.to); + if (side == 1) return to; + } + } + return from && {from: from, to: to}; + }; + + // Signals that the marker's widget changed, and surrounding layout + // should be recomputed. + TextMarker.prototype.changed = function() { + var pos = this.find(-1, true), widget = this, cm = this.doc.cm; + if (!pos || !cm) return; + runInOp(cm, function() { + var line = pos.line, lineN = lineNo(pos.line); + var view = findViewForLine(cm, lineN); + if (view) { + clearLineMeasurementCacheFor(view); + cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; + } + cm.curOp.updateMaxLine = true; + if (!lineIsHidden(widget.doc, line) && widget.height != null) { + var oldHeight = widget.height; + widget.height = null; + var dHeight = widgetHeight(widget) - oldHeight; + if (dHeight) + updateLineHeight(line, line.height + dHeight); + } + }); + }; + + TextMarker.prototype.attachLine = function(line) { + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) + (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); + } + this.lines.push(line); + }; + TextMarker.prototype.detachLine = function(line) { + this.lines.splice(indexOf(this.lines, line), 1); + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); + } + }; + + // Collapsed markers have unique ids, in order to be able to order + // them, which is needed for uniquely determining an outer marker + // when they overlap (they may nest, but not partially overlap). + var nextMarkerId = 0; + + // Create a marker, wire it up to the right lines, and + function markText(doc, from, to, options, type) { + // Shared markers (across linked documents) are handled separately + // (markTextShared will call out to this again, once per + // document). + if (options && options.shared) return markTextShared(doc, from, to, options, type); + // Ensure we are in an operation. + if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); + + var marker = new TextMarker(doc, type), diff = cmp(from, to); + if (options) copyObj(options, marker, false); + // Don't connect empty markers unless clearWhenEmpty is false + if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) + return marker; + if (marker.replacedWith) { + // Showing up as a widget implies collapsed (widget replaces text) + marker.collapsed = true; + marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget"); + if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true"); + if (options.insertLeft) marker.widgetNode.insertLeft = true; + } + if (marker.collapsed) { + if (conflictingCollapsedRange(doc, from.line, from, to, marker) || + from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) + throw new Error("Inserting collapsed marker partially overlapping an existing one"); + sawCollapsedSpans = true; + } + + if (marker.addToHistory) + addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); + + var curLine = from.line, cm = doc.cm, updateMaxLine; + doc.iter(curLine, to.line + 1, function(line) { + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) + updateMaxLine = true; + if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0); + addMarkedSpan(line, new MarkedSpan(marker, + curLine == from.line ? from.ch : null, + curLine == to.line ? to.ch : null)); + ++curLine; + }); + // lineIsHidden depends on the presence of the spans, so needs a second pass + if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { + if (lineIsHidden(doc, line)) updateLineHeight(line, 0); + }); + + if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); }); + + if (marker.readOnly) { + sawReadOnlySpans = true; + if (doc.history.done.length || doc.history.undone.length) + doc.clearHistory(); + } + if (marker.collapsed) { + marker.id = ++nextMarkerId; + marker.atomic = true; + } + if (cm) { + // Sync editor state + if (updateMaxLine) cm.curOp.updateMaxLine = true; + if (marker.collapsed) + regChange(cm, from.line, to.line + 1); + else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css) + for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text"); + if (marker.atomic) reCheckSelection(cm.doc); + signalLater(cm, "markerAdded", cm, marker); + } + return marker; + } + + // SHARED TEXTMARKERS + + // A shared marker spans multiple linked documents. It is + // implemented as a meta-marker-object controlling multiple normal + // markers. + var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) { + this.markers = markers; + this.primary = primary; + for (var i = 0; i < markers.length; ++i) + markers[i].parent = this; + }; + eventMixin(SharedTextMarker); + + SharedTextMarker.prototype.clear = function() { + if (this.explicitlyCleared) return; + this.explicitlyCleared = true; + for (var i = 0; i < this.markers.length; ++i) + this.markers[i].clear(); + signalLater(this, "clear"); + }; + SharedTextMarker.prototype.find = function(side, lineObj) { + return this.primary.find(side, lineObj); + }; + + function markTextShared(doc, from, to, options, type) { + options = copyObj(options); + options.shared = false; + var markers = [markText(doc, from, to, options, type)], primary = markers[0]; + var widget = options.widgetNode; + linkedDocs(doc, function(doc) { + if (widget) options.widgetNode = widget.cloneNode(true); + markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); + for (var i = 0; i < doc.linked.length; ++i) + if (doc.linked[i].isParent) return; + primary = lst(markers); + }); + return new SharedTextMarker(markers, primary); + } + + function findSharedMarkers(doc) { + return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), + function(m) { return m.parent; }); + } + + function copySharedMarkers(doc, markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], pos = marker.find(); + var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); + if (cmp(mFrom, mTo)) { + var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); + marker.markers.push(subMark); + subMark.parent = marker; + } + } + } + + function detachSharedMarkers(markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], linked = [marker.primary.doc];; + linkedDocs(marker.primary.doc, function(d) { linked.push(d); }); + for (var j = 0; j < marker.markers.length; j++) { + var subMarker = marker.markers[j]; + if (indexOf(linked, subMarker.doc) == -1) { + subMarker.parent = null; + marker.markers.splice(j--, 1); + } + } + } + } + + // TEXTMARKER SPANS + + function MarkedSpan(marker, from, to) { + this.marker = marker; + this.from = from; this.to = to; + } + + // Search an array of spans for a span matching the given marker. + function getMarkedSpanFor(spans, marker) { + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) return span; + } + } + // Remove a span from an array, returning undefined if no spans are + // left (we don't store arrays for lines without spans). + function removeMarkedSpan(spans, span) { + for (var r, i = 0; i < spans.length; ++i) + if (spans[i] != span) (r || (r = [])).push(spans[i]); + return r; + } + // Add a span to a line. + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + span.marker.attachLine(line); + } + + // Used for the algorithm that adjusts markers for a change in the + // document. These functions cut an array of spans at a given + // character position, returning an array of remaining chunks (or + // undefined if nothing remains). + function markedSpansBefore(old, startCh, isInsert) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); + (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); + } + } + return nw; + } + function markedSpansAfter(old, endCh, isInsert) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); + (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, + span.to == null ? null : span.to - endCh)); + } + } + return nw; + } + + // Given a change object, compute the new set of marker spans that + // cover the line in which the change took place. Removes spans + // entirely within the change, reconnects spans belonging to the + // same marker that appear on both sides of the change, and cuts off + // spans partially within the change. Returns an array of span + // arrays with one element for each line in (after) the change. + function stretchSpansOverChange(doc, change) { + if (change.full) return null; + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; + if (!oldFirst && !oldLast) return null; + + var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); + + // Next, merge those two ends + var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) span.to = startCh; + else if (sameLine) span.to = found.to == null ? null : found.to + offset; + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i = 0; i < last.length; ++i) { + var span = last[i]; + if (span.to != null) span.to += offset; + if (span.from == null) { + var found = getMarkedSpanFor(first, span.marker); + if (!found) { + span.from = offset; + if (sameLine) (first || (first = [])).push(span); + } + } else { + span.from += offset; + if (sameLine) (first || (first = [])).push(span); + } + } + } + // Make sure we didn't create any zero-length spans + if (first) first = clearEmptySpans(first); + if (last && last != first) last = clearEmptySpans(last); + + var newMarkers = [first]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, gapMarkers; + if (gap > 0 && first) + for (var i = 0; i < first.length; ++i) + if (first[i].to == null) + (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null)); + for (var i = 0; i < gap; ++i) + newMarkers.push(gapMarkers); + newMarkers.push(last); + } + return newMarkers; + } + + // Remove spans that are empty and don't have a clearWhenEmpty + // option of false. + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) + spans.splice(i--, 1); + } + if (!spans.length) return null; + return spans; + } + + // Used for un/re-doing changes from the history. Combines the + // result of computing the existing spans with the set of spans that + // existed in the history (so that deleting around a span and then + // undoing brings back the span). + function mergeOldSpans(doc, change) { + var old = getOldSpans(doc, change); + var stretched = stretchSpansOverChange(doc, change); + if (!old) return stretched; + if (!stretched) return old; + + for (var i = 0; i < old.length; ++i) { + var oldCur = old[i], stretchCur = stretched[i]; + if (oldCur && stretchCur) { + spans: for (var j = 0; j < stretchCur.length; ++j) { + var span = stretchCur[j]; + for (var k = 0; k < oldCur.length; ++k) + if (oldCur[k].marker == span.marker) continue spans; + oldCur.push(span); + } + } else if (stretchCur) { + old[i] = stretchCur; + } + } + return old; + } + + // Used to 'clip' out readOnly ranges when making a change. + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function(line) { + if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + (markers || (markers = [])).push(mark); + } + }); + if (!markers) return null; + var parts = [{from: from, to: to}]; + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], m = mk.find(0); + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue; + var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); + if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) + newParts.push({from: p.from, to: m.from}); + if (dto > 0 || !mk.inclusiveRight && !dto) + newParts.push({from: m.to, to: p.to}); + parts.splice.apply(parts, newParts); + j += newParts.length - 1; + } + } + return parts; + } + + // Connect or disconnect spans from a line. + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) return; + for (var i = 0; i < spans.length; ++i) + spans[i].marker.detachLine(line); + line.markedSpans = null; + } + function attachMarkedSpans(line, spans) { + if (!spans) return; + for (var i = 0; i < spans.length; ++i) + spans[i].marker.attachLine(line); + line.markedSpans = spans; + } + + // Helpers used when computing which overlapping collapsed span + // counts as the larger one. + function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; } + function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; } + + // Returns a number indicating which of two overlapping collapsed + // spans is larger (and thus includes the other). Falls back to + // comparing ids when the spans cover exactly the same range. + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length; + if (lenDiff != 0) return lenDiff; + var aPos = a.find(), bPos = b.find(); + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); + if (fromCmp) return -fromCmp; + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); + if (toCmp) return toCmp; + return b.id - a.id; + } + + // Find out whether a line ends or starts in a collapsed span. If + // so, return the marker for that span. + function collapsedSpanAtSide(line, start) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) for (var sp, i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) + found = sp.marker; + } + return found; + } + function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); } + function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); } + + // Test whether there exists a collapsed span that partially + // overlaps (covers the start or end, but not both) of a new span. + // Such overlap is not allowed. + function conflictingCollapsedRange(doc, lineNo, from, to, marker) { + var line = getLine(doc, lineNo); + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (!sp.marker.collapsed) continue; + var found = sp.marker.find(0); + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue; + if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || + fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) + return true; + } + } + + // A visual line is a line as drawn on the screen. Folding, for + // example, can cause multiple logical lines to appear on the same + // visual line. This finds the start of the visual line that the + // given line is part of (usually that is the line itself). + function visualLine(line) { + var merged; + while (merged = collapsedSpanAtStart(line)) + line = merged.find(-1, true).line; + return line; + } + + // Returns an array of logical lines that continue the visual line + // started by the argument, or undefined if there are no such lines. + function visualLineContinued(line) { + var merged, lines; + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line; + (lines || (lines = [])).push(line); + } + return lines; + } + + // Get the line number of the start of the visual line that the + // given line number is part of. + function visualLineNo(doc, lineN) { + var line = getLine(doc, lineN), vis = visualLine(line); + if (line == vis) return lineN; + return lineNo(vis); + } + // Get the line number of the start of the next visual line after + // the given line. + function visualLineEndNo(doc, lineN) { + if (lineN > doc.lastLine()) return lineN; + var line = getLine(doc, lineN), merged; + if (!lineIsHidden(doc, line)) return lineN; + while (merged = collapsedSpanAtEnd(line)) + line = merged.find(1, true).line; + return lineNo(line) + 1; + } + + // Compute whether a line is hidden. Lines count as hidden when they + // are part of a visual line that starts with another line, or when + // they are entirely covered by collapsed, non-widget span. + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) for (var sp, i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) continue; + if (sp.from == null) return true; + if (sp.marker.widgetNode) continue; + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) + return true; + } + } + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find(1, true); + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)); + } + if (span.marker.inclusiveRight && span.to == line.text.length) + return true; + for (var sp, i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && + (sp.to == null || sp.to != span.from) && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(doc, line, sp)) return true; + } + } + + // LINE WIDGETS + + // Line widgets are block elements displayed above or below a line. + + var LineWidget = CodeMirror.LineWidget = function(doc, node, options) { + if (options) for (var opt in options) if (options.hasOwnProperty(opt)) + this[opt] = options[opt]; + this.doc = doc; + this.node = node; + }; + eventMixin(LineWidget); + + function adjustScrollWhenAboveVisible(cm, line, diff) { + if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) + addToScrollPos(cm, null, diff); + } + + LineWidget.prototype.clear = function() { + var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); + if (no == null || !ws) return; + for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); + if (!ws.length) line.widgets = null; + var height = widgetHeight(this); + updateLineHeight(line, Math.max(0, line.height - height)); + if (cm) runInOp(cm, function() { + adjustScrollWhenAboveVisible(cm, line, -height); + regLineChange(cm, no, "widget"); + }); + }; + LineWidget.prototype.changed = function() { + var oldH = this.height, cm = this.doc.cm, line = this.line; + this.height = null; + var diff = widgetHeight(this) - oldH; + if (!diff) return; + updateLineHeight(line, line.height + diff); + if (cm) runInOp(cm, function() { + cm.curOp.forceUpdate = true; + adjustScrollWhenAboveVisible(cm, line, diff); + }); + }; + + function widgetHeight(widget) { + if (widget.height != null) return widget.height; + var cm = widget.doc.cm; + if (!cm) return 0; + if (!contains(document.body, widget.node)) { + var parentStyle = "position: relative;"; + if (widget.coverGutter) + parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; + if (widget.noHScroll) + parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; + removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); + } + return widget.height = widget.node.parentNode.offsetHeight; + } + + function addLineWidget(doc, handle, node, options) { + var widget = new LineWidget(doc, node, options); + var cm = doc.cm; + if (cm && widget.noHScroll) cm.display.alignWidgets = true; + changeLine(doc, handle, "widget", function(line) { + var widgets = line.widgets || (line.widgets = []); + if (widget.insertAt == null) widgets.push(widget); + else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); + widget.line = line; + if (cm && !lineIsHidden(doc, line)) { + var aboveVisible = heightAtLine(line) < doc.scrollTop; + updateLineHeight(line, line.height + widgetHeight(widget)); + if (aboveVisible) addToScrollPos(cm, null, widget.height); + cm.curOp.forceUpdate = true; + } + return true; + }); + return widget; + } + + // LINE DATA STRUCTURE + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) { + this.text = text; + attachMarkedSpans(this, markedSpans); + this.height = estimateHeight ? estimateHeight(this) : 1; + }; + eventMixin(Line); + Line.prototype.lineNo = function() { return lineNo(this); }; + + // Change the content (text, markers) of a line. Automatically + // invalidates cached information and tries to re-estimate the + // line's height. + function updateLine(line, text, markedSpans, estimateHeight) { + line.text = text; + if (line.stateAfter) line.stateAfter = null; + if (line.styles) line.styles = null; + if (line.order != null) line.order = null; + detachMarkedSpans(line); + attachMarkedSpans(line, markedSpans); + var estHeight = estimateHeight ? estimateHeight(line) : 1; + if (estHeight != line.height) updateLineHeight(line, estHeight); + } + + // Detach a line from the document tree and its markers. + function cleanUpLine(line) { + line.parent = null; + detachMarkedSpans(line); + } + + function extractLineClasses(type, output) { + if (type) for (;;) { + var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); + if (!lineClass) break; + type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); + var prop = lineClass[1] ? "bgClass" : "textClass"; + if (output[prop] == null) + output[prop] = lineClass[2]; + else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) + output[prop] += " " + lineClass[2]; + } + return type; + } + + function callBlankLine(mode, state) { + if (mode.blankLine) return mode.blankLine(state); + if (!mode.innerMode) return; + var inner = CodeMirror.innerMode(mode, state); + if (inner.mode.blankLine) return inner.mode.blankLine(inner.state); + } + + function readToken(mode, stream, state, inner) { + for (var i = 0; i < 10; i++) { + if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode; + var style = mode.token(stream, state); + if (stream.pos > stream.start) return style; + } + throw new Error("Mode " + mode.name + " failed to advance stream."); + } + + // Utility for getTokenAt and getLineTokens + function takeToken(cm, pos, precise, asArray) { + function getObj(copy) { + return {start: stream.start, end: stream.pos, + string: stream.current(), + type: style || null, + state: copy ? copyState(doc.mode, state) : state}; + } + + var doc = cm.doc, mode = doc.mode, style; + pos = clipPos(doc, pos); + var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise); + var stream = new StringStream(line.text, cm.options.tabSize), tokens; + if (asArray) tokens = []; + while ((asArray || stream.pos < pos.ch) && !stream.eol()) { + stream.start = stream.pos; + style = readToken(mode, stream, state); + if (asArray) tokens.push(getObj(true)); + } + return asArray ? tokens : getObj(); + } + + // Run the given mode's parser over a line, calling f for each token. + function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { + var flattenSpans = mode.flattenSpans; + if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; + var curStart = 0, curStyle = null; + var stream = new StringStream(text, cm.options.tabSize), style; + var inner = cm.options.addModeClass && [null]; + if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses); + while (!stream.eol()) { + if (stream.pos > cm.options.maxHighlightLength) { + flattenSpans = false; + if (forceToEnd) processLine(cm, text, state, stream.pos); + stream.pos = text.length; + style = null; + } else { + style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses); + } + if (inner) { + var mName = inner[0].name; + if (mName) style = "m-" + (style ? mName + " " + style : mName); + } + if (!flattenSpans || curStyle != style) { + while (curStart < stream.start) { + curStart = Math.min(stream.start, curStart + 50000); + f(curStart, curStyle); + } + curStyle = style; + } + stream.start = stream.pos; + } + while (curStart < stream.pos) { + // Webkit seems to refuse to render text nodes longer than 57444 characters + var pos = Math.min(stream.pos, curStart + 50000); + f(pos, curStyle); + curStart = pos; + } + } + + // Compute a style array (an array starting with a mode generation + // -- for invalidation -- followed by pairs of end positions and + // style strings), which is used to highlight the tokens on the + // line. + function highlightLine(cm, line, state, forceToEnd) { + // A styles array always starts with a number identifying the + // mode/overlays that it is based on (for easy invalidation). + var st = [cm.state.modeGen], lineClasses = {}; + // Compute the base array of styles + runMode(cm, line.text, cm.doc.mode, state, function(end, style) { + st.push(end, style); + }, lineClasses, forceToEnd); + + // Run overlays, adjust style array. + for (var o = 0; o < cm.state.overlays.length; ++o) { + var overlay = cm.state.overlays[o], i = 1, at = 0; + runMode(cm, line.text, overlay.mode, true, function(end, style) { + var start = i; + // Ensure there's a token end at the current position, and that i points at it + while (at < end) { + var i_end = st[i]; + if (i_end > end) + st.splice(i, 1, end, st[i+1], i_end); + i += 2; + at = Math.min(end, i_end); + } + if (!style) return; + if (overlay.opaque) { + st.splice(start, i - start, end, "cm-overlay " + style); + i = start + 2; + } else { + for (; start < i; start += 2) { + var cur = st[start+1]; + st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style; + } + } + }, lineClasses); + } + + return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}; + } + + function getLineStyles(cm, line, updateFrontier) { + if (!line.styles || line.styles[0] != cm.state.modeGen) { + var state = getStateBefore(cm, lineNo(line)); + var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state); + line.stateAfter = state; + line.styles = result.styles; + if (result.classes) line.styleClasses = result.classes; + else if (line.styleClasses) line.styleClasses = null; + if (updateFrontier === cm.doc.frontier) cm.doc.frontier++; + } + return line.styles; + } + + // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. Used for lines that + // aren't currently visible. + function processLine(cm, text, state, startAt) { + var mode = cm.doc.mode; + var stream = new StringStream(text, cm.options.tabSize); + stream.start = stream.pos = startAt || 0; + if (text == "") callBlankLine(mode, state); + while (!stream.eol()) { + readToken(mode, stream, state); + stream.start = stream.pos; + } + } + + // Convert a style as returned by a mode (either null, or a string + // containing one or more styles) to a CSS style. This is cached, + // and also looks for line-wide styles. + var styleToClassCache = {}, styleToClassCacheWithMode = {}; + function interpretTokenStyle(style, options) { + if (!style || /^\s*$/.test(style)) return null; + var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; + return cache[style] || + (cache[style] = style.replace(/\S+/g, "cm-$&")); + } + + // Render the DOM representation of the text of a line. Also builds + // up a 'line map', which points at the DOM nodes that represent + // specific stretches of text, and is used by the measuring code. + // The returned object contains the DOM node, this map, and + // information about line-wide styles that were set by the mode. + function buildLineContent(cm, lineView) { + // The padding-right forces the element to have a 'border', which + // is needed on Webkit to be able to get line-level bounding + // rectangles for it (in measureChar). + var content = elt("span", null, null, webkit ? "padding-right: .1px" : null); + var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content, + col: 0, pos: 0, cm: cm, + trailingSpace: false, + splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")}; + lineView.measure = {}; + + // Iterate over the logical lines that make up this visual line. + for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { + var line = i ? lineView.rest[i - 1] : lineView.line, order; + builder.pos = 0; + builder.addToken = buildToken; + // Optionally wire in some hacks into the token-rendering + // algorithm, to deal with browser quirks. + if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line))) + builder.addToken = buildTokenBadBidi(builder.addToken, order); + builder.map = []; + var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); + insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); + if (line.styleClasses) { + if (line.styleClasses.bgClass) + builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); + if (line.styleClasses.textClass) + builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); + } + + // Ensure at least a single node is present, for measuring. + if (builder.map.length == 0) + builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); + + // Store the map and a cache object for the current logical line + if (i == 0) { + lineView.measure.map = builder.map; + lineView.measure.cache = {}; + } else { + (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map); + (lineView.measure.caches || (lineView.measure.caches = [])).push({}); + } + } + + // See issue #2901 + if (webkit) { + var last = builder.content.lastChild + if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) + builder.content.className = "cm-tab-wrap-hack"; + } + + signal(cm, "renderLine", cm, lineView.line, builder.pre); + if (builder.pre.className) + builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); + + return builder; + } + + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + ch.charCodeAt(0).toString(16); + token.setAttribute("aria-label", token.title); + return token; + } + + // Build up the DOM representation for a single token, and add it to + // the line map. Takes care to render special characters separately. + function buildToken(builder, text, style, startStyle, endStyle, title, css) { + if (!text) return; + var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text + var special = builder.cm.state.specialChars, mustWrap = false; + if (!special.test(text)) { + builder.col += text.length; + var content = document.createTextNode(displayText); + builder.map.push(builder.pos, builder.pos + text.length, content); + if (ie && ie_version < 9) mustWrap = true; + builder.pos += text.length; + } else { + var content = document.createDocumentFragment(), pos = 0; + while (true) { + special.lastIndex = pos; + var m = special.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + if (skipped) { + var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); + if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); + else content.appendChild(txt); + builder.map.push(builder.pos, builder.pos + skipped, txt); + builder.col += skipped; + builder.pos += skipped; + } + if (!m) break; + pos += skipped + 1; + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; + var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + txt.setAttribute("role", "presentation"); + txt.setAttribute("cm-text", "\t"); + builder.col += tabWidth; + } else if (m[0] == "\r" || m[0] == "\n") { + var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); + txt.setAttribute("cm-text", m[0]); + builder.col += 1; + } else { + var txt = builder.cm.options.specialCharPlaceholder(m[0]); + txt.setAttribute("cm-text", m[0]); + if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); + else content.appendChild(txt); + builder.col += 1; + } + builder.map.push(builder.pos, builder.pos + 1, txt); + builder.pos++; + } + } + builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32 + if (style || startStyle || endStyle || mustWrap || css) { + var fullStyle = style || ""; + if (startStyle) fullStyle += startStyle; + if (endStyle) fullStyle += endStyle; + var token = elt("span", [content], fullStyle, css); + if (title) token.title = title; + return builder.content.appendChild(token); + } + builder.content.appendChild(content); + } + + function splitSpaces(text, trailingBefore) { + if (text.length > 1 && !/ /.test(text)) return text + var spaceBefore = trailingBefore, result = "" + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i) + if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) + ch = "\u00a0" + result += ch + spaceBefore = ch == " " + } + return result + } + + // Work around nonsense dimensions being reported for stretches of + // right-to-left text. + function buildTokenBadBidi(inner, order) { + return function(builder, text, style, startStyle, endStyle, title, css) { + style = style ? style + " cm-force-border" : "cm-force-border"; + var start = builder.pos, end = start + text.length; + for (;;) { + // Find the part that overlaps with the start of this text + for (var i = 0; i < order.length; i++) { + var part = order[i]; + if (part.to > start && part.from <= start) break; + } + if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css); + inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css); + startStyle = null; + text = text.slice(part.to - start); + start = part.to; + } + }; + } + + function buildCollapsedSpan(builder, size, marker, ignoreWidget) { + var widget = !ignoreWidget && marker.widgetNode; + if (widget) builder.map.push(builder.pos, builder.pos + size, widget); + if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { + if (!widget) + widget = builder.content.appendChild(document.createElement("span")); + widget.setAttribute("cm-marker", marker.id); + } + if (widget) { + builder.cm.display.input.setUneditable(widget); + builder.content.appendChild(widget); + } + builder.pos += size; + builder.trailingSpace = false + } + + // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + function insertLineContent(line, builder, styles) { + var spans = line.markedSpans, allText = line.text, at = 0; + if (!spans) { + for (var i = 1; i < styles.length; i+=2) + builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options)); + return; + } + + var len = allText.length, pos = 0, i = 1, text = "", style, css; + var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed; + for (;;) { + if (nextChange == pos) { // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = title = css = ""; + collapsed = null; nextChange = Infinity; + var foundBookmarks = [], endStyles + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], m = sp.marker; + if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { + foundBookmarks.push(m); + } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { + if (sp.to != null && sp.to != pos && nextChange > sp.to) { + nextChange = sp.to; + spanEndStyle = ""; + } + if (m.className) spanStyle += " " + m.className; + if (m.css) css = (css ? css + ";" : "") + m.css; + if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; + if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to) + if (m.title && !title) title = m.title; + if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) + collapsed = sp; + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from; + } + } + if (endStyles) for (var j = 0; j < endStyles.length; j += 2) + if (endStyles[j + 1] == nextChange) spanEndStyle += " " + endStyles[j] + + if (!collapsed || collapsed.from == pos) for (var j = 0; j < foundBookmarks.length; ++j) + buildCollapsedSpan(builder, 0, foundBookmarks[j]); + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, + collapsed.marker, collapsed.from == null); + if (collapsed.to == null) return; + if (collapsed.to == pos) collapsed = false; + } + } + if (pos >= len) break; + + var upto = Math.min(len, nextChange); + while (true) { + if (text) { + var end = pos + text.length; + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text; + builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css); + } + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} + pos = end; + spanStartStyle = ""; + } + text = allText.slice(at, at = styles[i++]); + style = interpretTokenStyle(styles[i++], builder.cm.options); + } + } + } + + // DOCUMENT DATA STRUCTURE + + // By default, updates that start and end at the beginning of a line + // are treated specially, in order to make the association of line + // widgets and marker elements with the text behave more intuitive. + function isWholeLineUpdate(doc, change) { + return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && + (!doc.cm || doc.cm.options.wholeLineUpdateBefore); + } + + // Perform a change on the document data structure. + function updateDoc(doc, change, markedSpans, estimateHeight) { + function spansFor(n) {return markedSpans ? markedSpans[n] : null;} + function update(line, text, spans) { + updateLine(line, text, spans, estimateHeight); + signalLater(line, "change", line, change); + } + function linesFor(start, end) { + for (var i = start, result = []; i < end; ++i) + result.push(new Line(text[i], spansFor(i), estimateHeight)); + return result; + } + + var from = change.from, to = change.to, text = change.text; + var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); + var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; + + // Adjust the line structure + if (change.full) { + doc.insert(0, linesFor(0, text.length)); + doc.remove(text.length, doc.size - text.length); + } else if (isWholeLineUpdate(doc, change)) { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = linesFor(0, text.length - 1); + update(lastLine, lastLine.text, lastSpans); + if (nlines) doc.remove(from.line, nlines); + if (added.length) doc.insert(from.line, added); + } else if (firstLine == lastLine) { + if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); + } else { + var added = linesFor(1, text.length - 1); + added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + doc.insert(from.line + 1, added); + } + } else if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); + doc.remove(from.line + 1, nlines); + } else { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); + var added = linesFor(1, text.length - 1); + if (nlines > 1) doc.remove(from.line + 1, nlines - 1); + doc.insert(from.line + 1, added); + } + + signalLater(doc, "change", doc, change); + } + + // The document is represented as a BTree consisting of leaves, with + // chunk of lines in them, and branches, with up to ten leaves or + // other branch nodes below them. The top node is always a branch + // node, and is the document object itself (meaning it has + // additional methods and properties). + // + // All nodes have parent links. The tree is used both to go from + // line numbers to line objects, and to go from objects to numbers. + // It also indexes by height, and is used to convert between height + // and line object, and to find the total height of the document. + // + // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html + + function LeafChunk(lines) { + this.lines = lines; + this.parent = null; + for (var i = 0, height = 0; i < lines.length; ++i) { + lines[i].parent = this; + height += lines[i].height; + } + this.height = height; + } + + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length; }, + // Remove the n lines at offset 'at'. + removeInner: function(at, n) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i]; + this.height -= line.height; + cleanUpLine(line); + signalLater(line, "delete"); + } + this.lines.splice(at, n); + }, + // Helper used to collapse a small branch into a single leaf. + collapse: function(lines) { + lines.push.apply(lines, this.lines); + }, + // Insert the given array of lines at offset 'at', count them as + // having the given height. + insertInner: function(at, lines, height) { + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + for (var i = 0; i < lines.length; ++i) lines[i].parent = this; + }, + // Used to iterate over a part of the tree. + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) + if (op(this.lines[at])) return true; + } + }; + + function BranchChunk(children) { + this.children = children; + var size = 0, height = 0; + for (var i = 0; i < children.length; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this; + } + this.size = size; + this.height = height; + this.parent = null; + } + + BranchChunk.prototype = { + chunkSize: function() { return this.size; }, + removeInner: function(at, n) { + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.removeInner(at, rm); + this.height -= oldHeight - child.height; + if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) break; + at = 0; + } else at -= sz; + } + // If the result is smaller than 25 lines, ensure that it is a + // single leaf node. + if (this.size - n < 25 && + (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + collapse: function(lines) { + for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines); + }, + insertInner: function(at, lines, height) { + this.size += lines.length; + this.height += height; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertInner(at, lines, height); + if (child.lines && child.lines.length > 50) { + // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. + // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. + var remaining = child.lines.length % 25 + 25 + for (var pos = remaining; pos < child.lines.length;) { + var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); + child.height -= leaf.height; + this.children.splice(++i, 0, leaf); + leaf.parent = this; + } + child.lines = child.lines.slice(0, remaining); + this.maybeSpill(); + } + break; + } + at -= sz; + } + }, + // When a node has grown, check whether it should be split. + maybeSpill: function() { + if (this.children.length <= 10) return; + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10); + me.parent.maybeSpill(); + }, + iterN: function(at, n, op) { + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) return true; + if ((n -= used) == 0) break; + at = 0; + } else at -= sz; + } + } + }; + + var nextDocId = 0; + var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) { + if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep); + if (firstLine == null) firstLine = 0; + + BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); + this.first = firstLine; + this.scrollTop = this.scrollLeft = 0; + this.cantEdit = false; + this.cleanGeneration = 1; + this.frontier = firstLine; + var start = Pos(firstLine, 0); + this.sel = simpleSelection(start); + this.history = new History(null); + this.id = ++nextDocId; + this.modeOption = mode; + this.lineSep = lineSep; + this.extend = false; + + if (typeof text == "string") text = this.splitLines(text); + updateDoc(this, {from: start, to: start, text: text}); + setSelection(this, simpleSelection(start), sel_dontScroll); + }; + + Doc.prototype = createObj(BranchChunk.prototype, { + constructor: Doc, + // Iterate over the document. Supports two forms -- with only one + // argument, it calls that for each line in the document. With + // three, it iterates over the range given by the first two (with + // the second being non-inclusive). + iter: function(from, to, op) { + if (op) this.iterN(from - this.first, to - from, op); + else this.iterN(this.first, this.first + this.size, from); + }, + + // Non-public interface for adding and removing lines. + insert: function(at, lines) { + var height = 0; + for (var i = 0; i < lines.length; ++i) height += lines[i].height; + this.insertInner(at - this.first, lines, height); + }, + remove: function(at, n) { this.removeInner(at - this.first, n); }, + + // From here, the methods are part of the public interface. Most + // are also available from CodeMirror (editor) instances. + + getValue: function(lineSep) { + var lines = getLines(this, this.first, this.first + this.size); + if (lineSep === false) return lines; + return lines.join(lineSep || this.lineSeparator()); + }, + setValue: docMethodOp(function(code) { + var top = Pos(this.first, 0), last = this.first + this.size - 1; + makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), + text: this.splitLines(code), origin: "setValue", full: true}, true); + setSelection(this, simpleSelection(top)); + }), + replaceRange: function(code, from, to, origin) { + from = clipPos(this, from); + to = to ? clipPos(this, to) : from; + replaceRange(this, code, from, to, origin); + }, + getRange: function(from, to, lineSep) { + var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); + if (lineSep === false) return lines; + return lines.join(lineSep || this.lineSeparator()); + }, + + getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;}, + + getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);}, + getLineNumber: function(line) {return lineNo(line);}, + + getLineHandleVisualStart: function(line) { + if (typeof line == "number") line = getLine(this, line); + return visualLine(line); + }, + + lineCount: function() {return this.size;}, + firstLine: function() {return this.first;}, + lastLine: function() {return this.first + this.size - 1;}, + + clipPos: function(pos) {return clipPos(this, pos);}, + + getCursor: function(start) { + var range = this.sel.primary(), pos; + if (start == null || start == "head") pos = range.head; + else if (start == "anchor") pos = range.anchor; + else if (start == "end" || start == "to" || start === false) pos = range.to(); + else pos = range.from(); + return pos; + }, + listSelections: function() { return this.sel.ranges; }, + somethingSelected: function() {return this.sel.somethingSelected();}, + + setCursor: docMethodOp(function(line, ch, options) { + setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); + }), + setSelection: docMethodOp(function(anchor, head, options) { + setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); + }), + extendSelection: docMethodOp(function(head, other, options) { + extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); + }), + extendSelections: docMethodOp(function(heads, options) { + extendSelections(this, clipPosArray(this, heads), options); + }), + extendSelectionsBy: docMethodOp(function(f, options) { + var heads = map(this.sel.ranges, f); + extendSelections(this, clipPosArray(this, heads), options); + }), + setSelections: docMethodOp(function(ranges, primary, options) { + if (!ranges.length) return; + for (var i = 0, out = []; i < ranges.length; i++) + out[i] = new Range(clipPos(this, ranges[i].anchor), + clipPos(this, ranges[i].head)); + if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex); + setSelection(this, normalizeSelection(out, primary), options); + }), + addSelection: docMethodOp(function(anchor, head, options) { + var ranges = this.sel.ranges.slice(0); + ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); + setSelection(this, normalizeSelection(ranges, ranges.length - 1), options); + }), + + getSelection: function(lineSep) { + var ranges = this.sel.ranges, lines; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this, ranges[i].from(), ranges[i].to()); + lines = lines ? lines.concat(sel) : sel; + } + if (lineSep === false) return lines; + else return lines.join(lineSep || this.lineSeparator()); + }, + getSelections: function(lineSep) { + var parts = [], ranges = this.sel.ranges; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this, ranges[i].from(), ranges[i].to()); + if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator()); + parts[i] = sel; + } + return parts; + }, + replaceSelection: function(code, collapse, origin) { + var dup = []; + for (var i = 0; i < this.sel.ranges.length; i++) + dup[i] = code; + this.replaceSelections(dup, collapse, origin || "+input"); + }, + replaceSelections: docMethodOp(function(code, collapse, origin) { + var changes = [], sel = this.sel; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin}; + } + var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); + for (var i = changes.length - 1; i >= 0; i--) + makeChange(this, changes[i]); + if (newSel) setSelectionReplaceHistory(this, newSel); + else if (this.cm) ensureCursorVisible(this.cm); + }), + undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), + redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), + undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), + redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), + + setExtending: function(val) {this.extend = val;}, + getExtending: function() {return this.extend;}, + + historySize: function() { + var hist = this.history, done = 0, undone = 0; + for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done; + for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone; + return {undo: done, redo: undone}; + }, + clearHistory: function() {this.history = new History(this.history.maxGeneration);}, + + markClean: function() { + this.cleanGeneration = this.changeGeneration(true); + }, + changeGeneration: function(forceSplit) { + if (forceSplit) + this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; + return this.history.generation; + }, + isClean: function (gen) { + return this.history.generation == (gen || this.cleanGeneration); + }, + + getHistory: function() { + return {done: copyHistoryArray(this.history.done), + undone: copyHistoryArray(this.history.undone)}; + }, + setHistory: function(histData) { + var hist = this.history = new History(this.history.maxGeneration); + hist.done = copyHistoryArray(histData.done.slice(0), null, true); + hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); + }, + + addLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + if (!line[prop]) line[prop] = cls; + else if (classTest(cls).test(line[prop])) return false; + else line[prop] += " " + cls; + return true; + }); + }), + removeLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + var cur = line[prop]; + if (!cur) return false; + else if (cls == null) line[prop] = null; + else { + var found = cur.match(classTest(cls)); + if (!found) return false; + var end = found.index + found[0].length; + line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; + } + return true; + }); + }), + + addLineWidget: docMethodOp(function(handle, node, options) { + return addLineWidget(this, handle, node, options); + }), + removeLineWidget: function(widget) { widget.clear(); }, + + markText: function(from, to, options) { + return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range"); + }, + setBookmark: function(pos, options) { + var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft, + clearWhenEmpty: false, shared: options && options.shared, + handleMouseEvents: options && options.handleMouseEvents}; + pos = clipPos(this, pos); + return markText(this, pos, pos, realOpts, "bookmark"); + }, + findMarksAt: function(pos) { + pos = clipPos(this, pos); + var markers = [], spans = getLine(this, pos.line).markedSpans; + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + markers.push(span.marker.parent || span.marker); + } + return markers; + }, + findMarks: function(from, to, filter) { + from = clipPos(this, from); to = clipPos(this, to); + var found = [], lineNo = from.line; + this.iter(from.line, to.line + 1, function(line) { + var spans = line.markedSpans; + if (spans) for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + if (!(span.to != null && lineNo == from.line && from.ch >= span.to || + span.from == null && lineNo != from.line || + span.from != null && lineNo == to.line && span.from >= to.ch) && + (!filter || filter(span.marker))) + found.push(span.marker.parent || span.marker); + } + ++lineNo; + }); + return found; + }, + getAllMarks: function() { + var markers = []; + this.iter(function(line) { + var sps = line.markedSpans; + if (sps) for (var i = 0; i < sps.length; ++i) + if (sps[i].from != null) markers.push(sps[i].marker); + }); + return markers; + }, + + posFromIndex: function(off) { + var ch, lineNo = this.first, sepSize = this.lineSeparator().length; + this.iter(function(line) { + var sz = line.text.length + sepSize; + if (sz > off) { ch = off; return true; } + off -= sz; + ++lineNo; + }); + return clipPos(this, Pos(lineNo, ch)); + }, + indexFromPos: function (coords) { + coords = clipPos(this, coords); + var index = coords.ch; + if (coords.line < this.first || coords.ch < 0) return 0; + var sepSize = this.lineSeparator().length; + this.iter(this.first, coords.line, function (line) { + index += line.text.length + sepSize; + }); + return index; + }, + + copy: function(copyHistory) { + var doc = new Doc(getLines(this, this.first, this.first + this.size), + this.modeOption, this.first, this.lineSep); + doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; + doc.sel = this.sel; + doc.extend = false; + if (copyHistory) { + doc.history.undoDepth = this.history.undoDepth; + doc.setHistory(this.getHistory()); + } + return doc; + }, + + linkedDoc: function(options) { + if (!options) options = {}; + var from = this.first, to = this.first + this.size; + if (options.from != null && options.from > from) from = options.from; + if (options.to != null && options.to < to) to = options.to; + var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep); + if (options.sharedHist) copy.history = this.history; + (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); + copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; + copySharedMarkers(copy, findSharedMarkers(this)); + return copy; + }, + unlinkDoc: function(other) { + if (other instanceof CodeMirror) other = other.doc; + if (this.linked) for (var i = 0; i < this.linked.length; ++i) { + var link = this.linked[i]; + if (link.doc != other) continue; + this.linked.splice(i, 1); + other.unlinkDoc(this); + detachSharedMarkers(findSharedMarkers(this)); + break; + } + // If the histories were shared, split them again + if (other.history == this.history) { + var splitIds = [other.id]; + linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true); + other.history = new History(null); + other.history.done = copyHistoryArray(this.history.done, splitIds); + other.history.undone = copyHistoryArray(this.history.undone, splitIds); + } + }, + iterLinkedDocs: function(f) {linkedDocs(this, f);}, + + getMode: function() {return this.mode;}, + getEditor: function() {return this.cm;}, + + splitLines: function(str) { + if (this.lineSep) return str.split(this.lineSep); + return splitLinesAuto(str); + }, + lineSeparator: function() { return this.lineSep || "\n"; } + }); + + // Public alias. + Doc.prototype.eachLine = Doc.prototype.iter; + + // Set up methods on CodeMirror's prototype to redirect to the editor's document. + var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); + for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) + CodeMirror.prototype[prop] = (function(method) { + return function() {return method.apply(this.doc, arguments);}; + })(Doc.prototype[prop]); + + eventMixin(Doc); + + // Call f for all linked documents. + function linkedDocs(doc, f, sharedHistOnly) { + function propagate(doc, skip, sharedHist) { + if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) { + var rel = doc.linked[i]; + if (rel.doc == skip) continue; + var shared = sharedHist && rel.sharedHist; + if (sharedHistOnly && !shared) continue; + f(rel.doc, shared); + propagate(rel.doc, doc, shared); + } + } + propagate(doc, null, true); + } + + // Attach a document to an editor. + function attachDoc(cm, doc) { + if (doc.cm) throw new Error("This document is already in use."); + cm.doc = doc; + doc.cm = cm; + estimateLineHeights(cm); + loadMode(cm); + if (!cm.options.lineWrapping) findMaxLine(cm); + cm.options.mode = doc.modeOption; + regChange(cm); + } + + // LINE UTILITIES + + // Find the line object corresponding to the given line number. + function getLine(doc, n) { + n -= doc.first; + if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document."); + for (var chunk = doc; !chunk.lines;) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break; } + n -= sz; + } + } + return chunk.lines[n]; + } + + // Get the part of a document between two positions, as an array of + // strings. + function getBetween(doc, start, end) { + var out = [], n = start.line; + doc.iter(start.line, end.line + 1, function(line) { + var text = line.text; + if (n == end.line) text = text.slice(0, end.ch); + if (n == start.line) text = text.slice(start.ch); + out.push(text); + ++n; + }); + return out; + } + // Get the lines between from and to, as array of strings. + function getLines(doc, from, to) { + var out = []; + doc.iter(from, to, function(line) { out.push(line.text); }); + return out; + } + + // Update the height of a line, propagating the height change + // upwards to parent nodes. + function updateLineHeight(line, height) { + var diff = height - line.height; + if (diff) for (var n = line; n; n = n.parent) n.height += diff; + } + + // Given a line object, find its line number by walking up through + // its parent links. + function lineNo(line) { + if (line.parent == null) return null; + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) break; + no += chunk.children[i].chunkSize(); + } + } + return no + cur.first; + } + + // Find the line at the given vertical position, using the height + // information in the document tree. + function lineAtHeight(chunk, h) { + var n = chunk.first; + outer: do { + for (var i = 0; i < chunk.children.length; ++i) { + var child = chunk.children[i], ch = child.height; + if (h < ch) { chunk = child; continue outer; } + h -= ch; + n += child.chunkSize(); + } + return n; + } while (!chunk.lines); + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) break; + h -= lh; + } + return n + i; + } + + + // Find the height above the given line. + function heightAtLine(lineObj) { + lineObj = visualLine(lineObj); + + var h = 0, chunk = lineObj.parent; + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + if (line == lineObj) break; + else h += line.height; + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i = 0; i < p.children.length; ++i) { + var cur = p.children[i]; + if (cur == chunk) break; + else h += cur.height; + } + } + return h; + } + + // Get the bidi ordering for the given line (and cache it). Returns + // false for lines that are fully left-to-right, and an array of + // BidiSpan objects otherwise. + function getOrder(line) { + var order = line.order; + if (order == null) order = line.order = bidiOrdering(line.text); + return order; + } + + // HISTORY + + function History(startGen) { + // Arrays of change events and selections. Doing something adds an + // event to done and clears undo. Undoing moves events from done + // to undone, redoing moves them in the other direction. + this.done = []; this.undone = []; + this.undoDepth = Infinity; + // Used to track when changes can be merged into a single undo + // event + this.lastModTime = this.lastSelTime = 0; + this.lastOp = this.lastSelOp = null; + this.lastOrigin = this.lastSelOrigin = null; + // Used by the isClean() method + this.generation = this.maxGeneration = startGen || 1; + } + + // Create a history change event from an updateDoc-style change + // object. + function historyChangeFromChange(doc, change) { + var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; + attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); + linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true); + return histChange; + } + + // Pop all selection events off the end of a history array. Stop at + // a change event. + function clearSelectionEvents(array) { + while (array.length) { + var last = lst(array); + if (last.ranges) array.pop(); + else break; + } + } + + // Find the top change event in the history. Pop off selection + // events that are in the way. + function lastChangeEvent(hist, force) { + if (force) { + clearSelectionEvents(hist.done); + return lst(hist.done); + } else if (hist.done.length && !lst(hist.done).ranges) { + return lst(hist.done); + } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { + hist.done.pop(); + return lst(hist.done); + } + } + + // Register a change in the history. Merges changes that are within + // a single operation, ore are close together with an origin that + // allows merging (starting with "+") into a single event. + function addChangeToHistory(doc, change, selAfter, opId) { + var hist = doc.history; + hist.undone.length = 0; + var time = +new Date, cur; + + if ((hist.lastOp == opId || + hist.lastOrigin == change.origin && change.origin && + ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) || + change.origin.charAt(0) == "*")) && + (cur = lastChangeEvent(hist, hist.lastOp == opId))) { + // Merge this change into the last event + var last = lst(cur.changes); + if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { + // Optimized case for simple insertion -- don't want to add + // new changesets for every character typed + last.to = changeEnd(change); + } else { + // Add new sub-event + cur.changes.push(historyChangeFromChange(doc, change)); + } + } else { + // Can not be merged, start a new event. + var before = lst(hist.done); + if (!before || !before.ranges) + pushSelectionToHistory(doc.sel, hist.done); + cur = {changes: [historyChangeFromChange(doc, change)], + generation: hist.generation}; + hist.done.push(cur); + while (hist.done.length > hist.undoDepth) { + hist.done.shift(); + if (!hist.done[0].ranges) hist.done.shift(); + } + } + hist.done.push(selAfter); + hist.generation = ++hist.maxGeneration; + hist.lastModTime = hist.lastSelTime = time; + hist.lastOp = hist.lastSelOp = opId; + hist.lastOrigin = hist.lastSelOrigin = change.origin; + + if (!last) signal(doc, "historyAdded"); + } + + function selectionEventCanBeMerged(doc, origin, prev, sel) { + var ch = origin.charAt(0); + return ch == "*" || + ch == "+" && + prev.ranges.length == sel.ranges.length && + prev.somethingSelected() == sel.somethingSelected() && + new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500); + } + + // Called whenever the selection changes, sets the new selection as + // the pending selection in the history, and pushes the old pending + // selection into the 'done' array when it was significantly + // different (in number of selected ranges, emptiness, or time). + function addSelectionToHistory(doc, sel, opId, options) { + var hist = doc.history, origin = options && options.origin; + + // A new event is started when the previous origin does not match + // the current, or the origins don't allow matching. Origins + // starting with * are always merged, those starting with + are + // merged when similar and close together in time. + if (opId == hist.lastSelOp || + (origin && hist.lastSelOrigin == origin && + (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || + selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) + hist.done[hist.done.length - 1] = sel; + else + pushSelectionToHistory(sel, hist.done); + + hist.lastSelTime = +new Date; + hist.lastSelOrigin = origin; + hist.lastSelOp = opId; + if (options && options.clearRedo !== false) + clearSelectionEvents(hist.undone); + } + + function pushSelectionToHistory(sel, dest) { + var top = lst(dest); + if (!(top && top.ranges && top.equals(sel))) + dest.push(sel); + } + + // Used to store marked span information in the history. + function attachLocalSpans(doc, change, from, to) { + var existing = change["spans_" + doc.id], n = 0; + doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) { + if (line.markedSpans) + (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; + ++n; + }); + } + + // When un/re-doing restores text containing marked spans, those + // that have been explicitly cleared should not be restored. + function removeClearedSpans(spans) { + if (!spans) return null; + for (var i = 0, out; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); } + else if (out) out.push(spans[i]); + } + return !out ? spans : out.length ? out : null; + } + + // Retrieve and filter the old marked spans stored in a change event. + function getOldSpans(doc, change) { + var found = change["spans_" + doc.id]; + if (!found) return null; + for (var i = 0, nw = []; i < change.text.length; ++i) + nw.push(removeClearedSpans(found[i])); + return nw; + } + + // Used both to provide a JSON-safe object in .getHistory, and, when + // detaching a document, to split the history in two + function copyHistoryArray(events, newGroup, instantiateSel) { + for (var i = 0, copy = []; i < events.length; ++i) { + var event = events[i]; + if (event.ranges) { + copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); + continue; + } + var changes = event.changes, newChanges = []; + copy.push({changes: newChanges}); + for (var j = 0; j < changes.length; ++j) { + var change = changes[j], m; + newChanges.push({from: change.from, to: change.to, text: change.text}); + if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) { + if (indexOf(newGroup, Number(m[1])) > -1) { + lst(newChanges)[prop] = change[prop]; + delete change[prop]; + } + } + } + } + return copy; + } + + // Rebasing/resetting history to deal with externally-sourced changes + + function rebaseHistSelSingle(pos, from, to, diff) { + if (to < pos.line) { + pos.line += diff; + } else if (from < pos.line) { + pos.line = from; + pos.ch = 0; + } + } + + // Tries to rebase an array of history events given a change in the + // document. If the change touches the same lines as the event, the + // event, and everything 'behind' it, is discarded. If the change is + // before the event, the event's positions are updated. Uses a + // copy-on-write scheme for the positions, to avoid having to + // reallocate them all on every rebase, but also avoid problems with + // shared position objects being unsafely updated. + function rebaseHistArray(array, from, to, diff) { + for (var i = 0; i < array.length; ++i) { + var sub = array[i], ok = true; + if (sub.ranges) { + if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } + for (var j = 0; j < sub.ranges.length; j++) { + rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); + rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); + } + continue; + } + for (var j = 0; j < sub.changes.length; ++j) { + var cur = sub.changes[j]; + if (to < cur.from.line) { + cur.from = Pos(cur.from.line + diff, cur.from.ch); + cur.to = Pos(cur.to.line + diff, cur.to.ch); + } else if (from <= cur.to.line) { + ok = false; + break; + } + } + if (!ok) { + array.splice(0, i + 1); + i = 0; + } + } + } + + function rebaseHist(hist, change) { + var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; + rebaseHistArray(hist.done, from, to, diff); + rebaseHistArray(hist.undone, from, to, diff); + } + + // EVENT UTILITIES + + // Due to the fact that we still support jurassic IE versions, some + // compatibility wrappers are needed. + + var e_preventDefault = CodeMirror.e_preventDefault = function(e) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + }; + var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) { + if (e.stopPropagation) e.stopPropagation(); + else e.cancelBubble = true; + }; + function e_defaultPrevented(e) { + return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false; + } + var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);}; + + function e_target(e) {return e.target || e.srcElement;} + function e_button(e) { + var b = e.which; + if (b == null) { + if (e.button & 1) b = 1; + else if (e.button & 2) b = 3; + else if (e.button & 4) b = 2; + } + if (mac && e.ctrlKey && b == 1) b = 3; + return b; + } + + // EVENT HANDLING + + // Lightweight event framework. on/off also work on DOM nodes, + // registering native DOM handlers. + + var on = CodeMirror.on = function(emitter, type, f) { + if (emitter.addEventListener) + emitter.addEventListener(type, f, false); + else if (emitter.attachEvent) + emitter.attachEvent("on" + type, f); + else { + var map = emitter._handlers || (emitter._handlers = {}); + var arr = map[type] || (map[type] = []); + arr.push(f); + } + }; + + var noHandlers = [] + function getHandlers(emitter, type, copy) { + var arr = emitter._handlers && emitter._handlers[type] + if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers + else return arr || noHandlers + } + + var off = CodeMirror.off = function(emitter, type, f) { + if (emitter.removeEventListener) + emitter.removeEventListener(type, f, false); + else if (emitter.detachEvent) + emitter.detachEvent("on" + type, f); + else { + var handlers = getHandlers(emitter, type, false) + for (var i = 0; i < handlers.length; ++i) + if (handlers[i] == f) { handlers.splice(i, 1); break; } + } + }; + + var signal = CodeMirror.signal = function(emitter, type /*, values...*/) { + var handlers = getHandlers(emitter, type, true) + if (!handlers.length) return; + var args = Array.prototype.slice.call(arguments, 2); + for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args); + }; + + var orphanDelayedCallbacks = null; + + // Often, we want to signal events at a point where we are in the + // middle of some work, but don't want the handler to start calling + // other methods on the editor, which might be in an inconsistent + // state or simply not expect any other events to happen. + // signalLater looks whether there are any handlers, and schedules + // them to be executed when the last operation ends, or, if no + // operation is active, when a timeout fires. + function signalLater(emitter, type /*, values...*/) { + var arr = getHandlers(emitter, type, false) + if (!arr.length) return; + var args = Array.prototype.slice.call(arguments, 2), list; + if (operationGroup) { + list = operationGroup.delayedCallbacks; + } else if (orphanDelayedCallbacks) { + list = orphanDelayedCallbacks; + } else { + list = orphanDelayedCallbacks = []; + setTimeout(fireOrphanDelayed, 0); + } + function bnd(f) {return function(){f.apply(null, args);};}; + for (var i = 0; i < arr.length; ++i) + list.push(bnd(arr[i])); + } + + function fireOrphanDelayed() { + var delayed = orphanDelayedCallbacks; + orphanDelayedCallbacks = null; + for (var i = 0; i < delayed.length; ++i) delayed[i](); + } + + // The DOM events that CodeMirror handles can be overridden by + // registering a (non-DOM) handler on the editor for the event name, + // and preventDefault-ing the event in that handler. + function signalDOMEvent(cm, e, override) { + if (typeof e == "string") + e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; + signal(cm, override || e.type, cm, e); + return e_defaultPrevented(e) || e.codemirrorIgnore; + } + + function signalCursorActivity(cm) { + var arr = cm._handlers && cm._handlers.cursorActivity; + if (!arr) return; + var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); + for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1) + set.push(arr[i]); + } + + function hasHandler(emitter, type) { + return getHandlers(emitter, type).length > 0 + } + + // Add on and off methods to a constructor's prototype, to make + // registering events on such objects more convenient. + function eventMixin(ctor) { + ctor.prototype.on = function(type, f) {on(this, type, f);}; + ctor.prototype.off = function(type, f) {off(this, type, f);}; + } + + // MISC UTILITIES + + // Number of pixels added to scroller and sizer to hide scrollbar + var scrollerGap = 30; + + // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; + + // Reused option objects for setSelection & friends + var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; + + function Delayed() {this.id = null;} + Delayed.prototype.set = function(ms, f) { + clearTimeout(this.id); + this.id = setTimeout(f, ms); + }; + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) end = string.length; + } + for (var i = startIndex || 0, n = startValue || 0;;) { + var nextTab = string.indexOf("\t", i); + if (nextTab < 0 || nextTab >= end) + return n + (end - i); + n += nextTab - i; + n += tabSize - (n % tabSize); + i = nextTab + 1; + } + }; + + // The inverse of countColumn -- find the offset that corresponds to + // a particular column. + var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) { + for (var pos = 0, col = 0;;) { + var nextTab = string.indexOf("\t", pos); + if (nextTab == -1) nextTab = string.length; + var skipped = nextTab - pos; + if (nextTab == string.length || col + skipped >= goal) + return pos + Math.min(skipped, goal - col); + col += nextTab - pos; + col += tabSize - (col % tabSize); + pos = nextTab + 1; + if (col >= goal) return pos; + } + } + + var spaceStrs = [""]; + function spaceStr(n) { + while (spaceStrs.length <= n) + spaceStrs.push(lst(spaceStrs) + " "); + return spaceStrs[n]; + } + + function lst(arr) { return arr[arr.length-1]; } + + var selectInput = function(node) { node.select(); }; + if (ios) // Mobile Safari apparently has a bug where select() is broken. + selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; + else if (ie) // Suppress mysterious IE10 errors + selectInput = function(node) { try { node.select(); } catch(_e) {} }; + + function indexOf(array, elt) { + for (var i = 0; i < array.length; ++i) + if (array[i] == elt) return i; + return -1; + } + function map(array, f) { + var out = []; + for (var i = 0; i < array.length; i++) out[i] = f(array[i], i); + return out; + } + + function nothing() {} + + function createObj(base, props) { + var inst; + if (Object.create) { + inst = Object.create(base); + } else { + nothing.prototype = base; + inst = new nothing(); + } + if (props) copyObj(props, inst); + return inst; + }; + + function copyObj(obj, target, overwrite) { + if (!target) target = {}; + for (var prop in obj) + if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) + target[prop] = obj[prop]; + return target; + } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function(){return f.apply(null, args);}; + } + + var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + var isWordCharBasic = CodeMirror.isWordChar = function(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); + }; + function isWordChar(ch, helper) { + if (!helper) return isWordCharBasic(ch); + if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true; + return helper.test(ch); + } + + function isEmpty(obj) { + for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; + return true; + } + + // Extending unicode characters. A series of a non-extending char + + // any number of extending chars is treated as a single unit as far + // as editing and measuring is concerned. This is not fully correct, + // since some scripts/fonts/browsers also treat other configurations + // of code points as a group. + var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); } + + // DOM UTILITIES + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + if (className) e.className = className; + if (style) e.style.cssText = style; + if (typeof content == "string") e.appendChild(document.createTextNode(content)); + else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); + return e; + } + + var range; + if (document.createRange) range = function(node, start, end, endNode) { + var r = document.createRange(); + r.setEnd(endNode || node, end); + r.setStart(node, start); + return r; + }; + else range = function(node, start, end) { + var r = document.body.createTextRange(); + try { r.moveToElementText(node.parentNode); } + catch(e) { return r; } + r.collapse(true); + r.moveEnd("character", end); + r.moveStart("character", start); + return r; + }; + + function removeChildren(e) { + for (var count = e.childNodes.length; count > 0; --count) + e.removeChild(e.firstChild); + return e; + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e); + } + + var contains = CodeMirror.contains = function(parent, child) { + if (child.nodeType == 3) // Android browser always returns false when child is a textnode + child = child.parentNode; + if (parent.contains) + return parent.contains(child); + do { + if (child.nodeType == 11) child = child.host; + if (child == parent) return true; + } while (child = child.parentNode); + }; + + function activeElt() { + var activeElement = document.activeElement; + while (activeElement && activeElement.root && activeElement.root.activeElement) + activeElement = activeElement.root.activeElement; + return activeElement; + } + // Older versions of IE throws unspecified error when touching + // document.activeElement in some cases (during loading, in iframe) + if (ie && ie_version < 11) activeElt = function() { + try { return document.activeElement; } + catch(e) { return document.body; } + }; + + function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); } + var rmClass = CodeMirror.rmClass = function(node, cls) { + var current = node.className; + var match = classTest(cls).exec(current); + if (match) { + var after = current.slice(match.index + match[0].length); + node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); + } + }; + var addClass = CodeMirror.addClass = function(node, cls) { + var current = node.className; + if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls; + }; + function joinClasses(a, b) { + var as = a.split(" "); + for (var i = 0; i < as.length; i++) + if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i]; + return b; + } + + // WINDOW-WIDE EVENTS + + // These must be handled carefully, because naively registering a + // handler for each editor will cause the editors to never be + // garbage collected. + + function forEachCodeMirror(f) { + if (!document.body.getElementsByClassName) return; + var byClass = document.body.getElementsByClassName("CodeMirror"); + for (var i = 0; i < byClass.length; i++) { + var cm = byClass[i].CodeMirror; + if (cm) f(cm); + } + } + + var globalsRegistered = false; + function ensureGlobalHandlers() { + if (globalsRegistered) return; + registerGlobalHandlers(); + globalsRegistered = true; + } + function registerGlobalHandlers() { + // When the window resizes, we need to refresh active editors. + var resizeTimer; + on(window, "resize", function() { + if (resizeTimer == null) resizeTimer = setTimeout(function() { + resizeTimer = null; + forEachCodeMirror(onResize); + }, 100); + }); + // When the window loses focus, we want to show the editor as blurred + on(window, "blur", function() { + forEachCodeMirror(onBlur); + }); + } + + // FEATURE DETECTION + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie && ie_version < 9) return false; + var div = elt('div'); + return "draggable" in div || "dragDrop" in div; + }(); + + var zwspSupported; + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200b"); + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); + if (measure.firstChild.offsetHeight != 0) + zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); + } + var node = zwspSupported ? elt("span", "\u200b") : + elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); + node.setAttribute("cm-text", ""); + return node; + } + + // Feature-detect IE's crummy client rect reporting for bidi text + var badBidiRects; + function hasBadBidiRects(measure) { + if (badBidiRects != null) return badBidiRects; + var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); + var r0 = range(txt, 0, 1).getBoundingClientRect(); + var r1 = range(txt, 1, 2).getBoundingClientRect(); + removeChildren(measure); + if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780) + return badBidiRects = (r1.right - r0.right < 3); + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { + var pos = 0, result = [], l = string.length; + while (pos <= l) { + var nl = string.indexOf("\n", pos); + if (nl == -1) nl = string.length; + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + return result; + } : function(string){return string.split(/\r\n?|\n/);}; + + var hasSelection = window.getSelection ? function(te) { + try { return te.selectionStart != te.selectionEnd; } + catch(e) { return false; } + } : function(te) { + try {var range = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range || range.parentElement() != te) return false; + return range.compareEndPoints("StartToEnd", range) != 0; + }; + + var hasCopyEvent = (function() { + var e = elt("div"); + if ("oncopy" in e) return true; + e.setAttribute("oncopy", "return;"); + return typeof e.oncopy == "function"; + })(); + + var badZoomedRects = null; + function hasBadZoomedRects(measure) { + if (badZoomedRects != null) return badZoomedRects; + var node = removeChildrenAndAdd(measure, elt("span", "x")); + var normal = node.getBoundingClientRect(); + var fromRange = range(node, 0, 1).getBoundingClientRect(); + return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1; + } + + // KEY NAMES + + var keyNames = CodeMirror.keyNames = { + 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", + 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", + 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", + 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" + }; + (function() { + // Number keys + for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i); + // Alphabetic keys + for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); + // Function keys + for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; + })(); + + // BIDI HELPERS + + function iterateBidiSections(order, from, to, f) { + if (!order) return f(from, to, "ltr"); + var found = false; + for (var i = 0; i < order.length; ++i) { + var part = order[i]; + if (part.from < to && part.to > from || from == to && part.to == from) { + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr"); + found = true; + } + } + if (!found) f(from, to, "ltr"); + } + + function bidiLeft(part) { return part.level % 2 ? part.to : part.from; } + function bidiRight(part) { return part.level % 2 ? part.from : part.to; } + + function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; } + function lineRight(line) { + var order = getOrder(line); + if (!order) return line.text.length; + return bidiRight(lst(order)); + } + + function lineStart(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLine(line); + if (visual != line) lineN = lineNo(visual); + var order = getOrder(visual); + var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); + return Pos(lineN, ch); + } + function lineEnd(cm, lineN) { + var merged, line = getLine(cm.doc, lineN); + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line; + lineN = null; + } + var order = getOrder(line); + var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); + return Pos(lineN == null ? lineNo(line) : lineN, ch); + } + function lineStartSmart(cm, pos) { + var start = lineStart(cm, pos.line); + var line = getLine(cm.doc, start.line); + var order = getOrder(line); + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(0, line.text.search(/\S/)); + var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; + return Pos(start.line, inWS ? 0 : firstNonWS); + } + return start; + } + + function compareBidiLevel(order, a, b) { + var linedir = order[0].level; + if (a == linedir) return true; + if (b == linedir) return false; + return a < b; + } + var bidiOther; + function getBidiPartAt(order, pos) { + bidiOther = null; + for (var i = 0, found; i < order.length; ++i) { + var cur = order[i]; + if (cur.from < pos && cur.to > pos) return i; + if ((cur.from == pos || cur.to == pos)) { + if (found == null) { + found = i; + } else if (compareBidiLevel(order, cur.level, order[found].level)) { + if (cur.from != cur.to) bidiOther = found; + return i; + } else { + if (cur.from != cur.to) bidiOther = i; + return found; + } + } + } + return found; + } + + function moveInLine(line, pos, dir, byUnit) { + if (!byUnit) return pos + dir; + do pos += dir; + while (pos > 0 && isExtendingChar(line.text.charAt(pos))); + return pos; + } + + // This is needed in order to move 'visually' through bi-directional + // text -- i.e., pressing left should make the cursor go left, even + // when in RTL text. The tricky part is the 'jumps', where RTL and + // LTR text touch each other. This often requires the cursor offset + // to move more than one unit, in order to visually move one unit. + function moveVisually(line, start, dir, byUnit) { + var bidi = getOrder(line); + if (!bidi) return moveLogically(line, start, dir, byUnit); + var pos = getBidiPartAt(bidi, start), part = bidi[pos]; + var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit); + + for (;;) { + if (target > part.from && target < part.to) return target; + if (target == part.from || target == part.to) { + if (getBidiPartAt(bidi, target) == pos) return target; + part = bidi[pos += dir]; + return (dir > 0) == part.level % 2 ? part.to : part.from; + } else { + part = bidi[pos += dir]; + if (!part) return null; + if ((dir > 0) == part.level % 2) + target = moveInLine(line, part.to, -1, byUnit); + else + target = moveInLine(line, part.from, 1, byUnit); + } + } + } + + function moveLogically(line, start, dir, byUnit) { + var target = start + dir; + if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir; + return target < 0 || target > line.text.length ? null : target; + } + + // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + var bidiOrdering = (function() { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; + // Character types for codepoints 0x600 to 0x6ff + var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm"; + function charType(code) { + if (code <= 0xf7) return lowTypes.charAt(code); + else if (0x590 <= code && code <= 0x5f4) return "R"; + else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600); + else if (0x6ee <= code && code <= 0x8ac) return "r"; + else if (0x2000 <= code && code <= 0x200b) return "w"; + else if (code == 0x200c) return "b"; + else return "L"; + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; + // Browsers seem to always treat the boundaries of block elements as being L. + var outerType = "L"; + + function BidiSpan(level, from, to) { + this.level = level; + this.from = from; this.to = to; + } + + return function(str) { + if (!bidiRE.test(str)) return false; + var len = str.length, types = []; + for (var i = 0, type; i < len; ++i) + types.push(type = charType(str.charCodeAt(i))); + + // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + for (var i = 0, prev = outerType; i < len; ++i) { + var type = types[i]; + if (type == "m") types[i] = prev; + else prev = type; + } + + // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + for (var i = 0, cur = outerType; i < len; ++i) { + var type = types[i]; + if (type == "1" && cur == "r") types[i] = "n"; + else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; } + } + + // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + for (var i = 1, prev = types[0]; i < len - 1; ++i) { + var type = types[i]; + if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1"; + else if (type == "," && prev == types[i+1] && + (prev == "1" || prev == "n")) types[i] = prev; + prev = type; + } + + // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + for (var i = 0; i < len; ++i) { + var type = types[i]; + if (type == ",") types[i] = "N"; + else if (type == "%") { + for (var end = i + 1; end < len && types[end] == "%"; ++end) {} + var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; + for (var j = i; j < end; ++j) types[j] = replace; + i = end - 1; + } + } + + // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + for (var i = 0, cur = outerType; i < len; ++i) { + var type = types[i]; + if (cur == "L" && type == "1") types[i] = "L"; + else if (isStrong.test(type)) cur = type; + } + + // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + for (var i = 0; i < len; ++i) { + if (isNeutral.test(types[i])) { + for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} + var before = (i ? types[i-1] : outerType) == "L"; + var after = (end < len ? types[end] : outerType) == "L"; + var replace = before || after ? "L" : "R"; + for (var j = i; j < end; ++j) types[j] = replace; + i = end - 1; + } + } + + // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + var order = [], m; + for (var i = 0; i < len;) { + if (countsAsLeft.test(types[i])) { + var start = i; + for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} + order.push(new BidiSpan(0, start, i)); + } else { + var pos = i, at = order.length; + for (++i; i < len && types[i] != "L"; ++i) {} + for (var j = pos; j < i;) { + if (countsAsNum.test(types[j])) { + if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j)); + var nstart = j; + for (++j; j < i && countsAsNum.test(types[j]); ++j) {} + order.splice(at, 0, new BidiSpan(2, nstart, j)); + pos = j; + } else ++j; + } + if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i)); + } + } + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length; + order.unshift(new BidiSpan(0, 0, m[0].length)); + } + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length; + order.push(new BidiSpan(0, len - m[0].length, len)); + } + if (order[0].level == 2) + order.unshift(new BidiSpan(1, order[0].to, order[0].to)); + if (order[0].level != lst(order).level) + order.push(new BidiSpan(order[0].level, len, len)); + + return order; + }; + })(); + + // THE END + + CodeMirror.version = "5.17.0"; + + return CodeMirror; +}); + +},{}],2:[function(require,module,exports){ +var pSlice = Array.prototype.slice; +var objectKeys = require('./lib/keys.js'); +var isArguments = require('./lib/is_arguments.js'); + +var deepEqual = module.exports = function (actual, expected, opts) { + if (!opts) opts = {}; + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') { + return opts.strict ? actual === expected : actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected, opts); + } +} + +function isUndefinedOrNull(value) { + return value === null || value === undefined; +} + +function isBuffer (x) { + if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false; + if (typeof x.copy !== 'function' || typeof x.slice !== 'function') { + return false; + } + if (x.length > 0 && typeof x[0] !== 'number') return false; + return true; +} + +function objEquiv(a, b, opts) { + var i, key; + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return deepEqual(a, b, opts); + } + if (isBuffer(a)) { + if (!isBuffer(b)) { + return false; + } + if (a.length !== b.length) return false; + for (i = 0; i < a.length; i++) { + if (a[i] !== b[i]) return false; + } + return true; + } + try { + var ka = objectKeys(a), + kb = objectKeys(b); + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key], opts)) return false; + } + return typeof a === typeof b; +} + +},{"./lib/is_arguments.js":3,"./lib/keys.js":4}],3:[function(require,module,exports){ +var supportsArgumentsClass = (function(){ + return Object.prototype.toString.call(arguments) +})() == '[object Arguments]'; + +exports = module.exports = supportsArgumentsClass ? supported : unsupported; + +exports.supported = supported; +function supported(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +}; + +exports.unsupported = unsupported; +function unsupported(object){ + return object && + typeof object == 'object' && + typeof object.length == 'number' && + Object.prototype.hasOwnProperty.call(object, 'callee') && + !Object.prototype.propertyIsEnumerable.call(object, 'callee') || + false; +}; },{}],4:[function(require,module,exports){ -"use strict";var invariant=function(r,e,n,i,o,a,t,f){if(!r){var s;if(void 0===e)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var d=[n,i,o,a,t,f],l=0;s=new Error("Invariant Violation: "+e.replace(/%s/g,function(){return d[l++]}))}throw s.framesToPop=1,s}};module.exports=invariant; +exports = module.exports = typeof Object.keys === 'function' + ? Object.keys : shim; + +exports.shim = shim; +function shim (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} },{}],5:[function(require,module,exports){ -"use strict";function _classCallCheck(i,t){if(!(i instanceof t))throw new TypeError("Cannot call a class as a function")}exports.__esModule=!0;var invariant=require("fbjs/lib/invariant"),_prefix="ID_",Dispatcher=function(){function i(){_classCallCheck(this,i),this._callbacks={},this._isDispatching=!1,this._isHandled={},this._isPending={},this._lastID=1}return i.prototype.register=function(i){var t=_prefix+this._lastID++;return this._callbacks[t]=i,t},i.prototype.unregister=function(i){this._callbacks[i]?void 0:invariant(!1),delete this._callbacks[i]},i.prototype.waitFor=function(i){this._isDispatching?void 0:invariant(!1);for(var t=0;t=o&&e&&(r=!0,t()))}}var l=0,r=!1,n=!1,e=!1,p=void 0;s()}exports.__esModule=!0;var _slice=Array.prototype.slice;exports.loopAsync=loopAsync; +/** + * Use invariant() to assert state which your program assumes to be true. + * + * Provide sprintf-style format (only %s is supported) and arguments + * to provide information about what broke and what you were + * expecting. + * + * The invariant message will be stripped in production, but the invariant + * will remain to ensure logic does not differ in production. + */ +var invariant = function (condition, format, a, b, c, d, e, f) { + if (process.env.NODE_ENV !== 'production') { + if (format === undefined) { + throw new Error('invariant requires an error message argument'); + } + } + + if (!condition) { + var error; + if (format === undefined) { + error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); + } else { + var args = [a, b, c, d, e, f]; + var argIndex = 0; + error = new Error('Invariant Violation: ' + format.replace(/%s/g, function () { + return args[argIndex++]; + })); + } + + error.framesToPop = 1; // we don't care about invariant's own frame + throw error; + } +}; + +module.exports = invariant; +}).call(this,require('_process')) + +},{"_process":37}],6:[function(require,module,exports){ +(function (process){ +/** + * Copyright (c) 2014-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule Dispatcher + * + * @preventMunge + */ + +'use strict'; + +exports.__esModule = true; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + +var invariant = require('fbjs/lib/invariant'); + +var _prefix = 'ID_'; + +/** + * Dispatcher is used to broadcast payloads to registered callbacks. This is + * different from generic pub-sub systems in two ways: + * + * 1) Callbacks are not subscribed to particular events. Every payload is + * dispatched to every registered callback. + * 2) Callbacks can be deferred in whole or part until other callbacks have + * been executed. + * + * For example, consider this hypothetical flight destination form, which + * selects a default city when a country is selected: + * + * var flightDispatcher = new Dispatcher(); + * + * // Keeps track of which country is selected + * var CountryStore = {country: null}; + * + * // Keeps track of which city is selected + * var CityStore = {city: null}; + * + * // Keeps track of the base flight price of the selected city + * var FlightPriceStore = {price: null} + * + * When a user changes the selected city, we dispatch the payload: + * + * flightDispatcher.dispatch({ + * actionType: 'city-update', + * selectedCity: 'paris' + * }); + * + * This payload is digested by `CityStore`: + * + * flightDispatcher.register(function(payload) { + * if (payload.actionType === 'city-update') { + * CityStore.city = payload.selectedCity; + * } + * }); + * + * When the user selects a country, we dispatch the payload: + * + * flightDispatcher.dispatch({ + * actionType: 'country-update', + * selectedCountry: 'australia' + * }); + * + * This payload is digested by both stores: + * + * CountryStore.dispatchToken = flightDispatcher.register(function(payload) { + * if (payload.actionType === 'country-update') { + * CountryStore.country = payload.selectedCountry; + * } + * }); + * + * When the callback to update `CountryStore` is registered, we save a reference + * to the returned token. Using this token with `waitFor()`, we can guarantee + * that `CountryStore` is updated before the callback that updates `CityStore` + * needs to query its data. + * + * CityStore.dispatchToken = flightDispatcher.register(function(payload) { + * if (payload.actionType === 'country-update') { + * // `CountryStore.country` may not be updated. + * flightDispatcher.waitFor([CountryStore.dispatchToken]); + * // `CountryStore.country` is now guaranteed to be updated. + * + * // Select the default city for the new country + * CityStore.city = getDefaultCityForCountry(CountryStore.country); + * } + * }); + * + * The usage of `waitFor()` can be chained, for example: + * + * FlightPriceStore.dispatchToken = + * flightDispatcher.register(function(payload) { + * switch (payload.actionType) { + * case 'country-update': + * case 'city-update': + * flightDispatcher.waitFor([CityStore.dispatchToken]); + * FlightPriceStore.price = + * getFlightPriceStore(CountryStore.country, CityStore.city); + * break; + * } + * }); + * + * The `country-update` payload will be guaranteed to invoke the stores' + * registered callbacks in order: `CountryStore`, `CityStore`, then + * `FlightPriceStore`. + */ + +var Dispatcher = (function () { + function Dispatcher() { + _classCallCheck(this, Dispatcher); + + this._callbacks = {}; + this._isDispatching = false; + this._isHandled = {}; + this._isPending = {}; + this._lastID = 1; + } + + /** + * Registers a callback to be invoked with every dispatched payload. Returns + * a token that can be used with `waitFor()`. + */ + + Dispatcher.prototype.register = function register(callback) { + var id = _prefix + this._lastID++; + this._callbacks[id] = callback; + return id; + }; + + /** + * Removes a callback based on its token. + */ + + Dispatcher.prototype.unregister = function unregister(id) { + !this._callbacks[id] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatcher.unregister(...): `%s` does not map to a registered callback.', id) : invariant(false) : undefined; + delete this._callbacks[id]; + }; + + /** + * Waits for the callbacks specified to be invoked before continuing execution + * of the current callback. This method should only be used by a callback in + * response to a dispatched payload. + */ + + Dispatcher.prototype.waitFor = function waitFor(ids) { + !this._isDispatching ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatcher.waitFor(...): Must be invoked while dispatching.') : invariant(false) : undefined; + for (var ii = 0; ii < ids.length; ii++) { + var id = ids[ii]; + if (this._isPending[id]) { + !this._isHandled[id] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatcher.waitFor(...): Circular dependency detected while ' + 'waiting for `%s`.', id) : invariant(false) : undefined; + continue; + } + !this._callbacks[id] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatcher.waitFor(...): `%s` does not map to a registered callback.', id) : invariant(false) : undefined; + this._invokeCallback(id); + } + }; + + /** + * Dispatches a payload to all registered callbacks. + */ + + Dispatcher.prototype.dispatch = function dispatch(payload) { + !!this._isDispatching ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.') : invariant(false) : undefined; + this._startDispatching(payload); + try { + for (var id in this._callbacks) { + if (this._isPending[id]) { + continue; + } + this._invokeCallback(id); + } + } finally { + this._stopDispatching(); + } + }; + + /** + * Is this Dispatcher currently dispatching. + */ + + Dispatcher.prototype.isDispatching = function isDispatching() { + return this._isDispatching; + }; + + /** + * Call the callback stored with the given id. Also do some internal + * bookkeeping. + * + * @internal + */ + + Dispatcher.prototype._invokeCallback = function _invokeCallback(id) { + this._isPending[id] = true; + this._callbacks[id](this._pendingPayload); + this._isHandled[id] = true; + }; + + /** + * Set up bookkeeping needed when dispatching. + * + * @internal + */ + + Dispatcher.prototype._startDispatching = function _startDispatching(payload) { + for (var id in this._callbacks) { + this._isPending[id] = false; + this._isHandled[id] = false; + } + this._pendingPayload = payload; + this._isDispatching = true; + }; + + /** + * Clear bookkeeping used for dispatching. + * + * @internal + */ + + Dispatcher.prototype._stopDispatching = function _stopDispatching() { + delete this._pendingPayload; + this._isDispatching = false; + }; + + return Dispatcher; +})(); + +module.exports = Dispatcher; +}).call(this,require('_process')) + +},{"_process":37,"fbjs/lib/invariant":5}],7:[function(require,module,exports){ +/** + * Indicates that navigation was caused by a call to history.push. + */ +'use strict'; + +exports.__esModule = true; +var PUSH = 'PUSH'; + +exports.PUSH = PUSH; +/** + * Indicates that navigation was caused by a call to history.replace. + */ +var REPLACE = 'REPLACE'; + +exports.REPLACE = REPLACE; +/** + * Indicates that navigation was caused by some other action such + * as using a browser's back/forward buttons and/or manually manipulating + * the URL in a browser's location bar. This is the default. + * + * See https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate + * for more information. + */ +var POP = 'POP'; + +exports.POP = POP; +exports['default'] = { + PUSH: PUSH, + REPLACE: REPLACE, + POP: POP +}; },{}],8:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function createKey(e){return KeyPrefix+e}function saveState(e,r){try{null==r?window.sessionStorage.removeItem(createKey(e)):window.sessionStorage.setItem(createKey(e),JSON.stringify(r))}catch(e){if(e.name===SecurityError)return;if(QuotaExceededErrors.indexOf(e.name)>=0&&0===window.sessionStorage.length)return;throw e}}function readState(e){var r=void 0;try{r=window.sessionStorage.getItem(createKey(e))}catch(e){if(e.name===SecurityError)return null}if(r)try{return JSON.parse(r)}catch(e){}return null}exports.__esModule=!0,exports.saveState=saveState,exports.readState=readState;var _warning=require("warning"),_warning2=_interopRequireDefault(_warning),KeyPrefix="@@History/",QuotaExceededErrors=["QuotaExceededError","QUOTA_EXCEEDED_ERR"],SecurityError="SecurityError"; +"use strict"; -},{"warning":243}],9:[function(require,module,exports){ -"use strict";function addEventListener(t,e,o){t.addEventListener?t.addEventListener(e,o,!1):t.attachEvent("on"+e,o)}function removeEventListener(t,e,o){t.removeEventListener?t.removeEventListener(e,o,!1):t.detachEvent("on"+e,o)}function getHashPath(){return window.location.href.split("#")[1]||""}function replaceHashPath(t){window.location.replace(window.location.pathname+window.location.search+"#"+t)}function getWindowPath(){return window.location.pathname+window.location.search+window.location.hash}function go(t){t&&window.history.go(t)}function getUserConfirmation(t,e){e(window.confirm(t))}function supportsHistory(){var t=navigator.userAgent;return(t.indexOf("Android 2.")===-1&&t.indexOf("Android 4.0")===-1||t.indexOf("Mobile Safari")===-1||t.indexOf("Chrome")!==-1||t.indexOf("Windows Phone")!==-1)&&(window.history&&"pushState"in window.history)}function supportsGoWithoutReloadUsingHash(){var t=navigator.userAgent;return t.indexOf("Firefox")===-1}exports.__esModule=!0,exports.addEventListener=addEventListener,exports.removeEventListener=removeEventListener,exports.getHashPath=getHashPath,exports.replaceHashPath=replaceHashPath,exports.getWindowPath=getWindowPath,exports.go=go,exports.getUserConfirmation=getUserConfirmation,exports.supportsHistory=supportsHistory,exports.supportsGoWithoutReloadUsingHash=supportsGoWithoutReloadUsingHash; +exports.__esModule = true; +var _slice = Array.prototype.slice; +exports.loopAsync = loopAsync; -},{}],10:[function(require,module,exports){ -"use strict";exports.__esModule=!0;var canUseDOM=!("undefined"==typeof window||!window.document||!window.document.createElement);exports.canUseDOM=canUseDOM; +function loopAsync(turns, work, callback) { + var currentTurn = 0, + isDone = false; + var sync = false, + hasNext = false, + doneArgs = undefined; + function done() { + isDone = true; + if (sync) { + // Iterate instead of recursing if possible. + doneArgs = [].concat(_slice.call(arguments)); + return; + } + + callback.apply(this, arguments); + } + + function next() { + if (isDone) { + return; + } + + hasNext = true; + if (sync) { + // Iterate instead of recursing if possible. + return; + } + + sync = true; + + while (!isDone && currentTurn < turns && hasNext) { + hasNext = false; + work.call(this, currentTurn++, next, done); + } + + sync = false; + + if (isDone) { + // This means the loop finished synchronously. + callback.apply(this, doneArgs); + return; + } + + if (currentTurn >= turns && hasNext) { + isDone = true; + callback(); + } + } + + next(); +} +},{}],9:[function(require,module,exports){ +(function (process){ +/*eslint-disable no-empty */ +'use strict'; + +exports.__esModule = true; +exports.saveState = saveState; +exports.readState = readState; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _warning = require('warning'); + +var _warning2 = _interopRequireDefault(_warning); + +var KeyPrefix = '@@History/'; +var QuotaExceededErrors = ['QuotaExceededError', 'QUOTA_EXCEEDED_ERR']; + +var SecurityError = 'SecurityError'; + +function createKey(key) { + return KeyPrefix + key; +} + +function saveState(key, state) { + try { + if (state == null) { + window.sessionStorage.removeItem(createKey(key)); + } else { + window.sessionStorage.setItem(createKey(key), JSON.stringify(state)); + } + } catch (error) { + if (error.name === SecurityError) { + // Blocking cookies in Chrome/Firefox/Safari throws SecurityError on any + // attempt to access window.sessionStorage. + process.env.NODE_ENV !== 'production' ? _warning2['default'](false, '[history] Unable to save state; sessionStorage is not available due to security settings') : undefined; + + return; + } + + if (QuotaExceededErrors.indexOf(error.name) >= 0 && window.sessionStorage.length === 0) { + // Safari "private mode" throws QuotaExceededError. + process.env.NODE_ENV !== 'production' ? _warning2['default'](false, '[history] Unable to save state; sessionStorage is not available in Safari private mode') : undefined; + + return; + } + + throw error; + } +} + +function readState(key) { + var json = undefined; + try { + json = window.sessionStorage.getItem(createKey(key)); + } catch (error) { + if (error.name === SecurityError) { + // Blocking cookies in Chrome/Firefox/Safari throws SecurityError on any + // attempt to access window.sessionStorage. + process.env.NODE_ENV !== 'production' ? _warning2['default'](false, '[history] Unable to read state; sessionStorage is not available due to security settings') : undefined; + + return null; + } + } + + if (json) { + try { + return JSON.parse(json); + } catch (error) { + // Ignore invalid JSON. + } + } + + return null; +} +}).call(this,require('_process')) + +},{"_process":37,"warning":23}],10:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; +exports.addEventListener = addEventListener; +exports.removeEventListener = removeEventListener; +exports.getHashPath = getHashPath; +exports.replaceHashPath = replaceHashPath; +exports.getWindowPath = getWindowPath; +exports.go = go; +exports.getUserConfirmation = getUserConfirmation; +exports.supportsHistory = supportsHistory; +exports.supportsGoWithoutReloadUsingHash = supportsGoWithoutReloadUsingHash; + +function addEventListener(node, event, listener) { + if (node.addEventListener) { + node.addEventListener(event, listener, false); + } else { + node.attachEvent('on' + event, listener); + } +} + +function removeEventListener(node, event, listener) { + if (node.removeEventListener) { + node.removeEventListener(event, listener, false); + } else { + node.detachEvent('on' + event, listener); + } +} + +function getHashPath() { + // We can't use window.location.hash here because it's not + // consistent across browsers - Firefox will pre-decode it! + return window.location.href.split('#')[1] || ''; +} + +function replaceHashPath(path) { + window.location.replace(window.location.pathname + window.location.search + '#' + path); +} + +function getWindowPath() { + return window.location.pathname + window.location.search + window.location.hash; +} + +function go(n) { + if (n) window.history.go(n); +} + +function getUserConfirmation(message, callback) { + callback(window.confirm(message)); +} + +/** + * Returns true if the HTML5 history API is supported. Taken from Modernizr. + * + * https://github.com/Modernizr/Modernizr/blob/master/LICENSE + * https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js + * changed to avoid false negatives for Windows Phones: https://github.com/rackt/react-router/issues/586 + */ + +function supportsHistory() { + var ua = navigator.userAgent; + if ((ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) && ua.indexOf('Mobile Safari') !== -1 && ua.indexOf('Chrome') === -1 && ua.indexOf('Windows Phone') === -1) { + return false; + } + return window.history && 'pushState' in window.history; +} + +/** + * Returns false if using go(n) with hash history causes a full page reload. + */ + +function supportsGoWithoutReloadUsingHash() { + var ua = navigator.userAgent; + return ua.indexOf('Firefox') === -1; +} },{}],11:[function(require,module,exports){ -"use strict";function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}function extractPath(t){var r=t.match(/^https?:\/\/[^\/]*/);return null==r?t:t.substring(r[0].length)}function parsePath(t){var r=extractPath(t),e="",a="",n=r.indexOf("#");n!==-1&&(a=r.substring(n),r=r.substring(0,n));var s=r.indexOf("?");return s!==-1&&(e=r.substring(s),r=r.substring(0,s)),""===r&&(r="/"),{pathname:r,search:e,hash:a}}exports.__esModule=!0,exports.extractPath=extractPath,exports.parsePath=parsePath;var _warning=require("warning"),_warning2=_interopRequireDefault(_warning); +'use strict'; -},{"warning":243}],12:[function(require,module,exports){ -"use strict";function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}function createBrowserHistory(){function t(t){try{t=t||window.history.state||{}}catch(e){t={}}var e=_DOMUtils.getWindowPath(),r=t,n=r.key,i=void 0;n?i=_DOMStateStorage.readState(n):(i=null,n=_.createKey(),c&&window.history.replaceState(_extends({},t,{key:n}),null));var o=_PathUtils.parsePath(e);return _.createLocation(_extends({},o,{state:i}),void 0,n)}function e(e){function r(e){void 0!==e.state&&n(t(e.state))}var n=e.transitionTo;return _DOMUtils.addEventListener(window,"popstate",r),function(){_DOMUtils.removeEventListener(window,"popstate",r)}}function r(t){var e=t.basename,r=t.pathname,n=t.search,i=t.hash,o=t.state,a=t.action,s=t.key;if(a!==_Actions.POP){_DOMStateStorage.saveState(s,o);var u=(e||"")+r+n+i,c={key:s};if(a===_Actions.PUSH){if(l)return window.location.href=u,!1;window.history.pushState(c,null,u)}else{if(l)return window.location.replace(u),!1;window.history.replaceState(c,null,u)}}}function n(t){1===++f&&(v=e(_));var r=_.listenBefore(t);return function(){r(),0===--f&&v()}}function i(t){1===++f&&(v=e(_));var r=_.listen(t);return function(){r(),0===--f&&v()}}function o(t){1===++f&&(v=e(_)),_.registerTransitionHook(t)}function a(t){_.unregisterTransitionHook(t),0===--f&&v()}var s=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];_ExecutionEnvironment.canUseDOM?void 0:_invariant2.default(!1);var u=s.forceRefresh,c=_DOMUtils.supportsHistory(),l=!c||u,_=_createDOMHistory2.default(_extends({},s,{getCurrentLocation:t,finishTransition:r,saveState:_DOMStateStorage.saveState})),f=0,v=void 0;return _extends({},_,{listenBefore:n,listen:i,registerTransitionHook:o,unregisterTransitionHook:a})}exports.__esModule=!0;var _extends=Object.assign||function(t){for(var e=1;e=0&&t=0&&f1?t-1:0),i=1;i1?n-1:0),u=1;u= 0 && current < entries.length) ? process.env.NODE_ENV !== 'production' ? _invariant2['default'](false, 'Current index must be >= 0 and < %s, was %s', entries.length, current) : _invariant2['default'](false) : undefined; + } + + var storage = createStateStorage(entries); + + function saveState(key, state) { + storage[key] = state; + } + + function readState(key) { + return storage[key]; + } + + function getCurrentLocation() { + var entry = entries[current]; + var basename = entry.basename; + var pathname = entry.pathname; + var search = entry.search; + + var path = (basename || '') + pathname + (search || ''); + + var key = undefined, + state = undefined; + if (entry.key) { + key = entry.key; + state = readState(key); + } else { + key = history.createKey(); + state = null; + entry.key = key; + } + + var location = _PathUtils.parsePath(path); + + return history.createLocation(_extends({}, location, { state: state }), undefined, key); + } + + function canGo(n) { + var index = current + n; + return index >= 0 && index < entries.length; + } + + function go(n) { + if (n) { + if (!canGo(n)) { + process.env.NODE_ENV !== 'production' ? _warning2['default'](false, 'Cannot go(%s) there is not enough history', n) : undefined; + return; + } + + current += n; + + var currentLocation = getCurrentLocation(); + + // change action to POP + history.transitionTo(_extends({}, currentLocation, { action: _Actions.POP })); + } + } + + function finishTransition(location) { + switch (location.action) { + case _Actions.PUSH: + current += 1; + + // if we are not on the top of stack + // remove rest and push new + if (current < entries.length) entries.splice(current); + + entries.push(location); + saveState(location.key, location.state); + break; + case _Actions.REPLACE: + entries[current] = location; + saveState(location.key, location.state); + break; + } + } + + return history; +} + +exports['default'] = createMemoryHistory; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./Actions":7,"./PathUtils":12,"./createHistory":16,"_process":37,"invariant":25,"warning":23}],19:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _warning = require('warning'); + +var _warning2 = _interopRequireDefault(_warning); + +function deprecate(fn, message) { + return function () { + process.env.NODE_ENV !== 'production' ? _warning2['default'](false, '[history] ' + message) : undefined; + return fn.apply(this, arguments); + }; +} + +exports['default'] = deprecate; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"_process":37,"warning":23}],20:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _warning = require('warning'); + +var _warning2 = _interopRequireDefault(_warning); + +function runTransitionHook(hook, location, callback) { + var result = hook(location, callback); + + if (hook.length < 2) { + // Assume the hook runs synchronously and automatically + // call the callback with the return value. + callback(result); + } else { + process.env.NODE_ENV !== 'production' ? _warning2['default'](result === undefined, 'You should not "return" in a transition hook with a callback argument; call the callback instead') : undefined; + } +} + +exports['default'] = runTransitionHook; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"_process":37,"warning":23}],21:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _warning = require('warning'); + +var _warning2 = _interopRequireDefault(_warning); + +var _ExecutionEnvironment = require('./ExecutionEnvironment'); + +var _PathUtils = require('./PathUtils'); + +var _runTransitionHook = require('./runTransitionHook'); + +var _runTransitionHook2 = _interopRequireDefault(_runTransitionHook); + +var _deprecate = require('./deprecate'); + +var _deprecate2 = _interopRequireDefault(_deprecate); + +function useBasename(createHistory) { + return function () { + var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + + var history = createHistory(options); + + var basename = options.basename; + + var checkedBaseHref = false; + + function checkBaseHref() { + if (checkedBaseHref) { + return; + } + + // Automatically use the value of in HTML + // documents as basename if it's not explicitly given. + if (basename == null && _ExecutionEnvironment.canUseDOM) { + var base = document.getElementsByTagName('base')[0]; + var baseHref = base && base.getAttribute('href'); + + if (baseHref != null) { + basename = baseHref; + + process.env.NODE_ENV !== 'production' ? _warning2['default'](false, 'Automatically setting basename using is deprecated and will ' + 'be removed in the next major release. The semantics of are ' + 'subtly different from basename. Please pass the basename explicitly in ' + 'the options to createHistory') : undefined; + } + } + + checkedBaseHref = true; + } + + function addBasename(location) { + checkBaseHref(); + + if (basename && location.basename == null) { + if (location.pathname.indexOf(basename) === 0) { + location.pathname = location.pathname.substring(basename.length); + location.basename = basename; + + if (location.pathname === '') location.pathname = '/'; + } else { + location.basename = ''; + } + } + + return location; + } + + function prependBasename(location) { + checkBaseHref(); + + if (!basename) return location; + + if (typeof location === 'string') location = _PathUtils.parsePath(location); + + var pname = location.pathname; + var normalizedBasename = basename.slice(-1) === '/' ? basename : basename + '/'; + var normalizedPathname = pname.charAt(0) === '/' ? pname.slice(1) : pname; + var pathname = normalizedBasename + normalizedPathname; + + return _extends({}, location, { + pathname: pathname + }); + } + + // Override all read methods with basename-aware versions. + function listenBefore(hook) { + return history.listenBefore(function (location, callback) { + _runTransitionHook2['default'](hook, addBasename(location), callback); + }); + } + + function listen(listener) { + return history.listen(function (location) { + listener(addBasename(location)); + }); + } + + // Override all write methods with basename-aware versions. + function push(location) { + history.push(prependBasename(location)); + } + + function replace(location) { + history.replace(prependBasename(location)); + } + + function createPath(location) { + return history.createPath(prependBasename(location)); + } + + function createHref(location) { + return history.createHref(prependBasename(location)); + } + + function createLocation(location) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + return addBasename(history.createLocation.apply(history, [prependBasename(location)].concat(args))); + } + + // deprecated + function pushState(state, path) { + if (typeof path === 'string') path = _PathUtils.parsePath(path); + + push(_extends({ state: state }, path)); + } + + // deprecated + function replaceState(state, path) { + if (typeof path === 'string') path = _PathUtils.parsePath(path); + + replace(_extends({ state: state }, path)); + } + + return _extends({}, history, { + listenBefore: listenBefore, + listen: listen, + push: push, + replace: replace, + createPath: createPath, + createHref: createHref, + createLocation: createLocation, + + pushState: _deprecate2['default'](pushState, 'pushState is deprecated; use push instead'), + replaceState: _deprecate2['default'](replaceState, 'replaceState is deprecated; use replace instead') + }); + }; +} + +exports['default'] = useBasename; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./ExecutionEnvironment":11,"./PathUtils":12,"./deprecate":19,"./runTransitionHook":20,"_process":37,"warning":23}],22:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +var _warning = require('warning'); + +var _warning2 = _interopRequireDefault(_warning); + +var _queryString = require('query-string'); + +var _runTransitionHook = require('./runTransitionHook'); + +var _runTransitionHook2 = _interopRequireDefault(_runTransitionHook); + +var _PathUtils = require('./PathUtils'); + +var _deprecate = require('./deprecate'); + +var _deprecate2 = _interopRequireDefault(_deprecate); + +var SEARCH_BASE_KEY = '$searchBase'; + +function defaultStringifyQuery(query) { + return _queryString.stringify(query).replace(/%20/g, '+'); +} + +var defaultParseQueryString = _queryString.parse; + +function isNestedObject(object) { + for (var p in object) { + if (Object.prototype.hasOwnProperty.call(object, p) && typeof object[p] === 'object' && !Array.isArray(object[p]) && object[p] !== null) return true; + }return false; +} + +/** + * Returns a new createHistory function that may be used to create + * history objects that know how to handle URL queries. + */ +function useQueries(createHistory) { + return function () { + var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + + var history = createHistory(options); + + var stringifyQuery = options.stringifyQuery; + var parseQueryString = options.parseQueryString; + + if (typeof stringifyQuery !== 'function') stringifyQuery = defaultStringifyQuery; + + if (typeof parseQueryString !== 'function') parseQueryString = defaultParseQueryString; + + function addQuery(location) { + if (location.query == null) { + var search = location.search; + + location.query = parseQueryString(search.substring(1)); + location[SEARCH_BASE_KEY] = { search: search, searchBase: '' }; + } + + // TODO: Instead of all the book-keeping here, this should just strip the + // stringified query from the search. + + return location; + } + + function appendQuery(location, query) { + var _extends2; + + var searchBaseSpec = location[SEARCH_BASE_KEY]; + var queryString = query ? stringifyQuery(query) : ''; + if (!searchBaseSpec && !queryString) { + return location; + } + + process.env.NODE_ENV !== 'production' ? _warning2['default'](stringifyQuery !== defaultStringifyQuery || !isNestedObject(query), 'useQueries does not stringify nested query objects by default; ' + 'use a custom stringifyQuery function') : undefined; + + if (typeof location === 'string') location = _PathUtils.parsePath(location); + + var searchBase = undefined; + if (searchBaseSpec && location.search === searchBaseSpec.search) { + searchBase = searchBaseSpec.searchBase; + } else { + searchBase = location.search || ''; + } + + var search = searchBase; + if (queryString) { + search += (search ? '&' : '?') + queryString; + } + + return _extends({}, location, (_extends2 = { + search: search + }, _extends2[SEARCH_BASE_KEY] = { search: search, searchBase: searchBase }, _extends2)); + } + + // Override all read methods with query-aware versions. + function listenBefore(hook) { + return history.listenBefore(function (location, callback) { + _runTransitionHook2['default'](hook, addQuery(location), callback); + }); + } + + function listen(listener) { + return history.listen(function (location) { + listener(addQuery(location)); + }); + } + + // Override all write methods with query-aware versions. + function push(location) { + history.push(appendQuery(location, location.query)); + } + + function replace(location) { + history.replace(appendQuery(location, location.query)); + } + + function createPath(location, query) { + process.env.NODE_ENV !== 'production' ? _warning2['default'](!query, 'the query argument to createPath is deprecated; use a location descriptor instead') : undefined; + + return history.createPath(appendQuery(location, query || location.query)); + } + + function createHref(location, query) { + process.env.NODE_ENV !== 'production' ? _warning2['default'](!query, 'the query argument to createHref is deprecated; use a location descriptor instead') : undefined; + + return history.createHref(appendQuery(location, query || location.query)); + } + + function createLocation(location) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var fullLocation = history.createLocation.apply(history, [appendQuery(location, location.query)].concat(args)); + if (location.query) { + fullLocation.query = location.query; + } + return addQuery(fullLocation); + } + + // deprecated + function pushState(state, path, query) { + if (typeof path === 'string') path = _PathUtils.parsePath(path); + + push(_extends({ state: state }, path, { query: query })); + } + + // deprecated + function replaceState(state, path, query) { + if (typeof path === 'string') path = _PathUtils.parsePath(path); + + replace(_extends({ state: state }, path, { query: query })); + } + + return _extends({}, history, { + listenBefore: listenBefore, + listen: listen, + push: push, + replace: replace, + createPath: createPath, + createHref: createHref, + createLocation: createLocation, + + pushState: _deprecate2['default'](pushState, 'pushState is deprecated; use push instead'), + replaceState: _deprecate2['default'](replaceState, 'replaceState is deprecated; use replace instead') + }); + }; +} + +exports['default'] = useQueries; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./PathUtils":12,"./deprecate":19,"./runTransitionHook":20,"_process":37,"query-string":38,"warning":23}],23:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2014-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +'use strict'; + +/** + * Similar to invariant but only logs a warning if the condition is not met. + * This can be used to log issues in development environments in critical + * paths. Removing the logging code for production environments will keep the + * same logic and follow the same code paths. + */ + +var warning = function() {}; + +if (process.env.NODE_ENV !== 'production') { + warning = function(condition, format, args) { + var len = arguments.length; + args = new Array(len > 2 ? len - 2 : 0); + for (var key = 2; key < len; key++) { + args[key - 2] = arguments[key]; + } + if (format === undefined) { + throw new Error( + '`warning(condition, format, ...args)` requires a warning ' + + 'message argument' + ); + } + + if (format.length < 10 || (/^[s\W]*$/).test(format)) { + throw new Error( + 'The warning format should be able to uniquely identify this ' + + 'warning. Please, use a more descriptive format than: ' + format + ); + } + + if (!condition) { + var argIndex = 0; + var message = 'Warning: ' + + format.replace(/%s/g, function() { + return args[argIndex++]; + }); + if (typeof console !== 'undefined') { + console.error(message); + } + try { + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + } catch(x) {} + } + }; +} + +module.exports = warning; + +}).call(this,require('_process')) + +},{"_process":37}],24:[function(require,module,exports){ +/** + * Copyright 2015, Yahoo! Inc. + * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. + */ +'use strict'; + +var REACT_STATICS = { + childContextTypes: true, + contextTypes: true, + defaultProps: true, + displayName: true, + getDefaultProps: true, + mixins: true, + propTypes: true, + type: true +}; + +var KNOWN_STATICS = { + name: true, + length: true, + prototype: true, + caller: true, + arguments: true, + arity: true +}; + +var isGetOwnPropertySymbolsAvailable = typeof Object.getOwnPropertySymbols === 'function'; + +module.exports = function hoistNonReactStatics(targetComponent, sourceComponent, customStatics) { + if (typeof sourceComponent !== 'string') { // don't hoist over string (html) components + var keys = Object.getOwnPropertyNames(sourceComponent); + + /* istanbul ignore else */ + if (isGetOwnPropertySymbolsAvailable) { + keys = keys.concat(Object.getOwnPropertySymbols(sourceComponent)); + } + + for (var i = 0; i < keys.length; ++i) { + if (!REACT_STATICS[keys[i]] && !KNOWN_STATICS[keys[i]] && (!customStatics || !customStatics[keys[i]])) { + try { + targetComponent[keys[i]] = sourceComponent[keys[i]]; + } catch (error) { + + } + } + } + } + + return targetComponent; +}; },{}],25:[function(require,module,exports){ -function baseProperty(t){return function(e){return null==e?void 0:e[t]}}function isArguments(t){return isArrayLikeObject(t)&&hasOwnProperty.call(t,"callee")&&(!propertyIsEnumerable.call(t,"callee")||objectToString.call(t)==argsTag)}function isArrayLike(t){return null!=t&&isLength(getLength(t))&&!isFunction(t)}function isArrayLikeObject(t){return isObjectLike(t)&&isArrayLike(t)}function isFunction(t){var e=isObject(t)?objectToString.call(t):"";return e==funcTag||e==genTag}function isLength(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=MAX_SAFE_INTEGER}function isObject(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function isObjectLike(t){return!!t&&"object"==typeof t}var MAX_SAFE_INTEGER=9007199254740991,argsTag="[object Arguments]",funcTag="[object Function]",genTag="[object GeneratorFunction]",objectProto=Object.prototype,hasOwnProperty=objectProto.hasOwnProperty,objectToString=objectProto.toString,propertyIsEnumerable=objectProto.propertyIsEnumerable,getLength=baseProperty("length");module.exports=isArguments; +(function (process){ +/** + * Copyright 2013-2015, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ -},{}],26:[function(require,module,exports){ -function isObjectLike(t){return!!t&&"object"==typeof t}function getNative(t,r){var e=null==t?void 0:t[r];return isNative(e)?e:void 0}function isLength(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=MAX_SAFE_INTEGER}function isFunction(t){return isObject(t)&&objToString.call(t)==funcTag}function isObject(t){var r=typeof t;return!!t&&("object"==r||"function"==r)}function isNative(t){return null!=t&&(isFunction(t)?reIsNative.test(fnToString.call(t)):isObjectLike(t)&&reIsHostCtor.test(t))}var arrayTag="[object Array]",funcTag="[object Function]",reIsHostCtor=/^\[object .+?Constructor\]$/,objectProto=Object.prototype,fnToString=Function.prototype.toString,hasOwnProperty=objectProto.hasOwnProperty,objToString=objectProto.toString,reIsNative=RegExp("^"+fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),nativeIsArray=getNative(Array,"isArray"),MAX_SAFE_INTEGER=9007199254740991,isArray=nativeIsArray||function(t){return isObjectLike(t)&&isLength(t.length)&&objToString.call(t)==arrayTag};module.exports=isArray; +'use strict'; + +/** + * Use invariant() to assert state which your program assumes to be true. + * + * Provide sprintf-style format (only %s is supported) and arguments + * to provide information about what broke and what you were + * expecting. + * + * The invariant message will be stripped in production, but the invariant + * will remain to ensure logic does not differ in production. + */ + +var invariant = function(condition, format, a, b, c, d, e, f) { + if (process.env.NODE_ENV !== 'production') { + if (format === undefined) { + throw new Error('invariant requires an error message argument'); + } + } + + if (!condition) { + var error; + if (format === undefined) { + error = new Error( + 'Minified exception occurred; use the non-minified dev environment ' + + 'for the full error message and additional helpful warnings.' + ); + } else { + var args = [a, b, c, d, e, f]; + var argIndex = 0; + error = new Error( + format.replace(/%s/g, function() { return args[argIndex++]; }) + ); + error.name = 'Invariant Violation'; + } + + error.framesToPop = 1; // we don't care about invariant's own frame + throw error; + } +}; + +module.exports = invariant; + +}).call(this,require('_process')) + +},{"_process":37}],26:[function(require,module,exports){ +/** + * lodash 3.9.1 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** `Object#toString` result references. */ +var funcTag = '[object Function]'; + +/** Used to detect host constructors (Safari > 5). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** + * Checks if `value` is object-like. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var fnToString = Function.prototype.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in older versions of Chrome and Safari which return 'function' for regexes + // and Safari 8 equivalents which return 'object' for typed array constructors. + return isObject(value) && objToString.call(value) == funcTag; +} + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ +function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); +} + +module.exports = getNative; },{}],27:[function(require,module,exports){ -function getPrototype(t){return nativeGetPrototype(Object(t))}var nativeGetPrototype=Object.getPrototypeOf;module.exports=getPrototype; +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as the `TypeError` message for "Functions" methods. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** Used as references for various `Number` constants. */ +var NAN = 0 / 0; + +/** `Object#toString` result references. */ +var funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + symbolTag = '[object Symbol]'; + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; + +/** Used to detect bad signed hexadecimal string values. */ +var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + +/** Used to detect binary string values. */ +var reIsBinary = /^0b[01]+$/i; + +/** Used to detect octal string values. */ +var reIsOctal = /^0o[0-7]+$/i; + +/** Built-in method references without a dependency on `root`. */ +var freeParseInt = parseInt; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ +function now() { + return Date.now(); +} + +/** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide an options object to indicate whether `func` should be invoked on + * the leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent calls + * to the debounced function return the result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked + * on the trailing edge of the timeout only if the debounced function is + * invoked more than once during the `wait` timeout. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ +function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + result = wait - timeSinceLastCall; + + return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8 which returns 'object' for typed array and weak map constructors, + // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +/** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ +function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = isFunction(value.valueOf) ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); +} + +module.exports = debounce; },{}],28:[function(require,module,exports){ -function isHostObject(t){var o=!1;if(null!=t&&"function"!=typeof t.toString)try{o=!!(t+"")}catch(t){}return o}module.exports=isHostObject; +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]'; + +/** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ +function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; +} + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Gets the "length" property value of `object`. + * + * **Note:** This function is used to avoid a + * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects + * Safari on at least iOS 8.1-8.3 ARM64. + * + * @private + * @param {Object} object The object to query. + * @returns {*} Returns the "length" value. + */ +var getLength = baseProperty('length'); + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. + return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && + (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); +} + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(getLength(value)) && !isFunction(value); +} + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8 which returns 'object' for typed array and weak map constructors, + // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, + * else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +module.exports = isArguments; },{}],29:[function(require,module,exports){ -function isObjectLike(e){return!!e&&"object"==typeof e}module.exports=isObjectLike; +/** + * lodash 3.0.4 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ + +/** `Object#toString` result references. */ +var arrayTag = '[object Array]', + funcTag = '[object Function]'; + +/** Used to detect host constructors (Safari > 5). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** + * Checks if `value` is object-like. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var fnToString = Function.prototype.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeIsArray = getNative(Array, 'isArray'); + +/** + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) + * of an array-like value. + */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + */ +function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(function() { return arguments; }()); + * // => false + */ +var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; +}; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in older versions of Chrome and Safari which return 'function' for regexes + // and Safari 8 equivalents which return 'object' for typed array constructors. + return isObject(value) && objToString.call(value) == funcTag; +} + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ +function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); +} + +module.exports = isArray; },{}],30:[function(require,module,exports){ -function isPlainObject(t){if(!isObjectLike(t)||objectToString.call(t)!=objectTag||isHostObject(t))return!1;var o=getPrototype(t);if(null===o)return!0;var e=hasOwnProperty.call(o,"constructor")&&o.constructor;return"function"==typeof e&&e instanceof e&&funcToString.call(e)==objectCtorString}var getPrototype=require("./_getPrototype"),isHostObject=require("./_isHostObject"),isObjectLike=require("./isObjectLike"),objectTag="[object Object]",objectProto=Object.prototype,funcToString=Function.prototype.toString,hasOwnProperty=objectProto.hasOwnProperty,objectCtorString=funcToString.call(Object),objectToString=objectProto.toString;module.exports=isPlainObject; +/** + * lodash 3.1.2 (Custom Build) + * Build: `lodash modern modularize exports="npm" -o ./` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.3 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license + */ +var getNative = require('lodash._getnative'), + isArguments = require('lodash.isarguments'), + isArray = require('lodash.isarray'); -},{"./_getPrototype":27,"./_isHostObject":28,"./isObjectLike":29}],31:[function(require,module,exports){ -"use strict";function toObject(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}function shouldUseNative(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var r={},t=0;t<10;t++)r["_"+String.fromCharCode(t)]=t;var n=Object.getOwnPropertyNames(r).map(function(e){return r[e]});if("0123456789"!==n.join(""))return!1;var o={};return"abcdefghijklmnopqrst".split("").forEach(function(e){o[e]=e}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},o)).join("")}catch(e){return!1}}var hasOwnProperty=Object.prototype.hasOwnProperty,propIsEnumerable=Object.prototype.propertyIsEnumerable;module.exports=shouldUseNative()?Object.assign:function(e,r){for(var t,n,o=toObject(e),a=1;a does not support changing `store` on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions."))}exports.__esModule=!0,exports.default=void 0;var _react=require("react"),_storeShape=require("../utils/storeShape"),_storeShape2=_interopRequireDefault(_storeShape),_warning=require("../utils/warning"),_warning2=_interopRequireDefault(_warning),didWarnAboutReceivingStore=!1,Provider=function(e){function t(r,o){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,e.call(this,r,o));return n.store=r.store,n}return _inherits(t,e),t.prototype.getChildContext=function(){return{store:this.store}},t.prototype.render=function(){var e=this.props.children;return _react.Children.only(e)},t}(_react.Component);exports.default=Provider,Provider.propTypes={store:_storeShape2.default.isRequired,children:_react.PropTypes.element.isRequired},Provider.childContextTypes={store:_storeShape2.default.isRequired}; +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; -},{"../utils/storeShape":36,"../utils/warning":37,"react":"react"}],34:[function(require,module,exports){ -"use strict";function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}function _classCallCheck(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function _inherits(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function getDisplayName(t){return t.displayName||t.name||"Component"}function tryCatch(t,e){try{return t.apply(e)}catch(t){return errorObject.value=t,errorObject}}function connect(t,e,r){var o=arguments.length<=3||void 0===arguments[3]?{}:arguments[3],s=Boolean(t),a=t||defaultMapStateToProps,n=void 0;n="function"==typeof e?e:e?(0,_wrapActionCreators2.default)(e):defaultMapDispatchToProps;var i=r||defaultMergeProps,p=o.pure,u=void 0===p||p,h=o.withRef,c=void 0!==h&&h,l=u&&i!==defaultMergeProps,d=nextVersion++;return function(t){function e(t,e,r){var o=i(t,e,r);return o}var r="Connect("+getDisplayName(t)+")",o=function(o){function i(t,e){_classCallCheck(this,i);var s=_possibleConstructorReturn(this,o.call(this,t,e));s.version=d,s.store=t.store||e.store,(0,_invariant2.default)(s.store,'Could not find "store" in either the context or '+('props of "'+r+'". ')+"Either wrap the root component in a , "+('or explicitly pass "store" as a prop to "'+r+'".'));var a=s.store.getState();return s.state={storeState:a},s.clearCache(),s}return _inherits(i,o),i.prototype.shouldComponentUpdate=function(){return!u||this.haveOwnPropsChanged||this.hasStoreStateChanged},i.prototype.computeStateProps=function(t,e){if(!this.finalMapStateToProps)return this.configureFinalMapState(t,e);var r=t.getState(),o=this.doStatePropsDependOnOwnProps?this.finalMapStateToProps(r,e):this.finalMapStateToProps(r);return o},i.prototype.configureFinalMapState=function(t,e){var r=a(t.getState(),e),o="function"==typeof r;return this.finalMapStateToProps=o?r:a,this.doStatePropsDependOnOwnProps=1!==this.finalMapStateToProps.length,o?this.computeStateProps(t,e):r},i.prototype.computeDispatchProps=function(t,e){if(!this.finalMapDispatchToProps)return this.configureFinalMapDispatch(t,e);var r=t.dispatch,o=this.doDispatchPropsDependOnOwnProps?this.finalMapDispatchToProps(r,e):this.finalMapDispatchToProps(r);return o},i.prototype.configureFinalMapDispatch=function(t,e){var r=n(t.dispatch,e),o="function"==typeof r;return this.finalMapDispatchToProps=o?r:n,this.doDispatchPropsDependOnOwnProps=1!==this.finalMapDispatchToProps.length,o?this.computeDispatchProps(t,e):r},i.prototype.updateStatePropsIfNeeded=function(){var t=this.computeStateProps(this.store,this.props);return(!this.stateProps||!(0,_shallowEqual2.default)(t,this.stateProps))&&(this.stateProps=t,!0)},i.prototype.updateDispatchPropsIfNeeded=function(){var t=this.computeDispatchProps(this.store,this.props);return(!this.dispatchProps||!(0,_shallowEqual2.default)(t,this.dispatchProps))&&(this.dispatchProps=t,!0)},i.prototype.updateMergedPropsIfNeeded=function(){var t=e(this.stateProps,this.dispatchProps,this.props);return!(this.mergedProps&&l&&(0,_shallowEqual2.default)(t,this.mergedProps))&&(this.mergedProps=t,!0)},i.prototype.isSubscribed=function(){return"function"==typeof this.unsubscribe},i.prototype.trySubscribe=function(){s&&!this.unsubscribe&&(this.unsubscribe=this.store.subscribe(this.handleChange.bind(this)),this.handleChange())},i.prototype.tryUnsubscribe=function(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null)},i.prototype.componentDidMount=function(){this.trySubscribe()},i.prototype.componentWillReceiveProps=function(t){u&&(0,_shallowEqual2.default)(t,this.props)||(this.haveOwnPropsChanged=!0)},i.prototype.componentWillUnmount=function(){this.tryUnsubscribe(),this.clearCache()},i.prototype.clearCache=function(){this.dispatchProps=null,this.stateProps=null,this.mergedProps=null,this.haveOwnPropsChanged=!0,this.hasStoreStateChanged=!0,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,this.renderedElement=null,this.finalMapDispatchToProps=null,this.finalMapStateToProps=null},i.prototype.handleChange=function(){if(this.unsubscribe){var t=this.store.getState(),e=this.state.storeState;if(!u||e!==t){if(u&&!this.doStatePropsDependOnOwnProps){var r=tryCatch(this.updateStatePropsIfNeeded,this);if(!r)return;r===errorObject&&(this.statePropsPrecalculationError=errorObject.value),this.haveStatePropsBeenPrecalculated=!0}this.hasStoreStateChanged=!0,this.setState({storeState:t})}}},i.prototype.getWrappedInstance=function(){return(0,_invariant2.default)(c,"To access the wrapped instance, you need to specify { withRef: true } as the fourth argument of the connect() call."),this.refs.wrappedInstance},i.prototype.render=function(){var e=this.haveOwnPropsChanged,r=this.hasStoreStateChanged,o=this.haveStatePropsBeenPrecalculated,s=this.statePropsPrecalculationError,a=this.renderedElement;if(this.haveOwnPropsChanged=!1,this.hasStoreStateChanged=!1,this.haveStatePropsBeenPrecalculated=!1,this.statePropsPrecalculationError=null,s)throw s;var n=!0,i=!0;u&&a&&(n=r||e&&this.doStatePropsDependOnOwnProps,i=e&&this.doDispatchPropsDependOnOwnProps);var p=!1,h=!1;o?p=!0:n&&(p=this.updateStatePropsIfNeeded()),i&&(h=this.updateDispatchPropsIfNeeded());var l=!0;return l=!!(p||h||e)&&this.updateMergedPropsIfNeeded(),!l&&a?a:(c?this.renderedElement=(0,_react.createElement)(t,_extends({},this.mergedProps,{ref:"wrappedInstance"})):this.renderedElement=(0,_react.createElement)(t,this.mergedProps),this.renderedElement)},i}(_react.Component);return o.displayName=r,o.WrappedComponent=t,o.contextTypes={store:_storeShape2.default},o.propTypes={store:_storeShape2.default},(0,_hoistNonReactStatics2.default)(o,t)}}var _extends=Object.assign||function(t){for(var e=1;e -1 && value % 1 == 0 && value < length; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + */ +function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * A fallback implementation of `Object.keys` which creates an array of the + * own enumerable property names of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function shimKeys(object) { + var props = keysIn(object), + propsLength = props.length, + length = propsLength && object.length; + + var allowIndexes = !!length && isLength(length) && + (isArray(object) || isArguments(object)); + + var index = -1, + result = []; + + while (++index < propsLength) { + var key = props[index]; + if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; +} + +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) + * for more details. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if ((typeof Ctor == 'function' && Ctor.prototype === object) || + (typeof object != 'function' && isArrayLike(object))) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; +}; + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = (length && isLength(length) && + (isArray(object) || isArguments(object)) && length) || 0; + + var Ctor = object.constructor, + index = -1, + isProto = typeof Ctor == 'function' && Ctor.prototype === object, + result = Array(length), + skipIndexes = length > 0; + + while (++index < length) { + result[index] = (index + ''); + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && + !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; +} + +module.exports = keys; + +},{"lodash._getnative":26,"lodash.isarguments":28,"lodash.isarray":29}],31:[function(require,module,exports){ +var overArg = require('./_overArg'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetPrototype = Object.getPrototypeOf; + +/** + * Gets the `[[Prototype]]` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {null|Object} Returns the `[[Prototype]]`. + */ +var getPrototype = overArg(nativeGetPrototype, Object); + +module.exports = getPrototype; + +},{"./_overArg":33}],32:[function(require,module,exports){ +/** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ +function isHostObject(value) { + // Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result = false; + if (value != null && typeof value.toString != 'function') { + try { + result = !!(value + ''); + } catch (e) {} + } + return result; +} + +module.exports = isHostObject; + +},{}],33:[function(require,module,exports){ +/** + * Creates a function that invokes `func` with its first argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +module.exports = overArg; + +},{}],34:[function(require,module,exports){ +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +module.exports = isObjectLike; + +},{}],35:[function(require,module,exports){ +var getPrototype = require('./_getPrototype'), + isHostObject = require('./_isHostObject'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = Function.prototype.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to infer the `Object` constructor. */ +var objectCtorString = funcToString.call(Object); + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, + * else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ +function isPlainObject(value) { + if (!isObjectLike(value) || + objectToString.call(value) != objectTag || isHostObject(value)) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return (typeof Ctor == 'function' && + Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); +} + +module.exports = isPlainObject; + +},{"./_getPrototype":31,"./_isHostObject":32,"./isObjectLike":34}],36:[function(require,module,exports){ +'use strict'; +/* eslint-disable no-unused-vars */ +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; + +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + + return Object(val); +} + +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + + // Detect buggy property enumeration order in older V8 versions. + + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } + + return true; + } catch (e) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} + +module.exports = shouldUseNative() ? Object.assign : function (target, source) { + var from; + var to = toObject(target); + var symbols; + + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + + if (Object.getOwnPropertySymbols) { + symbols = Object.getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + + return to; +}; + +},{}],37:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +(function () { + try { + cachedSetTimeout = setTimeout; + } catch (e) { + cachedSetTimeout = function () { + throw new Error('setTimeout is not defined'); + } + } + try { + cachedClearTimeout = clearTimeout; + } catch (e) { + cachedClearTimeout = function () { + throw new Error('clearTimeout is not defined'); + } + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + return setTimeout(fun, 0); + } else { + return cachedSetTimeout.call(null, fun, 0); + } +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + clearTimeout(marker); + } else { + cachedClearTimeout.call(null, marker); + } +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; },{}],38:[function(require,module,exports){ -"use strict";function wrapActionCreators(r){return function(e){return(0,_redux.bindActionCreators)(r,e)}}exports.__esModule=!0,exports.default=wrapActionCreators;var _redux=require("redux"); +'use strict'; +var strictUriEncode = require('strict-uri-encode'); -},{"redux":"redux"}],39:[function(require,module,exports){ -"use strict";function loopAsync(n,o,t){function c(){return l=!0,s?void(u=[].concat(Array.prototype.slice.call(arguments))):void t.apply(this,arguments)}function i(){if(!l&&(p=!0,!s)){for(s=!0;!l&&r=n&&p&&(l=!0,t()))}}var r=0,l=!1,s=!1,p=!1,u=void 0;i()}function mapAsync(n,o,t){function c(n,o,c){l||(o?(l=!0,t(o)):(r[n]=c,l=++s===i,l&&t(null,r)))}var i=n.length,r=[];if(0===i)return t(null,r);var l=!1,s=0;n.forEach(function(n,t){o(n,t,function(n,o){c(t,n,o)})})}exports.__esModule=!0,exports.loopAsync=loopAsync,exports.mapAsync=mapAsync; +exports.extract = function (str) { + return str.split('?')[1] || ''; +}; -},{}],40:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}exports.__esModule=!0;var _routerWarning=require("./routerWarning"),_routerWarning2=_interopRequireDefault(_routerWarning),_InternalPropTypes=require("./InternalPropTypes"),History={contextTypes:{history:_InternalPropTypes.history},componentWillMount:function(){this.history=this.context.history}};exports.default=History,module.exports=exports.default; +exports.parse = function (str) { + if (typeof str !== 'string') { + return {}; + } -},{"./InternalPropTypes":44,"./routerWarning":72}],41:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}exports.__esModule=!0;var _extends=Object.assign||function(e){for(var t=1;t should not have a "'+r+'" prop')}exports.__esModule=!0,exports.routes=exports.route=exports.components=exports.component=exports.history=void 0,exports.falsy=falsy;var _react=require("react"),func=_react.PropTypes.func,object=_react.PropTypes.object,arrayOf=_react.PropTypes.arrayOf,oneOfType=_react.PropTypes.oneOfType,element=_react.PropTypes.element,shape=_react.PropTypes.shape,string=_react.PropTypes.string,history=exports.history=shape({listen:func.isRequired,push:func.isRequired,replace:func.isRequired,go:func.isRequired,goBack:func.isRequired,goForward:func.isRequired}),component=exports.component=oneOfType([func,string]),components=exports.components=oneOfType([component,object]),route=exports.route=oneOfType([object,element]),routes=exports.routes=oneOfType([route,arrayOf(route)]); + key = decodeURIComponent(key); -},{"react":"react"}],45:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}exports.__esModule=!0;var _routerWarning=require("./routerWarning"),_routerWarning2=_interopRequireDefault(_routerWarning),_react=require("react"),_react2=_interopRequireDefault(_react),_invariant=require("invariant"),_invariant2=_interopRequireDefault(_invariant),object=_react2.default.PropTypes.object,Lifecycle={contextTypes:{history:object.isRequired,route:object},propTypes:{route:object},componentDidMount:function(){this.routerWillLeave?void 0:(0,_invariant2.default)(!1);var e=this.props.route||this.context.route;e?void 0:(0,_invariant2.default)(!1),this._unlistenBeforeLeavingRoute=this.context.history.listenBeforeLeavingRoute(e,this.routerWillLeave)},componentWillUnmount:function(){this._unlistenBeforeLeavingRoute&&this._unlistenBeforeLeavingRoute()}};exports.default=Lifecycle,module.exports=exports.default; + // missing `=` should be `null`: + // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters + val = val === undefined ? null : decodeURIComponent(val); -},{"./routerWarning":72,"invariant":23,"react":"react"}],46:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _objectWithoutProperties(e,t){var r={};for(var a in e)t.indexOf(a)>=0||Object.prototype.hasOwnProperty.call(e,a)&&(r[a]=e[a]);return r}function isLeftClickEvent(e){return 0===e.button}function isModifiedEvent(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function isEmptyObject(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))return!1;return!0}function createLocationDescriptor(e,t){var r=t.query,a=t.hash,n=t.state;return r||a||n?{pathname:e,query:r,hash:a,state:n}:e}exports.__esModule=!0;var _extends=Object.assign||function(e){for(var t=1;t0?void 0:(0,_invariant2.default)(!1),null!=p&&(i+=encodeURI(p))):"("===o?n+=1:")"===o?n-=1:":"===o.charAt(0)?(s=o.substring(1),p=t[s],null!=p||n>0?void 0:(0,_invariant2.default)(!1),null!=p&&(i+=encodeURIComponent(p))):i+=o;return i.replace(/\/+/g,"/")}exports.__esModule=!0,exports.compilePattern=compilePattern,exports.matchPattern=matchPattern,exports.getParamNames=getParamNames,exports.getParams=getParams,exports.formatPattern=formatPattern;var _invariant=require("invariant"),_invariant2=_interopRequireDefault(_invariant),CompiledPatternsCache={}; + return ret; + }, {}); +}; -},{"invariant":23}],48:[function(require,module,exports){ -"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var r={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(r[t]=e[t]);return r.default=e,r}function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}exports.__esModule=!0,exports.router=exports.routes=exports.route=exports.components=exports.component=exports.location=exports.history=exports.falsy=exports.locationShape=exports.routerShape=void 0;var _react=require("react"),_deprecateObjectProperties=require("./deprecateObjectProperties"),_deprecateObjectProperties2=_interopRequireDefault(_deprecateObjectProperties),_InternalPropTypes=require("./InternalPropTypes"),InternalPropTypes=_interopRequireWildcard(_InternalPropTypes),_routerWarning=require("./routerWarning"),_routerWarning2=_interopRequireDefault(_routerWarning),func=_react.PropTypes.func,object=_react.PropTypes.object,shape=_react.PropTypes.shape,string=_react.PropTypes.string,routerShape=exports.routerShape=shape({push:func.isRequired,replace:func.isRequired,go:func.isRequired,goBack:func.isRequired,goForward:func.isRequired,setRouteLeaveHook:func.isRequired,isActive:func.isRequired}),locationShape=exports.locationShape=shape({pathname:string.isRequired,search:string.isRequired,state:object,action:string.isRequired,key:string}),falsy=exports.falsy=InternalPropTypes.falsy,history=exports.history=InternalPropTypes.history,location=exports.location=locationShape,component=exports.component=InternalPropTypes.component,components=exports.components=InternalPropTypes.components,route=exports.route=InternalPropTypes.route,routes=exports.routes=InternalPropTypes.routes,router=exports.router=routerShape,defaultExport={falsy:falsy,history:history,location:location,component:component,components:components,route:route,router:router};exports.default=defaultExport; +exports.stringify = function (obj) { + return obj ? Object.keys(obj).sort().map(function (key) { + var val = obj[key]; -},{"./InternalPropTypes":44,"./deprecateObjectProperties":64,"./routerWarning":72,"react":"react"}],49:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}exports.__esModule=!0;var _react=require("react"),_react2=_interopRequireDefault(_react),_invariant=require("invariant"),_invariant2=_interopRequireDefault(_invariant),_RouteUtils=require("./RouteUtils"),_PatternUtils=require("./PatternUtils"),_InternalPropTypes=require("./InternalPropTypes"),_React$PropTypes=_react2.default.PropTypes,string=_React$PropTypes.string,object=_React$PropTypes.object,Redirect=_react2.default.createClass({displayName:"Redirect",statics:{createRouteFromReactElement:function(e){var t=(0,_RouteUtils.createRouteFromReactElement)(e);return t.from&&(t.path=t.from),t.onEnter=function(e,r){var a=e.location,n=e.params,i=void 0;if("/"===t.to.charAt(0))i=(0,_PatternUtils.formatPattern)(t.to,n);else if(t.to){var o=e.routes.indexOf(t),s=Redirect.getRoutePattern(e.routes,o-1),u=s.replace(/\/*$/,"/")+t.to;i=(0,_PatternUtils.formatPattern)(u,n)}else i=a.pathname;r({pathname:i,query:t.query||a.query,state:t.state||a.state})},t},getRoutePattern:function(e,t){for(var r="",a=t;a>=0;a--){var n=e[a],i=n.path||"";if(r=i.replace(/\/*$/,"/")+r,0===i.indexOf("/"))break}return"/"+r}},propTypes:{path:string,from:string,to:string.isRequired,query:object,state:object,onEnter:_InternalPropTypes.falsy,children:_InternalPropTypes.falsy},render:function(){(0,_invariant2.default)(!1)}});exports.default=Redirect,module.exports=exports.default; + if (val === undefined) { + return ''; + } -},{"./InternalPropTypes":44,"./PatternUtils":47,"./RouteUtils":52,"invariant":23,"react":"react"}],50:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}exports.__esModule=!0;var _react=require("react"),_react2=_interopRequireDefault(_react),_invariant=require("invariant"),_invariant2=_interopRequireDefault(_invariant),_RouteUtils=require("./RouteUtils"),_InternalPropTypes=require("./InternalPropTypes"),_React$PropTypes=_react2.default.PropTypes,string=_React$PropTypes.string,func=_React$PropTypes.func,Route=_react2.default.createClass({displayName:"Route",statics:{createRouteFromReactElement:_RouteUtils.createRouteFromReactElement},propTypes:{path:string,component:_InternalPropTypes.component,components:_InternalPropTypes.components,getComponent:func,getComponents:func},render:function(){(0,_invariant2.default)(!1)}});exports.default=Route,module.exports=exports.default; + if (val === null) { + return key; + } -},{"./InternalPropTypes":44,"./RouteUtils":52,"invariant":23,"react":"react"}],51:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}exports.__esModule=!0;var _routerWarning=require("./routerWarning"),_routerWarning2=_interopRequireDefault(_routerWarning),_react=require("react"),_react2=_interopRequireDefault(_react),object=_react2.default.PropTypes.object,RouteContext={propTypes:{route:object.isRequired},childContextTypes:{route:object.isRequired},getChildContext:function(){return{route:this.props.route}},componentWillMount:function(){}};exports.default=RouteContext,module.exports=exports.default; + if (Array.isArray(val)) { + return val.slice().sort().map(function (val2) { + return strictUriEncode(key) + '=' + strictUriEncode(val2); + }).join('&'); + } -},{"./routerWarning":72,"react":"react"}],52:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function isValidChild(e){return null==e||_react2.default.isValidElement(e)}function isReactChildren(e){return isValidChild(e)||Array.isArray(e)&&e.every(isValidChild)}function createRoute(e,t){return _extends({},e,t)}function createRouteFromReactElement(e){var t=e.type,r=createRoute(t.defaultProps,e.props);if(r.children){var a=createRoutesFromReactChildren(r.children,r);a.length&&(r.childRoutes=a),delete r.children}return r}function createRoutesFromReactChildren(e,t){var r=[];return _react2.default.Children.forEach(e,function(e){if(_react2.default.isValidElement(e))if(e.type.createRouteFromReactElement){var a=e.type.createRouteFromReactElement(e,t);a&&r.push(a)}else r.push(createRouteFromReactElement(e))}),r}function createRoutes(e){return isReactChildren(e)?e=createRoutesFromReactChildren(e):e&&!Array.isArray(e)&&(e=[e]),e}exports.__esModule=!0;var _extends=Object.assign||function(e){for(var t=1;t=0||Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t}function isDeprecatedHistory(e){return!e||!e.__v2_compatible__}function isUnsupportedHistory(e){return e&&e.getCurrentLocation}exports.__esModule=!0;var _extends=Object.assign||function(e){for(var r=1;r does not support changing `store` on the fly. ' + 'It is most likely that you see this error because you updated to ' + 'Redux 2.x and React Redux 2.x which no longer hot reload reducers ' + 'automatically. See https://github.com/reactjs/react-redux/releases/' + 'tag/v2.0.0 for the migration instructions.'); +} -},{"./AsyncUtils":39,"./makeStateWithLocation":69}],66:[function(require,module,exports){ -"use strict";function getRouteParams(t,e){var r={};return t.path?((0,_PatternUtils.getParamNames)(t.path).forEach(function(t){Object.prototype.hasOwnProperty.call(e,t)&&(r[t]=e[t])}),r):r}exports.__esModule=!0;var _PatternUtils=require("./PatternUtils");exports.default=getRouteParams,module.exports=exports.default; +var Provider = function (_Component) { + _inherits(Provider, _Component); -},{"./PatternUtils":47}],67:[function(require,module,exports){ -"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}exports.__esModule=!0;var _createHashHistory=require("history/lib/createHashHistory"),_createHashHistory2=_interopRequireDefault(_createHashHistory),_createRouterHistory=require("./createRouterHistory"),_createRouterHistory2=_interopRequireDefault(_createRouterHistory);exports.default=(0,_createRouterHistory2.default)(_createHashHistory2.default),module.exports=exports.default; + Provider.prototype.getChildContext = function getChildContext() { + return { store: this.store }; + }; -},{"./createRouterHistory":62,"history/lib/createHashHistory":14}],68:[function(require,module,exports){ -"use strict";function deepEqual(t,e){if(t==e)return!0;if(null==t||null==e)return!1;if(Array.isArray(t))return Array.isArray(e)&&t.length===e.length&&t.every(function(t,r){return deepEqual(t,e[r])});if("object"===("undefined"==typeof t?"undefined":_typeof(t))){for(var r in t)if(Object.prototype.hasOwnProperty.call(t,r))if(void 0===t[r]){if(void 0!==e[r])return!1}else{if(!Object.prototype.hasOwnProperty.call(e,r))return!1;if(!deepEqual(t[r],e[r]))return!1}return!0}return String(t)===String(e)}function pathIsActive(t,e){return"/"!==e.charAt(0)&&(e="/"+e),"/"!==t.charAt(t.length-1)&&(t+="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e===t}function routeIsActive(t,e,r){for(var n=t,u=[],i=[],a=0,o=e.length;a=0||Object.prototype.hasOwnProperty.call(e,o)&&(r[o]=e[o]);return r}function match(e,t){var r=e.history,o=e.routes,i=e.location,a=_objectWithoutProperties(e,["history","routes","location"]);r||i?void 0:(0,_invariant2.default)(!1),r=r?r:(0,_createMemoryHistory2.default)(a);var n=(0,_createTransitionManager2.default)(r,(0,_RouteUtils.createRoutes)(o)),u=void 0;i?i=r.createLocation(i):u=r.listen(function(e){i=e});var s=(0,_RouterUtils.createRouterObject)(r,n);r=(0,_RouterUtils.createRoutingHistory)(r,n),n.match(i,function(e,o,i){t(e,o,i&&_extends({},i,{history:r,router:s,matchContext:{history:r,transitionManager:n,router:s}})),u&&u()})}exports.__esModule=!0;var _extends=Object.assign||function(e){for(var t=1;t2?n-2:0),a=2;a=0||Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t}function useRoutes(e){return function(){var r=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],t=r.routes,n=_objectWithoutProperties(r,["routes"]),u=(0,_useQueries2.default)(e)(n),i=(0,_createTransitionManager2.default)(u,t);return _extends({},u,i)}}exports.__esModule=!0;var _extends=Object.assign||function(e){for(var r=1;r8&&documentMode<=11),SPACEBAR_CODE=32,SPACEBAR_CHAR=String.fromCharCode(SPACEBAR_CODE),topLevelTypes=EventConstants.topLevelTypes,eventTypes={beforeInput:{phasedRegistrationNames:{bubbled:keyOf({onBeforeInput:null}),captured:keyOf({onBeforeInputCapture:null})},dependencies:[topLevelTypes.topCompositionEnd,topLevelTypes.topKeyPress,topLevelTypes.topTextInput,topLevelTypes.topPaste]},compositionEnd:{phasedRegistrationNames:{bubbled:keyOf({onCompositionEnd:null}),captured:keyOf({onCompositionEndCapture:null})},dependencies:[topLevelTypes.topBlur,topLevelTypes.topCompositionEnd,topLevelTypes.topKeyDown,topLevelTypes.topKeyPress,topLevelTypes.topKeyUp,topLevelTypes.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:keyOf({onCompositionStart:null}),captured:keyOf({onCompositionStartCapture:null})},dependencies:[topLevelTypes.topBlur,topLevelTypes.topCompositionStart,topLevelTypes.topKeyDown,topLevelTypes.topKeyPress,topLevelTypes.topKeyUp,topLevelTypes.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:keyOf({onCompositionUpdate:null}),captured:keyOf({onCompositionUpdateCapture:null})},dependencies:[topLevelTypes.topBlur,topLevelTypes.topCompositionUpdate,topLevelTypes.topKeyDown,topLevelTypes.topKeyPress,topLevelTypes.topKeyUp,topLevelTypes.topMouseDown]}},hasSpaceKeypress=!1,currentComposition=null,BeforeInputEventPlugin={eventTypes:eventTypes,extractEvents:function(e,t,o,n){return[extractCompositionEvent(e,t,o,n),extractBeforeInputEvent(e,t,o,n)]}};module.exports=BeforeInputEventPlugin; +Provider.propTypes = { + store: _storeShape2["default"].isRequired, + children: _react.PropTypes.element.isRequired +}; +Provider.childContextTypes = { + store: _storeShape2["default"].isRequired +}; +}).call(this,require('_process')) -},{"./EventConstants":91,"./EventPropagators":95,"./FallbackCompositionState":96,"./SyntheticCompositionEvent":165,"./SyntheticInputEvent":169,"fbjs/lib/ExecutionEnvironment":210,"fbjs/lib/keyOf":228}],78:[function(require,module,exports){ -"use strict";function prefixKey(o,r){return o+r.charAt(0).toUpperCase()+r.substring(1)}var isUnitlessNumber={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridColumn:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},prefixes=["Webkit","ms","Moz","O"];Object.keys(isUnitlessNumber).forEach(function(o){prefixes.forEach(function(r){isUnitlessNumber[prefixKey(r,o)]=isUnitlessNumber[o]})});var shorthandPropertyExpansions={background:{backgroundAttachment:!0,backgroundColor:!0,backgroundImage:!0,backgroundPositionX:!0,backgroundPositionY:!0,backgroundRepeat:!0},backgroundPosition:{backgroundPositionX:!0,backgroundPositionY:!0},border:{borderWidth:!0,borderStyle:!0,borderColor:!0},borderBottom:{borderBottomWidth:!0,borderBottomStyle:!0,borderBottomColor:!0},borderLeft:{borderLeftWidth:!0,borderLeftStyle:!0,borderLeftColor:!0},borderRight:{borderRightWidth:!0,borderRightStyle:!0,borderRightColor:!0},borderTop:{borderTopWidth:!0,borderTopStyle:!0,borderTopColor:!0},font:{fontStyle:!0,fontVariant:!0,fontWeight:!0,fontSize:!0,lineHeight:!0,fontFamily:!0},outline:{outlineWidth:!0,outlineStyle:!0,outlineColor:!0}},CSSProperty={isUnitlessNumber:isUnitlessNumber,shorthandPropertyExpansions:shorthandPropertyExpansions};module.exports=CSSProperty; +},{"../utils/storeShape":42,"../utils/warning":43,"_process":37,"react":"react"}],40:[function(require,module,exports){ +(function (process){ +'use strict'; -},{}],79:[function(require,module,exports){ -"use strict";var CSSProperty=require("./CSSProperty"),ExecutionEnvironment=require("fbjs/lib/ExecutionEnvironment"),ReactInstrumentation=require("./ReactInstrumentation"),camelizeStyleName=require("fbjs/lib/camelizeStyleName"),dangerousStyleValue=require("./dangerousStyleValue"),hyphenateStyleName=require("fbjs/lib/hyphenateStyleName"),memoizeStringOnly=require("fbjs/lib/memoizeStringOnly"),warning=require("fbjs/lib/warning"),processStyleName=memoizeStringOnly(function(e){return hyphenateStyleName(e)}),hasShorthandPropertyBug=!1,styleFloatAccessor="cssFloat";if(ExecutionEnvironment.canUseDOM){var tempStyle=document.createElement("div").style;try{tempStyle.font=""}catch(e){hasShorthandPropertyBug=!0}void 0===document.documentElement.style.cssFloat&&(styleFloatAccessor="styleFloat")}var badVendoredStyleNamePattern,badStyleValueWithSemicolonPattern,warnedStyleNames,warnedStyleValues,warnedForNaNValue,warnHyphenatedStyleName,warnBadVendoredStyleName,warnStyleValueWithSemicolon,warnStyleValueIsNaN,checkRenderMessage,warnValidStyle,CSSPropertyOperations={createMarkupForStyles:function(e,t){var r="";for(var a in e)if(e.hasOwnProperty(a)){var n=e[a];null!=n&&(r+=processStyleName(a)+":",r+=dangerousStyleValue(a,n,t)+";")}return r||null},setValueForStyles:function(e,t,r){var a=e.style;for(var n in t)if(t.hasOwnProperty(n)){var l=dangerousStyleValue(n,t[n],r);if("float"!==n&&"cssFloat"!==n||(n=styleFloatAccessor),l)a[n]=l;else{var o=hasShorthandPropertyBug&&CSSProperty.shorthandPropertyExpansions[n];if(o)for(var s in o)a[s]="";else a[n]=""}}}};module.exports=CSSPropertyOperations; +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; }; -},{"./CSSProperty":78,"./ReactInstrumentation":141,"./dangerousStyleValue":183,"fbjs/lib/ExecutionEnvironment":210,"fbjs/lib/camelizeStyleName":212,"fbjs/lib/hyphenateStyleName":223,"fbjs/lib/memoizeStringOnly":230,"fbjs/lib/warning":232}],80:[function(require,module,exports){ -"use strict";function CallbackQueue(){this._callbacks=null,this._contexts=null}var _prodInvariant=require("./reactProdInvariant"),_assign=require("object-assign"),PooledClass=require("./PooledClass"),invariant=require("fbjs/lib/invariant");_assign(CallbackQueue.prototype,{enqueue:function(t,l){this._callbacks=this._callbacks||[],this._contexts=this._contexts||[],this._callbacks.push(t),this._contexts.push(l)},notifyAll:function(){var t=this._callbacks,l=this._contexts;if(t){t.length!==l.length?_prodInvariant("24"):void 0,this._callbacks=null,this._contexts=null;for(var s=0;s8));var isInputEventSupported=!1;ExecutionEnvironment.canUseDOM&&(isInputEventSupported=isEventSupported("input")&&(!("documentMode"in document)||document.documentMode>11));var newValueProp={get:function(){return activeElementValueProp.get.call(this)},set:function(e){activeElementValue=""+e,activeElementValueProp.set.call(this,e)}},ChangeEventPlugin={eventTypes:eventTypes,extractEvents:function(e,t,n,a){var o,l,r=t?ReactDOMComponentTree.getNodeFromInstance(t):window;if(shouldUseChangeEvent(r)?doesChangeEventBubble?o=getTargetInstForChangeEvent:l=handleEventsForChangeEventIE8:isTextInputElement(r)?isInputEventSupported?o=getTargetInstForInputEvent:(o=getTargetInstForInputEventIE,l=handleEventsForInputEventIE):shouldUseClickEvent(r)&&(o=getTargetInstForClickEvent),o){var v=o(e,t);if(v){var p=SyntheticEvent.getPooled(eventTypes.change,v,n,a);return p.type="change",EventPropagators.accumulateTwoPhaseDispatches(p),p}}l&&l(e,r,t)}};module.exports=ChangeEventPlugin; +var _react = require('react'); -},{"./EventConstants":91,"./EventPluginHub":92,"./EventPropagators":95,"./ReactDOMComponentTree":115,"./ReactUpdates":158,"./SyntheticEvent":167,"./getEventTarget":191,"./isEventSupported":198,"./isTextInputElement":199,"fbjs/lib/ExecutionEnvironment":210,"fbjs/lib/keyOf":228}],82:[function(require,module,exports){ -"use strict";function getNodeAfter(e,t){return Array.isArray(t)&&(t=t[1]),t?t.nextSibling:e.firstChild}function insertLazyTreeChildAt(e,t,r){DOMLazyTree.insertTreeBefore(e,t,r)}function moveChild(e,t,r){Array.isArray(t)?moveDelimitedText(e,t[0],t[1],r):insertChildAt(e,t,r)}function removeChild(e,t){if(Array.isArray(t)){var r=t[1];t=t[0],removeDelimitedText(e,t,r),e.removeChild(r)}e.removeChild(t)}function moveDelimitedText(e,t,r,i){for(var n=t;;){var a=n.nextSibling;if(insertChildAt(e,n,i),n===r)break;n=a}}function removeDelimitedText(e,t,r){for(;;){var i=t.nextSibling;if(i===r)break;e.removeChild(i)}}function replaceDelimitedText(e,t,r){var i=e.parentNode,n=e.nextSibling;n===t?r&&insertChildAt(i,document.createTextNode(r),n):r?(setTextContent(n,r),removeDelimitedText(i,n,t)):removeDelimitedText(i,e,t)}var DOMLazyTree=require("./DOMLazyTree"),Danger=require("./Danger"),ReactMultiChildUpdateTypes=require("./ReactMultiChildUpdateTypes"),ReactDOMComponentTree=require("./ReactDOMComponentTree"),ReactInstrumentation=require("./ReactInstrumentation"),createMicrosoftUnsafeLocalFunction=require("./createMicrosoftUnsafeLocalFunction"),setInnerHTML=require("./setInnerHTML"),setTextContent=require("./setTextContent"),insertChildAt=createMicrosoftUnsafeLocalFunction(function(e,t,r){e.insertBefore(t,r)}),dangerouslyReplaceNodeWithMarkup=Danger.dangerouslyReplaceNodeWithMarkup,DOMChildrenOperations={dangerouslyReplaceNodeWithMarkup:dangerouslyReplaceNodeWithMarkup,replaceDelimitedText:replaceDelimitedText,processUpdates:function(e,t){for(var r=0;r, ' + ('or explicitly pass "store" as a prop to "' + connectDisplayName + '".')); + + var storeState = _this.store.getState(); + _this.state = { storeState: storeState }; + _this.clearCache(); + return _this; + } + + Connect.prototype.computeStateProps = function computeStateProps(store, props) { + if (!this.finalMapStateToProps) { + return this.configureFinalMapState(store, props); + } + + var state = store.getState(); + var stateProps = this.doStatePropsDependOnOwnProps ? this.finalMapStateToProps(state, props) : this.finalMapStateToProps(state); + + if (process.env.NODE_ENV !== 'production') { + checkStateShape(stateProps, 'mapStateToProps'); + } + return stateProps; + }; + + Connect.prototype.configureFinalMapState = function configureFinalMapState(store, props) { + var mappedState = mapState(store.getState(), props); + var isFactory = typeof mappedState === 'function'; + + this.finalMapStateToProps = isFactory ? mappedState : mapState; + this.doStatePropsDependOnOwnProps = this.finalMapStateToProps.length !== 1; + + if (isFactory) { + return this.computeStateProps(store, props); + } + + if (process.env.NODE_ENV !== 'production') { + checkStateShape(mappedState, 'mapStateToProps'); + } + return mappedState; + }; + + Connect.prototype.computeDispatchProps = function computeDispatchProps(store, props) { + if (!this.finalMapDispatchToProps) { + return this.configureFinalMapDispatch(store, props); + } + + var dispatch = store.dispatch; + + var dispatchProps = this.doDispatchPropsDependOnOwnProps ? this.finalMapDispatchToProps(dispatch, props) : this.finalMapDispatchToProps(dispatch); + + if (process.env.NODE_ENV !== 'production') { + checkStateShape(dispatchProps, 'mapDispatchToProps'); + } + return dispatchProps; + }; + + Connect.prototype.configureFinalMapDispatch = function configureFinalMapDispatch(store, props) { + var mappedDispatch = mapDispatch(store.dispatch, props); + var isFactory = typeof mappedDispatch === 'function'; + + this.finalMapDispatchToProps = isFactory ? mappedDispatch : mapDispatch; + this.doDispatchPropsDependOnOwnProps = this.finalMapDispatchToProps.length !== 1; + + if (isFactory) { + return this.computeDispatchProps(store, props); + } + + if (process.env.NODE_ENV !== 'production') { + checkStateShape(mappedDispatch, 'mapDispatchToProps'); + } + return mappedDispatch; + }; + + Connect.prototype.updateStatePropsIfNeeded = function updateStatePropsIfNeeded() { + var nextStateProps = this.computeStateProps(this.store, this.props); + if (this.stateProps && (0, _shallowEqual2["default"])(nextStateProps, this.stateProps)) { + return false; + } + + this.stateProps = nextStateProps; + return true; + }; + + Connect.prototype.updateDispatchPropsIfNeeded = function updateDispatchPropsIfNeeded() { + var nextDispatchProps = this.computeDispatchProps(this.store, this.props); + if (this.dispatchProps && (0, _shallowEqual2["default"])(nextDispatchProps, this.dispatchProps)) { + return false; + } + + this.dispatchProps = nextDispatchProps; + return true; + }; + + Connect.prototype.updateMergedPropsIfNeeded = function updateMergedPropsIfNeeded() { + var nextMergedProps = computeMergedProps(this.stateProps, this.dispatchProps, this.props); + if (this.mergedProps && checkMergedEquals && (0, _shallowEqual2["default"])(nextMergedProps, this.mergedProps)) { + return false; + } + + this.mergedProps = nextMergedProps; + return true; + }; + + Connect.prototype.isSubscribed = function isSubscribed() { + return typeof this.unsubscribe === 'function'; + }; + + Connect.prototype.trySubscribe = function trySubscribe() { + if (shouldSubscribe && !this.unsubscribe) { + this.unsubscribe = this.store.subscribe(this.handleChange.bind(this)); + this.handleChange(); + } + }; + + Connect.prototype.tryUnsubscribe = function tryUnsubscribe() { + if (this.unsubscribe) { + this.unsubscribe(); + this.unsubscribe = null; + } + }; + + Connect.prototype.componentDidMount = function componentDidMount() { + this.trySubscribe(); + }; + + Connect.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { + if (!pure || !(0, _shallowEqual2["default"])(nextProps, this.props)) { + this.haveOwnPropsChanged = true; + } + }; + + Connect.prototype.componentWillUnmount = function componentWillUnmount() { + this.tryUnsubscribe(); + this.clearCache(); + }; + + Connect.prototype.clearCache = function clearCache() { + this.dispatchProps = null; + this.stateProps = null; + this.mergedProps = null; + this.haveOwnPropsChanged = true; + this.hasStoreStateChanged = true; + this.haveStatePropsBeenPrecalculated = false; + this.statePropsPrecalculationError = null; + this.renderedElement = null; + this.finalMapDispatchToProps = null; + this.finalMapStateToProps = null; + }; + + Connect.prototype.handleChange = function handleChange() { + if (!this.unsubscribe) { + return; + } + + var storeState = this.store.getState(); + var prevStoreState = this.state.storeState; + if (pure && prevStoreState === storeState) { + return; + } + + if (pure && !this.doStatePropsDependOnOwnProps) { + var haveStatePropsChanged = tryCatch(this.updateStatePropsIfNeeded, this); + if (!haveStatePropsChanged) { + return; + } + if (haveStatePropsChanged === errorObject) { + this.statePropsPrecalculationError = errorObject.value; + } + this.haveStatePropsBeenPrecalculated = true; + } + + this.hasStoreStateChanged = true; + this.setState({ storeState: storeState }); + }; + + Connect.prototype.getWrappedInstance = function getWrappedInstance() { + (0, _invariant2["default"])(withRef, 'To access the wrapped instance, you need to specify ' + '{ withRef: true } as the fourth argument of the connect() call.'); + + return this.refs.wrappedInstance; + }; + + Connect.prototype.render = function render() { + var haveOwnPropsChanged = this.haveOwnPropsChanged; + var hasStoreStateChanged = this.hasStoreStateChanged; + var haveStatePropsBeenPrecalculated = this.haveStatePropsBeenPrecalculated; + var statePropsPrecalculationError = this.statePropsPrecalculationError; + var renderedElement = this.renderedElement; + + this.haveOwnPropsChanged = false; + this.hasStoreStateChanged = false; + this.haveStatePropsBeenPrecalculated = false; + this.statePropsPrecalculationError = null; + + if (statePropsPrecalculationError) { + throw statePropsPrecalculationError; + } + + var shouldUpdateStateProps = true; + var shouldUpdateDispatchProps = true; + if (pure && renderedElement) { + shouldUpdateStateProps = hasStoreStateChanged || haveOwnPropsChanged && this.doStatePropsDependOnOwnProps; + shouldUpdateDispatchProps = haveOwnPropsChanged && this.doDispatchPropsDependOnOwnProps; + } + + var haveStatePropsChanged = false; + var haveDispatchPropsChanged = false; + if (haveStatePropsBeenPrecalculated) { + haveStatePropsChanged = true; + } else if (shouldUpdateStateProps) { + haveStatePropsChanged = this.updateStatePropsIfNeeded(); + } + if (shouldUpdateDispatchProps) { + haveDispatchPropsChanged = this.updateDispatchPropsIfNeeded(); + } + + var haveMergedPropsChanged = true; + if (haveStatePropsChanged || haveDispatchPropsChanged || haveOwnPropsChanged) { + haveMergedPropsChanged = this.updateMergedPropsIfNeeded(); + } else { + haveMergedPropsChanged = false; + } + + if (!haveMergedPropsChanged && renderedElement) { + return renderedElement; + } + + if (withRef) { + this.renderedElement = (0, _react.createElement)(WrappedComponent, _extends({}, this.mergedProps, { + ref: 'wrappedInstance' + })); + } else { + this.renderedElement = (0, _react.createElement)(WrappedComponent, this.mergedProps); + } + + return this.renderedElement; + }; + + return Connect; + }(_react.Component); + + Connect.displayName = connectDisplayName; + Connect.WrappedComponent = WrappedComponent; + Connect.contextTypes = { + store: _storeShape2["default"] + }; + Connect.propTypes = { + store: _storeShape2["default"] + }; + + if (process.env.NODE_ENV !== 'production') { + Connect.prototype.componentWillUpdate = function componentWillUpdate() { + if (this.version === version) { + return; + } + + // We are hot reloading! + this.version = version; + this.trySubscribe(); + this.clearCache(); + }; + } + + return (0, _hoistNonReactStatics2["default"])(Connect, WrappedComponent); + }; +} +}).call(this,require('_process')) + +},{"../utils/shallowEqual":41,"../utils/storeShape":42,"../utils/warning":43,"../utils/wrapActionCreators":44,"_process":37,"hoist-non-react-statics":24,"invariant":25,"lodash/isPlainObject":35,"react":"react"}],41:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports["default"] = shallowEqual; +function shallowEqual(objA, objB) { + if (objA === objB) { + return true; + } + + var keysA = Object.keys(objA); + var keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } + + // Test for A's keys different from B. + var hasOwn = Object.prototype.hasOwnProperty; + for (var i = 0; i < keysA.length; i++) { + if (!hasOwn.call(objB, keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) { + return false; + } + } + + return true; +} +},{}],42:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _react = require('react'); + +exports["default"] = _react.PropTypes.shape({ + subscribe: _react.PropTypes.func.isRequired, + dispatch: _react.PropTypes.func.isRequired, + getState: _react.PropTypes.func.isRequired +}); +},{"react":"react"}],43:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; +exports["default"] = warning; +/** + * Prints a warning in the console if it exists. + * + * @param {String} message The warning message. + * @returns {void} + */ +function warning(message) { + /* eslint-disable no-console */ + if (typeof console !== 'undefined' && typeof console.error === 'function') { + console.error(message); + } + /* eslint-enable no-console */ + try { + // This error was thrown as a convenience so that you can use this stack + // to find the callsite that caused this warning to fire. + throw new Error(message); + /* eslint-disable no-empty */ + } catch (e) {} + /* eslint-enable no-empty */ +} +},{}],44:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; +exports["default"] = wrapActionCreators; + +var _redux = require('redux'); + +function wrapActionCreators(actionCreators) { + return function (dispatch) { + return (0, _redux.bindActionCreators)(actionCreators, dispatch); + }; +} +},{"redux":"redux"}],45:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.loopAsync = loopAsync; +exports.mapAsync = mapAsync; +function loopAsync(turns, work, callback) { + var currentTurn = 0, + isDone = false; + var sync = false, + hasNext = false, + doneArgs = void 0; + + function done() { + isDone = true; + if (sync) { + // Iterate instead of recursing if possible. + doneArgs = [].concat(Array.prototype.slice.call(arguments)); + return; + } + + callback.apply(this, arguments); + } + + function next() { + if (isDone) { + return; + } + + hasNext = true; + if (sync) { + // Iterate instead of recursing if possible. + return; + } + + sync = true; + + while (!isDone && currentTurn < turns && hasNext) { + hasNext = false; + work.call(this, currentTurn++, next, done); + } + + sync = false; + + if (isDone) { + // This means the loop finished synchronously. + callback.apply(this, doneArgs); + return; + } + + if (currentTurn >= turns && hasNext) { + isDone = true; + callback(); + } + } + + next(); +} + +function mapAsync(array, work, callback) { + var length = array.length; + var values = []; + + if (length === 0) return callback(null, values); + + var isDone = false, + doneCount = 0; + + function done(index, error, value) { + if (isDone) return; + + if (error) { + isDone = true; + callback(error); + } else { + values[index] = value; + + isDone = ++doneCount === length; + + if (isDone) callback(null, values); + } + } + + array.forEach(function (item, index) { + work(item, index, function (error, value) { + done(index, error, value); + }); + }); +} +},{}],46:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +var _InternalPropTypes = require('./InternalPropTypes'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * A mixin that adds the "history" instance variable to components. + */ +var History = { + + contextTypes: { + history: _InternalPropTypes.history + }, + + componentWillMount: function componentWillMount() { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'the `History` mixin is deprecated, please access `context.router` with your own `contextTypes`. http://tiny.cc/router-historymixin') : void 0; + this.history = this.context.history; + } +}; + +exports.default = History; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./InternalPropTypes":50,"./routerWarning":78,"_process":37}],47:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _Link = require('./Link'); + +var _Link2 = _interopRequireDefault(_Link); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * An is used to link to an . + */ +var IndexLink = _react2.default.createClass({ + displayName: 'IndexLink', + render: function render() { + return _react2.default.createElement(_Link2.default, _extends({}, this.props, { onlyActiveOnIndex: true })); + } +}); + +exports.default = IndexLink; +module.exports = exports['default']; +},{"./Link":52,"react":"react"}],48:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _Redirect = require('./Redirect'); + +var _Redirect2 = _interopRequireDefault(_Redirect); + +var _InternalPropTypes = require('./InternalPropTypes'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _React$PropTypes = _react2.default.PropTypes; +var string = _React$PropTypes.string; +var object = _React$PropTypes.object; + +/** + * An is used to redirect from an indexRoute. + */ + +var IndexRedirect = _react2.default.createClass({ + displayName: 'IndexRedirect', + + + statics: { + createRouteFromReactElement: function createRouteFromReactElement(element, parentRoute) { + /* istanbul ignore else: sanity check */ + if (parentRoute) { + parentRoute.indexRoute = _Redirect2.default.createRouteFromReactElement(element); + } else { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'An does not make sense at the root of your route config') : void 0; + } + } + }, + + propTypes: { + to: string.isRequired, + query: object, + state: object, + onEnter: _InternalPropTypes.falsy, + children: _InternalPropTypes.falsy + }, + + /* istanbul ignore next: sanity check */ + render: function render() { + !false ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, ' elements are for router configuration only and should not be rendered') : (0, _invariant2.default)(false) : void 0; + } +}); + +exports.default = IndexRedirect; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./InternalPropTypes":50,"./Redirect":55,"./routerWarning":78,"_process":37,"invariant":25,"react":"react"}],49:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _RouteUtils = require('./RouteUtils'); + +var _InternalPropTypes = require('./InternalPropTypes'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var func = _react2.default.PropTypes.func; + +/** + * An is used to specify its parent's in + * a JSX route config. + */ + +var IndexRoute = _react2.default.createClass({ + displayName: 'IndexRoute', + + + statics: { + createRouteFromReactElement: function createRouteFromReactElement(element, parentRoute) { + /* istanbul ignore else: sanity check */ + if (parentRoute) { + parentRoute.indexRoute = (0, _RouteUtils.createRouteFromReactElement)(element); + } else { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'An does not make sense at the root of your route config') : void 0; + } + } + }, + + propTypes: { + path: _InternalPropTypes.falsy, + component: _InternalPropTypes.component, + components: _InternalPropTypes.components, + getComponent: func, + getComponents: func + }, + + /* istanbul ignore next: sanity check */ + render: function render() { + !false ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, ' elements are for router configuration only and should not be rendered') : (0, _invariant2.default)(false) : void 0; + } +}); + +exports.default = IndexRoute; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./InternalPropTypes":50,"./RouteUtils":58,"./routerWarning":78,"_process":37,"invariant":25,"react":"react"}],50:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; +exports.routes = exports.route = exports.components = exports.component = exports.history = undefined; +exports.falsy = falsy; + +var _react = require('react'); + +var func = _react.PropTypes.func; +var object = _react.PropTypes.object; +var arrayOf = _react.PropTypes.arrayOf; +var oneOfType = _react.PropTypes.oneOfType; +var element = _react.PropTypes.element; +var shape = _react.PropTypes.shape; +var string = _react.PropTypes.string; +function falsy(props, propName, componentName) { + if (props[propName]) return new Error('<' + componentName + '> should not have a "' + propName + '" prop'); +} + +var history = exports.history = shape({ + listen: func.isRequired, + push: func.isRequired, + replace: func.isRequired, + go: func.isRequired, + goBack: func.isRequired, + goForward: func.isRequired +}); + +var component = exports.component = oneOfType([func, string]); +var components = exports.components = oneOfType([component, object]); +var route = exports.route = oneOfType([object, element]); +var routes = exports.routes = oneOfType([route, arrayOf(route)]); +},{"react":"react"}],51:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var object = _react2.default.PropTypes.object; + +/** + * The Lifecycle mixin adds the routerWillLeave lifecycle method to a + * component that may be used to cancel a transition or prompt the user + * for confirmation. + * + * On standard transitions, routerWillLeave receives a single argument: the + * location we're transitioning to. To cancel the transition, return false. + * To prompt the user for confirmation, return a prompt message (string). + * + * During the beforeunload event (assuming you're using the useBeforeUnload + * history enhancer), routerWillLeave does not receive a location object + * because it isn't possible for us to know the location we're transitioning + * to. In this case routerWillLeave must return a prompt message to prevent + * the user from closing the window/tab. + */ + +var Lifecycle = { + + contextTypes: { + history: object.isRequired, + // Nested children receive the route as context, either + // set by the route component using the RouteContext mixin + // or by some other ancestor. + route: object + }, + + propTypes: { + // Route components receive the route object as a prop. + route: object + }, + + componentDidMount: function componentDidMount() { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'the `Lifecycle` mixin is deprecated, please use `context.router.setRouteLeaveHook(route, hook)`. http://tiny.cc/router-lifecyclemixin') : void 0; + !this.routerWillLeave ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'The Lifecycle mixin requires you to define a routerWillLeave method') : (0, _invariant2.default)(false) : void 0; + + var route = this.props.route || this.context.route; + + !route ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'The Lifecycle mixin must be used on either a) a or ' + 'b) a descendant of a that uses the RouteContext mixin') : (0, _invariant2.default)(false) : void 0; + + this._unlistenBeforeLeavingRoute = this.context.history.listenBeforeLeavingRoute(route, this.routerWillLeave); + }, + componentWillUnmount: function componentWillUnmount() { + if (this._unlistenBeforeLeavingRoute) this._unlistenBeforeLeavingRoute(); + } +}; + +exports.default = Lifecycle; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./routerWarning":78,"_process":37,"invariant":25,"react":"react"}],52:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _PropTypes = require('./PropTypes'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +var _React$PropTypes = _react2.default.PropTypes; +var bool = _React$PropTypes.bool; +var object = _React$PropTypes.object; +var string = _React$PropTypes.string; +var func = _React$PropTypes.func; +var oneOfType = _React$PropTypes.oneOfType; + + +function isLeftClickEvent(event) { + return event.button === 0; +} + +function isModifiedEvent(event) { + return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); +} + +// TODO: De-duplicate against hasAnyProperties in createTransitionManager. +function isEmptyObject(object) { + for (var p in object) { + if (Object.prototype.hasOwnProperty.call(object, p)) return false; + }return true; +} + +function createLocationDescriptor(to, _ref) { + var query = _ref.query; + var hash = _ref.hash; + var state = _ref.state; + + if (query || hash || state) { + return { pathname: to, query: query, hash: hash, state: state }; + } + + return to; +} + +/** + * A is used to create an element that links to a route. + * When that route is active, the link gets the value of its + * activeClassName prop. + * + * For example, assuming you have the following route: + * + * + * + * You could use the following component to link to that route: + * + * + * + * Links may pass along location state and/or query string parameters + * in the state/query props, respectively. + * + * + */ +var Link = _react2.default.createClass({ + displayName: 'Link', + + + contextTypes: { + router: _PropTypes.routerShape + }, + + propTypes: { + to: oneOfType([string, object]).isRequired, + query: object, + hash: string, + state: object, + activeStyle: object, + activeClassName: string, + onlyActiveOnIndex: bool.isRequired, + onClick: func, + target: string + }, + + getDefaultProps: function getDefaultProps() { + return { + onlyActiveOnIndex: false, + style: {} + }; + }, + handleClick: function handleClick(event) { + if (this.props.onClick) this.props.onClick(event); + + if (event.defaultPrevented) return; + + !this.context.router ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 's rendered outside of a router context cannot navigate.') : (0, _invariant2.default)(false) : void 0; + + if (isModifiedEvent(event) || !isLeftClickEvent(event)) return; + + // If target prop is set (e.g. to "_blank"), let browser handle link. + /* istanbul ignore if: untestable with Karma */ + if (this.props.target) return; + + event.preventDefault(); + + var _props = this.props; + var to = _props.to; + var query = _props.query; + var hash = _props.hash; + var state = _props.state; + + var location = createLocationDescriptor(to, { query: query, hash: hash, state: state }); + + this.context.router.push(location); + }, + render: function render() { + var _props2 = this.props; + var to = _props2.to; + var query = _props2.query; + var hash = _props2.hash; + var state = _props2.state; + var activeClassName = _props2.activeClassName; + var activeStyle = _props2.activeStyle; + var onlyActiveOnIndex = _props2.onlyActiveOnIndex; + + var props = _objectWithoutProperties(_props2, ['to', 'query', 'hash', 'state', 'activeClassName', 'activeStyle', 'onlyActiveOnIndex']); + + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(!(query || hash || state), 'the `query`, `hash`, and `state` props on `` are deprecated, use `. http://tiny.cc/router-isActivedeprecated') : void 0; + + // Ignore if rendered outside the context of router, simplifies unit testing. + var router = this.context.router; + + + if (router) { + var location = createLocationDescriptor(to, { query: query, hash: hash, state: state }); + props.href = router.createHref(location); + + if (activeClassName || activeStyle != null && !isEmptyObject(activeStyle)) { + if (router.isActive(location, onlyActiveOnIndex)) { + if (activeClassName) { + if (props.className) { + props.className += ' ' + activeClassName; + } else { + props.className = activeClassName; + } + } + + if (activeStyle) props.style = _extends({}, props.style, activeStyle); + } + } + } + + return _react2.default.createElement('a', _extends({}, props, { onClick: this.handleClick })); + } +}); + +exports.default = Link; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./PropTypes":54,"./routerWarning":78,"_process":37,"invariant":25,"react":"react"}],53:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; +exports.compilePattern = compilePattern; +exports.matchPattern = matchPattern; +exports.getParamNames = getParamNames; +exports.getParams = getParams; +exports.formatPattern = formatPattern; + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} + +function _compilePattern(pattern) { + var regexpSource = ''; + var paramNames = []; + var tokens = []; + + var match = void 0, + lastIndex = 0, + matcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|\*\*|\*|\(|\)/g; + while (match = matcher.exec(pattern)) { + if (match.index !== lastIndex) { + tokens.push(pattern.slice(lastIndex, match.index)); + regexpSource += escapeRegExp(pattern.slice(lastIndex, match.index)); + } + + if (match[1]) { + regexpSource += '([^/]+)'; + paramNames.push(match[1]); + } else if (match[0] === '**') { + regexpSource += '(.*)'; + paramNames.push('splat'); + } else if (match[0] === '*') { + regexpSource += '(.*?)'; + paramNames.push('splat'); + } else if (match[0] === '(') { + regexpSource += '(?:'; + } else if (match[0] === ')') { + regexpSource += ')?'; + } + + tokens.push(match[0]); + + lastIndex = matcher.lastIndex; + } + + if (lastIndex !== pattern.length) { + tokens.push(pattern.slice(lastIndex, pattern.length)); + regexpSource += escapeRegExp(pattern.slice(lastIndex, pattern.length)); + } + + return { + pattern: pattern, + regexpSource: regexpSource, + paramNames: paramNames, + tokens: tokens + }; +} + +var CompiledPatternsCache = Object.create(null); + +function compilePattern(pattern) { + if (!CompiledPatternsCache[pattern]) CompiledPatternsCache[pattern] = _compilePattern(pattern); + + return CompiledPatternsCache[pattern]; +} + +/** + * Attempts to match a pattern on the given pathname. Patterns may use + * the following special characters: + * + * - :paramName Matches a URL segment up to the next /, ?, or #. The + * captured string is considered a "param" + * - () Wraps a segment of the URL that is optional + * - * Consumes (non-greedy) all characters up to the next + * character in the pattern, or to the end of the URL if + * there is none + * - ** Consumes (greedy) all characters up to the next character + * in the pattern, or to the end of the URL if there is none + * + * The function calls callback(error, matched) when finished. + * The return value is an object with the following properties: + * + * - remainingPathname + * - paramNames + * - paramValues + */ +function matchPattern(pattern, pathname) { + // Ensure pattern starts with leading slash for consistency with pathname. + if (pattern.charAt(0) !== '/') { + pattern = '/' + pattern; + } + + var _compilePattern2 = compilePattern(pattern); + + var regexpSource = _compilePattern2.regexpSource; + var paramNames = _compilePattern2.paramNames; + var tokens = _compilePattern2.tokens; + + + if (pattern.charAt(pattern.length - 1) !== '/') { + regexpSource += '/?'; // Allow optional path separator at end. + } + + // Special-case patterns like '*' for catch-all routes. + if (tokens[tokens.length - 1] === '*') { + regexpSource += '$'; + } + + var match = pathname.match(new RegExp('^' + regexpSource, 'i')); + if (match == null) { + return null; + } + + var matchedPath = match[0]; + var remainingPathname = pathname.substr(matchedPath.length); + + if (remainingPathname) { + // Require that the match ends at a path separator, if we didn't match + // the full path, so any remaining pathname is a new path segment. + if (matchedPath.charAt(matchedPath.length - 1) !== '/') { + return null; + } + + // If there is a remaining pathname, treat the path separator as part of + // the remaining pathname for properly continuing the match. + remainingPathname = '/' + remainingPathname; + } + + return { + remainingPathname: remainingPathname, + paramNames: paramNames, + paramValues: match.slice(1).map(function (v) { + return v && decodeURIComponent(v); + }) + }; +} + +function getParamNames(pattern) { + return compilePattern(pattern).paramNames; +} + +function getParams(pattern, pathname) { + var match = matchPattern(pattern, pathname); + if (!match) { + return null; + } + + var paramNames = match.paramNames; + var paramValues = match.paramValues; + + var params = {}; + + paramNames.forEach(function (paramName, index) { + params[paramName] = paramValues[index]; + }); + + return params; +} + +/** + * Returns a version of the given pattern with params interpolated. Throws + * if there is a dynamic segment of the pattern for which there is no param. + */ +function formatPattern(pattern, params) { + params = params || {}; + + var _compilePattern3 = compilePattern(pattern); + + var tokens = _compilePattern3.tokens; + + var parenCount = 0, + pathname = '', + splatIndex = 0; + + var token = void 0, + paramName = void 0, + paramValue = void 0; + for (var i = 0, len = tokens.length; i < len; ++i) { + token = tokens[i]; + + if (token === '*' || token === '**') { + paramValue = Array.isArray(params.splat) ? params.splat[splatIndex++] : params.splat; + + !(paramValue != null || parenCount > 0) ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'Missing splat #%s for path "%s"', splatIndex, pattern) : (0, _invariant2.default)(false) : void 0; + + if (paramValue != null) pathname += encodeURI(paramValue); + } else if (token === '(') { + parenCount += 1; + } else if (token === ')') { + parenCount -= 1; + } else if (token.charAt(0) === ':') { + paramName = token.substring(1); + paramValue = params[paramName]; + + !(paramValue != null || parenCount > 0) ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'Missing "%s" parameter for path "%s"', paramName, pattern) : (0, _invariant2.default)(false) : void 0; + + if (paramValue != null) pathname += encodeURIComponent(paramValue); + } else { + pathname += token; + } + } + + return pathname.replace(/\/+/g, '/'); +} +}).call(this,require('_process')) + +},{"_process":37,"invariant":25}],54:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; +exports.router = exports.routes = exports.route = exports.components = exports.component = exports.location = exports.history = exports.falsy = exports.locationShape = exports.routerShape = undefined; + +var _react = require('react'); + +var _deprecateObjectProperties = require('./deprecateObjectProperties'); + +var _deprecateObjectProperties2 = _interopRequireDefault(_deprecateObjectProperties); + +var _InternalPropTypes = require('./InternalPropTypes'); + +var InternalPropTypes = _interopRequireWildcard(_InternalPropTypes); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var func = _react.PropTypes.func; +var object = _react.PropTypes.object; +var shape = _react.PropTypes.shape; +var string = _react.PropTypes.string; +var routerShape = exports.routerShape = shape({ + push: func.isRequired, + replace: func.isRequired, + go: func.isRequired, + goBack: func.isRequired, + goForward: func.isRequired, + setRouteLeaveHook: func.isRequired, + isActive: func.isRequired +}); + +var locationShape = exports.locationShape = shape({ + pathname: string.isRequired, + search: string.isRequired, + state: object, + action: string.isRequired, + key: string +}); + +// Deprecated stuff below: + +var falsy = exports.falsy = InternalPropTypes.falsy; +var history = exports.history = InternalPropTypes.history; +var location = exports.location = locationShape; +var component = exports.component = InternalPropTypes.component; +var components = exports.components = InternalPropTypes.components; +var route = exports.route = InternalPropTypes.route; +var routes = exports.routes = InternalPropTypes.routes; +var router = exports.router = routerShape; + +if (process.env.NODE_ENV !== 'production') { + (function () { + var deprecatePropType = function deprecatePropType(propType, message) { + return function () { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, message) : void 0; + return propType.apply(undefined, arguments); + }; + }; + + var deprecateInternalPropType = function deprecateInternalPropType(propType) { + return deprecatePropType(propType, 'This prop type is not intended for external use, and was previously exported by mistake. These internal prop types are deprecated for external use, and will be removed in a later version.'); + }; + + var deprecateRenamedPropType = function deprecateRenamedPropType(propType, name) { + return deprecatePropType(propType, 'The `' + name + '` prop type is now exported as `' + name + 'Shape` to avoid name conflicts. This export is deprecated and will be removed in a later version.'); + }; + + exports.falsy = falsy = deprecateInternalPropType(falsy); + exports.history = history = deprecateInternalPropType(history); + exports.component = component = deprecateInternalPropType(component); + exports.components = components = deprecateInternalPropType(components); + exports.route = route = deprecateInternalPropType(route); + exports.routes = routes = deprecateInternalPropType(routes); + + exports.location = location = deprecateRenamedPropType(location, 'location'); + exports.router = router = deprecateRenamedPropType(router, 'router'); + })(); +} + +var defaultExport = { + falsy: falsy, + history: history, + location: location, + component: component, + components: components, + route: route, + // For some reason, routes was never here. + router: router +}; + +if (process.env.NODE_ENV !== 'production') { + defaultExport = (0, _deprecateObjectProperties2.default)(defaultExport, 'The default export from `react-router/lib/PropTypes` is deprecated. Please use the named exports instead.'); +} + +exports.default = defaultExport; +}).call(this,require('_process')) + +},{"./InternalPropTypes":50,"./deprecateObjectProperties":70,"./routerWarning":78,"_process":37,"react":"react"}],55:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _RouteUtils = require('./RouteUtils'); + +var _PatternUtils = require('./PatternUtils'); + +var _InternalPropTypes = require('./InternalPropTypes'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _React$PropTypes = _react2.default.PropTypes; +var string = _React$PropTypes.string; +var object = _React$PropTypes.object; + +/** + * A is used to declare another URL path a client should + * be sent to when they request a given URL. + * + * Redirects are placed alongside routes in the route configuration + * and are traversed in the same manner. + */ + +var Redirect = _react2.default.createClass({ + displayName: 'Redirect', + + + statics: { + createRouteFromReactElement: function createRouteFromReactElement(element) { + var route = (0, _RouteUtils.createRouteFromReactElement)(element); + + if (route.from) route.path = route.from; + + route.onEnter = function (nextState, replace) { + var location = nextState.location; + var params = nextState.params; + + + var pathname = void 0; + if (route.to.charAt(0) === '/') { + pathname = (0, _PatternUtils.formatPattern)(route.to, params); + } else if (!route.to) { + pathname = location.pathname; + } else { + var routeIndex = nextState.routes.indexOf(route); + var parentPattern = Redirect.getRoutePattern(nextState.routes, routeIndex - 1); + var pattern = parentPattern.replace(/\/*$/, '/') + route.to; + pathname = (0, _PatternUtils.formatPattern)(pattern, params); + } + + replace({ + pathname: pathname, + query: route.query || location.query, + state: route.state || location.state + }); + }; + + return route; + }, + getRoutePattern: function getRoutePattern(routes, routeIndex) { + var parentPattern = ''; + + for (var i = routeIndex; i >= 0; i--) { + var route = routes[i]; + var pattern = route.path || ''; + + parentPattern = pattern.replace(/\/*$/, '/') + parentPattern; + + if (pattern.indexOf('/') === 0) break; + } + + return '/' + parentPattern; + } + }, + + propTypes: { + path: string, + from: string, // Alias for path + to: string.isRequired, + query: object, + state: object, + onEnter: _InternalPropTypes.falsy, + children: _InternalPropTypes.falsy + }, + + /* istanbul ignore next: sanity check */ + render: function render() { + !false ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, ' elements are for router configuration only and should not be rendered') : (0, _invariant2.default)(false) : void 0; + } +}); + +exports.default = Redirect; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./InternalPropTypes":50,"./PatternUtils":53,"./RouteUtils":58,"_process":37,"invariant":25,"react":"react"}],56:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _RouteUtils = require('./RouteUtils'); + +var _InternalPropTypes = require('./InternalPropTypes'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _React$PropTypes = _react2.default.PropTypes; +var string = _React$PropTypes.string; +var func = _React$PropTypes.func; + +/** + * A is used to declare which components are rendered to the + * page when the URL matches a given pattern. + * + * Routes are arranged in a nested tree structure. When a new URL is + * requested, the tree is searched depth-first to find a route whose + * path matches the URL. When one is found, all routes in the tree + * that lead to it are considered "active" and their components are + * rendered into the DOM, nested in the same order as in the tree. + */ + +var Route = _react2.default.createClass({ + displayName: 'Route', + + + statics: { + createRouteFromReactElement: _RouteUtils.createRouteFromReactElement + }, + + propTypes: { + path: string, + component: _InternalPropTypes.component, + components: _InternalPropTypes.components, + getComponent: func, + getComponents: func + }, + + /* istanbul ignore next: sanity check */ + render: function render() { + !false ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, ' elements are for router configuration only and should not be rendered') : (0, _invariant2.default)(false) : void 0; + } +}); + +exports.default = Route; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./InternalPropTypes":50,"./RouteUtils":58,"_process":37,"invariant":25,"react":"react"}],57:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var object = _react2.default.PropTypes.object; + +/** + * The RouteContext mixin provides a convenient way for route + * components to set the route in context. This is needed for + * routes that render elements that want to use the Lifecycle + * mixin to prevent transitions. + */ + +var RouteContext = { + + propTypes: { + route: object.isRequired + }, + + childContextTypes: { + route: object.isRequired + }, + + getChildContext: function getChildContext() { + return { + route: this.props.route + }; + }, + componentWillMount: function componentWillMount() { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'The `RouteContext` mixin is deprecated. You can provide `this.props.route` on context with your own `contextTypes`. http://tiny.cc/router-routecontextmixin') : void 0; + } +}; + +exports.default = RouteContext; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./routerWarning":78,"_process":37,"react":"react"}],58:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +exports.isReactChildren = isReactChildren; +exports.createRouteFromReactElement = createRouteFromReactElement; +exports.createRoutesFromReactChildren = createRoutesFromReactChildren; +exports.createRoutes = createRoutes; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function isValidChild(object) { + return object == null || _react2.default.isValidElement(object); +} + +function isReactChildren(object) { + return isValidChild(object) || Array.isArray(object) && object.every(isValidChild); +} + +function createRoute(defaultProps, props) { + return _extends({}, defaultProps, props); +} + +function createRouteFromReactElement(element) { + var type = element.type; + var route = createRoute(type.defaultProps, element.props); + + if (route.children) { + var childRoutes = createRoutesFromReactChildren(route.children, route); + + if (childRoutes.length) route.childRoutes = childRoutes; + + delete route.children; + } + + return route; +} + +/** + * Creates and returns a routes object from the given ReactChildren. JSX + * provides a convenient way to visualize how routes in the hierarchy are + * nested. + * + * import { Route, createRoutesFromReactChildren } from 'react-router' + * + * const routes = createRoutesFromReactChildren( + * + * + * + * + * ) + * + * Note: This method is automatically used when you provide children + * to a component. + */ +function createRoutesFromReactChildren(children, parentRoute) { + var routes = []; + + _react2.default.Children.forEach(children, function (element) { + if (_react2.default.isValidElement(element)) { + // Component classes may have a static create* method. + if (element.type.createRouteFromReactElement) { + var route = element.type.createRouteFromReactElement(element, parentRoute); + + if (route) routes.push(route); + } else { + routes.push(createRouteFromReactElement(element)); + } + } + }); + + return routes; +} + +/** + * Creates and returns an array of routes from the given object which + * may be a JSX route, a plain object route, or an array of either. + */ +function createRoutes(routes) { + if (isReactChildren(routes)) { + routes = createRoutesFromReactChildren(routes); + } else if (routes && !Array.isArray(routes)) { + routes = [routes]; + } + + return routes; +} +},{"react":"react"}],59:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _createHashHistory = require('history/lib/createHashHistory'); + +var _createHashHistory2 = _interopRequireDefault(_createHashHistory); + +var _useQueries = require('history/lib/useQueries'); + +var _useQueries2 = _interopRequireDefault(_useQueries); + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _createTransitionManager = require('./createTransitionManager'); + +var _createTransitionManager2 = _interopRequireDefault(_createTransitionManager); + +var _InternalPropTypes = require('./InternalPropTypes'); + +var _RouterContext = require('./RouterContext'); + +var _RouterContext2 = _interopRequireDefault(_RouterContext); + +var _RouteUtils = require('./RouteUtils'); + +var _RouterUtils = require('./RouterUtils'); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +function isDeprecatedHistory(history) { + return !history || !history.__v2_compatible__; +} + +/* istanbul ignore next: sanity check */ +function isUnsupportedHistory(history) { + // v3 histories expose getCurrentLocation, but aren't currently supported. + return history && history.getCurrentLocation; +} + +var _React$PropTypes = _react2.default.PropTypes; +var func = _React$PropTypes.func; +var object = _React$PropTypes.object; + +/** + * A is a high-level API for automatically setting up + * a router that renders a with all the props + * it needs each time the URL changes. + */ + +var Router = _react2.default.createClass({ + displayName: 'Router', + + + propTypes: { + history: object, + children: _InternalPropTypes.routes, + routes: _InternalPropTypes.routes, // alias for children + render: func, + createElement: func, + onError: func, + onUpdate: func, + + // Deprecated: + parseQueryString: func, + stringifyQuery: func, + + // PRIVATE: For client-side rehydration of server match. + matchContext: object + }, + + getDefaultProps: function getDefaultProps() { + return { + render: function render(props) { + return _react2.default.createElement(_RouterContext2.default, props); + } + }; + }, + getInitialState: function getInitialState() { + return { + location: null, + routes: null, + params: null, + components: null + }; + }, + handleError: function handleError(error) { + if (this.props.onError) { + this.props.onError.call(this, error); + } else { + // Throw errors by default so we don't silently swallow them! + throw error; // This error probably occurred in getChildRoutes or getComponents. + } + }, + componentWillMount: function componentWillMount() { + var _this = this; + + var _props = this.props; + var parseQueryString = _props.parseQueryString; + var stringifyQuery = _props.stringifyQuery; + + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(!(parseQueryString || stringifyQuery), '`parseQueryString` and `stringifyQuery` are deprecated. Please create a custom history. http://tiny.cc/router-customquerystring') : void 0; + + var _createRouterObjects = this.createRouterObjects(); + + var history = _createRouterObjects.history; + var transitionManager = _createRouterObjects.transitionManager; + var router = _createRouterObjects.router; + + + this._unlisten = transitionManager.listen(function (error, state) { + if (error) { + _this.handleError(error); + } else { + _this.setState(state, _this.props.onUpdate); + } + }); + + this.history = history; + this.router = router; + }, + createRouterObjects: function createRouterObjects() { + var matchContext = this.props.matchContext; + + if (matchContext) { + return matchContext; + } + + var history = this.props.history; + var _props2 = this.props; + var routes = _props2.routes; + var children = _props2.children; + + + !!isUnsupportedHistory(history) ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'You have provided a history object created with history v3.x. ' + 'This version of React Router is not compatible with v3 history ' + 'objects. Please use history v2.x instead.') : (0, _invariant2.default)(false) : void 0; + + if (isDeprecatedHistory(history)) { + history = this.wrapDeprecatedHistory(history); + } + + var transitionManager = (0, _createTransitionManager2.default)(history, (0, _RouteUtils.createRoutes)(routes || children)); + var router = (0, _RouterUtils.createRouterObject)(history, transitionManager); + var routingHistory = (0, _RouterUtils.createRoutingHistory)(history, transitionManager); + + return { history: routingHistory, transitionManager: transitionManager, router: router }; + }, + wrapDeprecatedHistory: function wrapDeprecatedHistory(history) { + var _props3 = this.props; + var parseQueryString = _props3.parseQueryString; + var stringifyQuery = _props3.stringifyQuery; + + + var createHistory = void 0; + if (history) { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'It appears you have provided a deprecated history object to ``, please use a history provided by ' + 'React Router with `import { browserHistory } from \'react-router\'` or `import { hashHistory } from \'react-router\'`. ' + 'If you are using a custom history please create it with `useRouterHistory`, see http://tiny.cc/router-usinghistory for details.') : void 0; + createHistory = function createHistory() { + return history; + }; + } else { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, '`Router` no longer defaults the history prop to hash history. Please use the `hashHistory` singleton instead. http://tiny.cc/router-defaulthistory') : void 0; + createHistory = _createHashHistory2.default; + } + + return (0, _useQueries2.default)(createHistory)({ parseQueryString: parseQueryString, stringifyQuery: stringifyQuery }); + }, + + + /* istanbul ignore next: sanity check */ + componentWillReceiveProps: function componentWillReceiveProps(nextProps) { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(nextProps.history === this.props.history, 'You cannot change ; it will be ignored') : void 0; + + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)((nextProps.routes || nextProps.children) === (this.props.routes || this.props.children), 'You cannot change ; it will be ignored') : void 0; + }, + componentWillUnmount: function componentWillUnmount() { + if (this._unlisten) this._unlisten(); + }, + render: function render() { + var _state = this.state; + var location = _state.location; + var routes = _state.routes; + var params = _state.params; + var components = _state.components; + var _props4 = this.props; + var createElement = _props4.createElement; + var render = _props4.render; + + var props = _objectWithoutProperties(_props4, ['createElement', 'render']); + + if (location == null) return null; // Async match + + // Only forward non-Router-specific props to routing context, as those are + // the only ones that might be custom routing context props. + Object.keys(Router.propTypes).forEach(function (propType) { + return delete props[propType]; + }); + + return render(_extends({}, props, { + history: this.history, + router: this.router, + location: location, + routes: routes, + params: params, + components: components, + createElement: createElement + })); + } +}); + +exports.default = Router; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./InternalPropTypes":50,"./RouteUtils":58,"./RouterContext":60,"./RouterUtils":61,"./createTransitionManager":69,"./routerWarning":78,"_process":37,"history/lib/createHashHistory":15,"history/lib/useQueries":22,"invariant":25,"react":"react"}],60:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; + +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 _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _deprecateObjectProperties = require('./deprecateObjectProperties'); + +var _deprecateObjectProperties2 = _interopRequireDefault(_deprecateObjectProperties); + +var _getRouteParams = require('./getRouteParams'); + +var _getRouteParams2 = _interopRequireDefault(_getRouteParams); + +var _RouteUtils = require('./RouteUtils'); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _React$PropTypes = _react2.default.PropTypes; +var array = _React$PropTypes.array; +var func = _React$PropTypes.func; +var object = _React$PropTypes.object; + +/** + * A renders the component tree for a given router state + * and sets the history object and the current location in context. + */ + +var RouterContext = _react2.default.createClass({ + displayName: 'RouterContext', + + + propTypes: { + history: object, + router: object.isRequired, + location: object.isRequired, + routes: array.isRequired, + params: object.isRequired, + components: array.isRequired, + createElement: func.isRequired + }, + + getDefaultProps: function getDefaultProps() { + return { + createElement: _react2.default.createElement + }; + }, + + + childContextTypes: { + history: object, + location: object.isRequired, + router: object.isRequired + }, + + getChildContext: function getChildContext() { + var _props = this.props; + var router = _props.router; + var history = _props.history; + var location = _props.location; + + if (!router) { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, '`` expects a `router` rather than a `history`') : void 0; + + router = _extends({}, history, { + setRouteLeaveHook: history.listenBeforeLeavingRoute + }); + delete router.listenBeforeLeavingRoute; + } + + if (process.env.NODE_ENV !== 'production') { + location = (0, _deprecateObjectProperties2.default)(location, '`context.location` is deprecated, please use a route component\'s `props.location` instead. http://tiny.cc/router-accessinglocation'); + } + + return { history: history, location: location, router: router }; + }, + createElement: function createElement(component, props) { + return component == null ? null : this.props.createElement(component, props); + }, + render: function render() { + var _this = this; + + var _props2 = this.props; + var history = _props2.history; + var location = _props2.location; + var routes = _props2.routes; + var params = _props2.params; + var components = _props2.components; + + var element = null; + + if (components) { + element = components.reduceRight(function (element, components, index) { + if (components == null) return element; // Don't create new children; use the grandchildren. + + var route = routes[index]; + var routeParams = (0, _getRouteParams2.default)(route, params); + var props = { + history: history, + location: location, + params: params, + route: route, + routeParams: routeParams, + routes: routes + }; + + if ((0, _RouteUtils.isReactChildren)(element)) { + props.children = element; + } else if (element) { + for (var prop in element) { + if (Object.prototype.hasOwnProperty.call(element, prop)) props[prop] = element[prop]; + } + } + + if ((typeof components === 'undefined' ? 'undefined' : _typeof(components)) === 'object') { + var elements = {}; + + for (var key in components) { + if (Object.prototype.hasOwnProperty.call(components, key)) { + // Pass through the key as a prop to createElement to allow + // custom createElement functions to know which named component + // they're rendering, for e.g. matching up to fetched data. + elements[key] = _this.createElement(components[key], _extends({ + key: key }, props)); + } + } + + return elements; + } + + return _this.createElement(components, props); + }, element); + } + + !(element === null || element === false || _react2.default.isValidElement(element)) ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'The root route must render a single element') : (0, _invariant2.default)(false) : void 0; + + return element; + } +}); + +exports.default = RouterContext; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./RouteUtils":58,"./deprecateObjectProperties":70,"./getRouteParams":72,"./routerWarning":78,"_process":37,"invariant":25,"react":"react"}],61:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +exports.createRouterObject = createRouterObject; +exports.createRoutingHistory = createRoutingHistory; + +var _deprecateObjectProperties = require('./deprecateObjectProperties'); + +var _deprecateObjectProperties2 = _interopRequireDefault(_deprecateObjectProperties); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createRouterObject(history, transitionManager) { + return _extends({}, history, { + setRouteLeaveHook: transitionManager.listenBeforeLeavingRoute, + isActive: transitionManager.isActive + }); +} + +// deprecated +function createRoutingHistory(history, transitionManager) { + history = _extends({}, history, transitionManager); + + if (process.env.NODE_ENV !== 'production') { + history = (0, _deprecateObjectProperties2.default)(history, '`props.history` and `context.history` are deprecated. Please use `context.router`. http://tiny.cc/router-contextchanges'); + } + + return history; +} +}).call(this,require('_process')) + +},{"./deprecateObjectProperties":70,"_process":37}],62:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _RouterContext = require('./RouterContext'); + +var _RouterContext2 = _interopRequireDefault(_RouterContext); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var RoutingContext = _react2.default.createClass({ + displayName: 'RoutingContext', + componentWillMount: function componentWillMount() { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, '`RoutingContext` has been renamed to `RouterContext`. Please use `import { RouterContext } from \'react-router\'`. http://tiny.cc/router-routercontext') : void 0; + }, + render: function render() { + return _react2.default.createElement(_RouterContext2.default, this.props); + } +}); + +exports.default = RoutingContext; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./RouterContext":60,"./routerWarning":78,"_process":37,"react":"react"}],63:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; +exports.runEnterHooks = runEnterHooks; +exports.runChangeHooks = runChangeHooks; +exports.runLeaveHooks = runLeaveHooks; + +var _AsyncUtils = require('./AsyncUtils'); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createTransitionHook(hook, route, asyncArity) { + return function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + hook.apply(route, args); + + if (hook.length < asyncArity) { + var callback = args[args.length - 1]; + // Assume hook executes synchronously and + // automatically call the callback. + callback(); + } + }; +} + +function getEnterHooks(routes) { + return routes.reduce(function (hooks, route) { + if (route.onEnter) hooks.push(createTransitionHook(route.onEnter, route, 3)); + + return hooks; + }, []); +} + +function getChangeHooks(routes) { + return routes.reduce(function (hooks, route) { + if (route.onChange) hooks.push(createTransitionHook(route.onChange, route, 4)); + return hooks; + }, []); +} + +function runTransitionHooks(length, iter, callback) { + if (!length) { + callback(); + return; + } + + var redirectInfo = void 0; + function replace(location, deprecatedPathname, deprecatedQuery) { + if (deprecatedPathname) { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, '`replaceState(state, pathname, query) is deprecated; use `replace(location)` with a location descriptor instead. http://tiny.cc/router-isActivedeprecated') : void 0; + redirectInfo = { + pathname: deprecatedPathname, + query: deprecatedQuery, + state: location + }; + + return; + } + + redirectInfo = location; + } + + (0, _AsyncUtils.loopAsync)(length, function (index, next, done) { + iter(index, replace, function (error) { + if (error || redirectInfo) { + done(error, redirectInfo); // No need to continue. + } else { + next(); + } + }); + }, callback); +} + +/** + * Runs all onEnter hooks in the given array of routes in order + * with onEnter(nextState, replace, callback) and calls + * callback(error, redirectInfo) when finished. The first hook + * to use replace short-circuits the loop. + * + * If a hook needs to run asynchronously, it may use the callback + * function. However, doing so will cause the transition to pause, + * which could lead to a non-responsive UI if the hook is slow. + */ +function runEnterHooks(routes, nextState, callback) { + var hooks = getEnterHooks(routes); + return runTransitionHooks(hooks.length, function (index, replace, next) { + hooks[index](nextState, replace, next); + }, callback); +} + +/** + * Runs all onChange hooks in the given array of routes in order + * with onChange(prevState, nextState, replace, callback) and calls + * callback(error, redirectInfo) when finished. The first hook + * to use replace short-circuits the loop. + * + * If a hook needs to run asynchronously, it may use the callback + * function. However, doing so will cause the transition to pause, + * which could lead to a non-responsive UI if the hook is slow. + */ +function runChangeHooks(routes, state, nextState, callback) { + var hooks = getChangeHooks(routes); + return runTransitionHooks(hooks.length, function (index, replace, next) { + hooks[index](state, nextState, replace, next); + }, callback); +} + +/** + * Runs all onLeave hooks in the given array of routes in order. + */ +function runLeaveHooks(routes, prevState) { + for (var i = 0, len = routes.length; i < len; ++i) { + if (routes[i].onLeave) routes[i].onLeave.call(routes[i], prevState); + } +} +}).call(this,require('_process')) + +},{"./AsyncUtils":45,"./routerWarning":78,"_process":37}],64:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _RouterContext = require('./RouterContext'); + +var _RouterContext2 = _interopRequireDefault(_RouterContext); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function () { + for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) { + middlewares[_key] = arguments[_key]; + } + + var withContext = middlewares.map(function (m) { + return m.renderRouterContext; + }).filter(function (f) { + return f; + }); + var withComponent = middlewares.map(function (m) { + return m.renderRouteComponent; + }).filter(function (f) { + return f; + }); + var makeCreateElement = function makeCreateElement() { + var baseCreateElement = arguments.length <= 0 || arguments[0] === undefined ? _react.createElement : arguments[0]; + return function (Component, props) { + return withComponent.reduceRight(function (previous, renderRouteComponent) { + return renderRouteComponent(previous, props); + }, baseCreateElement(Component, props)); + }; + }; + + return function (renderProps) { + return withContext.reduceRight(function (previous, renderRouterContext) { + return renderRouterContext(previous, renderProps); + }, _react2.default.createElement(_RouterContext2.default, _extends({}, renderProps, { + createElement: makeCreateElement(renderProps.createElement) + }))); + }; +}; + +module.exports = exports['default']; +},{"./RouterContext":60,"react":"react"}],65:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _createBrowserHistory = require('history/lib/createBrowserHistory'); + +var _createBrowserHistory2 = _interopRequireDefault(_createBrowserHistory); + +var _createRouterHistory = require('./createRouterHistory'); + +var _createRouterHistory2 = _interopRequireDefault(_createRouterHistory); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = (0, _createRouterHistory2.default)(_createBrowserHistory2.default); +module.exports = exports['default']; +},{"./createRouterHistory":68,"history/lib/createBrowserHistory":13}],66:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _PatternUtils = require('./PatternUtils'); + +function routeParamsChanged(route, prevState, nextState) { + if (!route.path) return false; + + var paramNames = (0, _PatternUtils.getParamNames)(route.path); + + return paramNames.some(function (paramName) { + return prevState.params[paramName] !== nextState.params[paramName]; + }); +} + +/** + * Returns an object of { leaveRoutes, changeRoutes, enterRoutes } determined by + * the change from prevState to nextState. We leave routes if either + * 1) they are not in the next state or 2) they are in the next state + * but their params have changed (i.e. /users/123 => /users/456). + * + * leaveRoutes are ordered starting at the leaf route of the tree + * we're leaving up to the common parent route. enterRoutes are ordered + * from the top of the tree we're entering down to the leaf route. + * + * changeRoutes are any routes that didn't leave or enter during + * the transition. + */ +function computeChangedRoutes(prevState, nextState) { + var prevRoutes = prevState && prevState.routes; + var nextRoutes = nextState.routes; + + var leaveRoutes = void 0, + changeRoutes = void 0, + enterRoutes = void 0; + if (prevRoutes) { + (function () { + var parentIsLeaving = false; + leaveRoutes = prevRoutes.filter(function (route) { + if (parentIsLeaving) { + return true; + } else { + var isLeaving = nextRoutes.indexOf(route) === -1 || routeParamsChanged(route, prevState, nextState); + if (isLeaving) parentIsLeaving = true; + return isLeaving; + } + }); + + // onLeave hooks start at the leaf route. + leaveRoutes.reverse(); + + enterRoutes = []; + changeRoutes = []; + + nextRoutes.forEach(function (route) { + var isNew = prevRoutes.indexOf(route) === -1; + var paramsChanged = leaveRoutes.indexOf(route) !== -1; + + if (isNew || paramsChanged) enterRoutes.push(route);else changeRoutes.push(route); + }); + })(); + } else { + leaveRoutes = []; + changeRoutes = []; + enterRoutes = nextRoutes; + } + + return { + leaveRoutes: leaveRoutes, + changeRoutes: changeRoutes, + enterRoutes: enterRoutes + }; +} + +exports.default = computeChangedRoutes; +module.exports = exports['default']; +},{"./PatternUtils":53}],67:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; +exports.default = createMemoryHistory; + +var _useQueries = require('history/lib/useQueries'); + +var _useQueries2 = _interopRequireDefault(_useQueries); + +var _useBasename = require('history/lib/useBasename'); + +var _useBasename2 = _interopRequireDefault(_useBasename); + +var _createMemoryHistory = require('history/lib/createMemoryHistory'); + +var _createMemoryHistory2 = _interopRequireDefault(_createMemoryHistory); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createMemoryHistory(options) { + // signatures and type checking differ between `useRoutes` and + // `createMemoryHistory`, have to create `memoryHistory` first because + // `useQueries` doesn't understand the signature + var memoryHistory = (0, _createMemoryHistory2.default)(options); + var createHistory = function createHistory() { + return memoryHistory; + }; + var history = (0, _useQueries2.default)((0, _useBasename2.default)(createHistory))(options); + history.__v2_compatible__ = true; + return history; +} +module.exports = exports['default']; +},{"history/lib/createMemoryHistory":18,"history/lib/useBasename":21,"history/lib/useQueries":22}],68:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +exports.default = function (createHistory) { + var history = void 0; + if (canUseDOM) history = (0, _useRouterHistory2.default)(createHistory)(); + return history; +}; + +var _useRouterHistory = require('./useRouterHistory'); + +var _useRouterHistory2 = _interopRequireDefault(_useRouterHistory); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); + +module.exports = exports['default']; +},{"./useRouterHistory":79}],69:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +exports.default = createTransitionManager; + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +var _Actions = require('history/lib/Actions'); + +var _computeChangedRoutes2 = require('./computeChangedRoutes'); + +var _computeChangedRoutes3 = _interopRequireDefault(_computeChangedRoutes2); + +var _TransitionUtils = require('./TransitionUtils'); + +var _isActive2 = require('./isActive'); + +var _isActive3 = _interopRequireDefault(_isActive2); + +var _getComponents = require('./getComponents'); + +var _getComponents2 = _interopRequireDefault(_getComponents); + +var _matchRoutes = require('./matchRoutes'); + +var _matchRoutes2 = _interopRequireDefault(_matchRoutes); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function hasAnyProperties(object) { + for (var p in object) { + if (Object.prototype.hasOwnProperty.call(object, p)) return true; + }return false; +} + +function createTransitionManager(history, routes) { + var state = {}; + + // Signature should be (location, indexOnly), but needs to support (path, + // query, indexOnly) + function isActive(location) { + var indexOnlyOrDeprecatedQuery = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; + var deprecatedIndexOnly = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; + + var indexOnly = void 0; + if (indexOnlyOrDeprecatedQuery && indexOnlyOrDeprecatedQuery !== true || deprecatedIndexOnly !== null) { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, '`isActive(pathname, query, indexOnly) is deprecated; use `isActive(location, indexOnly)` with a location descriptor instead. http://tiny.cc/router-isActivedeprecated') : void 0; + location = { pathname: location, query: indexOnlyOrDeprecatedQuery }; + indexOnly = deprecatedIndexOnly || false; + } else { + location = history.createLocation(location); + indexOnly = indexOnlyOrDeprecatedQuery; + } + + return (0, _isActive3.default)(location, indexOnly, state.location, state.routes, state.params); + } + + function createLocationFromRedirectInfo(location) { + return history.createLocation(location, _Actions.REPLACE); + } + + var partialNextState = void 0; + + function match(location, callback) { + if (partialNextState && partialNextState.location === location) { + // Continue from where we left off. + finishMatch(partialNextState, callback); + } else { + (0, _matchRoutes2.default)(routes, location, function (error, nextState) { + if (error) { + callback(error); + } else if (nextState) { + finishMatch(_extends({}, nextState, { location: location }), callback); + } else { + callback(); + } + }); + } + } + + function finishMatch(nextState, callback) { + var _computeChangedRoutes = (0, _computeChangedRoutes3.default)(state, nextState); + + var leaveRoutes = _computeChangedRoutes.leaveRoutes; + var changeRoutes = _computeChangedRoutes.changeRoutes; + var enterRoutes = _computeChangedRoutes.enterRoutes; + + + (0, _TransitionUtils.runLeaveHooks)(leaveRoutes, state); + + // Tear down confirmation hooks for left routes + leaveRoutes.filter(function (route) { + return enterRoutes.indexOf(route) === -1; + }).forEach(removeListenBeforeHooksForRoute); + + // change and enter hooks are run in series + (0, _TransitionUtils.runChangeHooks)(changeRoutes, state, nextState, function (error, redirectInfo) { + if (error || redirectInfo) return handleErrorOrRedirect(error, redirectInfo); + + (0, _TransitionUtils.runEnterHooks)(enterRoutes, nextState, finishEnterHooks); + }); + + function finishEnterHooks(error, redirectInfo) { + if (error || redirectInfo) return handleErrorOrRedirect(error, redirectInfo); + + // TODO: Fetch components after state is updated. + (0, _getComponents2.default)(nextState, function (error, components) { + if (error) { + callback(error); + } else { + // TODO: Make match a pure function and have some other API + // for "match and update state". + callback(null, null, state = _extends({}, nextState, { components: components })); + } + }); + } + + function handleErrorOrRedirect(error, redirectInfo) { + if (error) callback(error);else callback(null, createLocationFromRedirectInfo(redirectInfo)); + } + } + + var RouteGuid = 1; + + function getRouteID(route) { + var create = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; + + return route.__id__ || create && (route.__id__ = RouteGuid++); + } + + var RouteHooks = Object.create(null); + + function getRouteHooksForRoutes(routes) { + return routes.reduce(function (hooks, route) { + hooks.push.apply(hooks, RouteHooks[getRouteID(route)]); + return hooks; + }, []); + } + + function transitionHook(location, callback) { + (0, _matchRoutes2.default)(routes, location, function (error, nextState) { + if (nextState == null) { + // TODO: We didn't actually match anything, but hang + // onto error/nextState so we don't have to matchRoutes + // again in the listen callback. + callback(); + return; + } + + // Cache some state here so we don't have to + // matchRoutes() again in the listen callback. + partialNextState = _extends({}, nextState, { location: location }); + + var hooks = getRouteHooksForRoutes((0, _computeChangedRoutes3.default)(state, partialNextState).leaveRoutes); + + var result = void 0; + for (var i = 0, len = hooks.length; result == null && i < len; ++i) { + // Passing the location arg here indicates to + // the user that this is a transition hook. + result = hooks[i](location); + } + + callback(result); + }); + } + + /* istanbul ignore next: untestable with Karma */ + function beforeUnloadHook() { + // Synchronously check to see if any route hooks want + // to prevent the current window/tab from closing. + if (state.routes) { + var hooks = getRouteHooksForRoutes(state.routes); + + var message = void 0; + for (var i = 0, len = hooks.length; typeof message !== 'string' && i < len; ++i) { + // Passing no args indicates to the user that this is a + // beforeunload hook. We don't know the next location. + message = hooks[i](); + } + + return message; + } + } + + var unlistenBefore = void 0, + unlistenBeforeUnload = void 0; + + function removeListenBeforeHooksForRoute(route) { + var routeID = getRouteID(route, false); + if (!routeID) { + return; + } + + delete RouteHooks[routeID]; + + if (!hasAnyProperties(RouteHooks)) { + // teardown transition & beforeunload hooks + if (unlistenBefore) { + unlistenBefore(); + unlistenBefore = null; + } + + if (unlistenBeforeUnload) { + unlistenBeforeUnload(); + unlistenBeforeUnload = null; + } + } + } + + /** + * Registers the given hook function to run before leaving the given route. + * + * During a normal transition, the hook function receives the next location + * as its only argument and can return either a prompt message (string) to show the user, + * to make sure they want to leave the page; or `false`, to prevent the transition. + * Any other return value will have no effect. + * + * During the beforeunload event (in browsers) the hook receives no arguments. + * In this case it must return a prompt message to prevent the transition. + * + * Returns a function that may be used to unbind the listener. + */ + function listenBeforeLeavingRoute(route, hook) { + // TODO: Warn if they register for a route that isn't currently + // active. They're probably doing something wrong, like re-creating + // route objects on every location change. + var routeID = getRouteID(route); + var hooks = RouteHooks[routeID]; + + if (!hooks) { + var thereWereNoRouteHooks = !hasAnyProperties(RouteHooks); + + RouteHooks[routeID] = [hook]; + + if (thereWereNoRouteHooks) { + // setup transition & beforeunload hooks + unlistenBefore = history.listenBefore(transitionHook); + + if (history.listenBeforeUnload) unlistenBeforeUnload = history.listenBeforeUnload(beforeUnloadHook); + } + } else { + if (hooks.indexOf(hook) === -1) { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'adding multiple leave hooks for the same route is deprecated; manage multiple confirmations in your own code instead') : void 0; + + hooks.push(hook); + } + } + + return function () { + var hooks = RouteHooks[routeID]; + + if (hooks) { + var newHooks = hooks.filter(function (item) { + return item !== hook; + }); + + if (newHooks.length === 0) { + removeListenBeforeHooksForRoute(route); + } else { + RouteHooks[routeID] = newHooks; + } + } + }; + } + + /** + * This is the API for stateful environments. As the location + * changes, we update state and call the listener. We can also + * gracefully handle errors and redirects. + */ + function listen(listener) { + // TODO: Only use a single history listener. Otherwise we'll + // end up with multiple concurrent calls to match. + return history.listen(function (location) { + if (state.location === location) { + listener(null, state); + } else { + match(location, function (error, redirectLocation, nextState) { + if (error) { + listener(error); + } else if (redirectLocation) { + history.transitionTo(redirectLocation); + } else if (nextState) { + listener(null, nextState); + } else { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'Location "%s" did not match any routes', location.pathname + location.search + location.hash) : void 0; + } + }); + } + }); + } + + return { + isActive: isActive, + match: match, + listenBeforeLeavingRoute: listenBeforeLeavingRoute, + listen: listen + }; +} + +//export default useRoutes + +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./TransitionUtils":63,"./computeChangedRoutes":66,"./getComponents":71,"./isActive":74,"./matchRoutes":77,"./routerWarning":78,"_process":37,"history/lib/Actions":7}],70:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; +exports.canUseMembrane = undefined; + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var canUseMembrane = exports.canUseMembrane = false; + +// No-op by default. +var deprecateObjectProperties = function deprecateObjectProperties(object) { + return object; +}; + +if (process.env.NODE_ENV !== 'production') { + try { + if (Object.defineProperty({}, 'x', { + get: function get() { + return true; + } + }).x) { + exports.canUseMembrane = canUseMembrane = true; + } + /* eslint-disable no-empty */ + } catch (e) {} + /* eslint-enable no-empty */ + + if (canUseMembrane) { + deprecateObjectProperties = function deprecateObjectProperties(object, message) { + // Wrap the deprecated object in a membrane to warn on property access. + var membrane = {}; + + var _loop = function _loop(prop) { + if (!Object.prototype.hasOwnProperty.call(object, prop)) { + return 'continue'; + } + + if (typeof object[prop] === 'function') { + // Can't use fat arrow here because of use of arguments below. + membrane[prop] = function () { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, message) : void 0; + return object[prop].apply(object, arguments); + }; + return 'continue'; + } + + // These properties are non-enumerable to prevent React dev tools from + // seeing them and causing spurious warnings when accessing them. In + // principle this could be done with a proxy, but support for the + // ownKeys trap on proxies is not universal, even among browsers that + // otherwise support proxies. + Object.defineProperty(membrane, prop, { + get: function get() { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, message) : void 0; + return object[prop]; + } + }); + }; + + for (var prop in object) { + var _ret = _loop(prop); + + if (_ret === 'continue') continue; + } + + return membrane; + }; + } +} + +exports.default = deprecateObjectProperties; +}).call(this,require('_process')) + +},{"./routerWarning":78,"_process":37}],71:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _AsyncUtils = require('./AsyncUtils'); + +var _makeStateWithLocation = require('./makeStateWithLocation'); + +var _makeStateWithLocation2 = _interopRequireDefault(_makeStateWithLocation); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getComponentsForRoute(nextState, route, callback) { + if (route.component || route.components) { + callback(null, route.component || route.components); + return; + } + + var getComponent = route.getComponent || route.getComponents; + if (!getComponent) { + callback(); + return; + } + + var location = nextState.location; + + var nextStateWithLocation = (0, _makeStateWithLocation2.default)(nextState, location); + + getComponent.call(route, nextStateWithLocation, callback); +} + +/** + * Asynchronously fetches all components needed for the given router + * state and calls callback(error, components) when finished. + * + * Note: This operation may finish synchronously if no routes have an + * asynchronous getComponents method. + */ +function getComponents(nextState, callback) { + (0, _AsyncUtils.mapAsync)(nextState.routes, function (route, index, callback) { + getComponentsForRoute(nextState, route, callback); + }, callback); +} + +exports.default = getComponents; +module.exports = exports['default']; +},{"./AsyncUtils":45,"./makeStateWithLocation":75}],72:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _PatternUtils = require('./PatternUtils'); + +/** + * Extracts an object of params the given route cares about from + * the given params object. + */ +function getRouteParams(route, params) { + var routeParams = {}; + + if (!route.path) return routeParams; + + (0, _PatternUtils.getParamNames)(route.path).forEach(function (p) { + if (Object.prototype.hasOwnProperty.call(params, p)) { + routeParams[p] = params[p]; + } + }); + + return routeParams; +} + +exports.default = getRouteParams; +module.exports = exports['default']; +},{"./PatternUtils":53}],73:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _createHashHistory = require('history/lib/createHashHistory'); + +var _createHashHistory2 = _interopRequireDefault(_createHashHistory); + +var _createRouterHistory = require('./createRouterHistory'); + +var _createRouterHistory2 = _interopRequireDefault(_createRouterHistory); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = (0, _createRouterHistory2.default)(_createHashHistory2.default); +module.exports = exports['default']; +},{"./createRouterHistory":68,"history/lib/createHashHistory":15}],74:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; + +exports.default = isActive; + +var _PatternUtils = require('./PatternUtils'); + +function deepEqual(a, b) { + if (a == b) return true; + + if (a == null || b == null) return false; + + if (Array.isArray(a)) { + return Array.isArray(b) && a.length === b.length && a.every(function (item, index) { + return deepEqual(item, b[index]); + }); + } + + if ((typeof a === 'undefined' ? 'undefined' : _typeof(a)) === 'object') { + for (var p in a) { + if (!Object.prototype.hasOwnProperty.call(a, p)) { + continue; + } + + if (a[p] === undefined) { + if (b[p] !== undefined) { + return false; + } + } else if (!Object.prototype.hasOwnProperty.call(b, p)) { + return false; + } else if (!deepEqual(a[p], b[p])) { + return false; + } + } + + return true; + } + + return String(a) === String(b); +} + +/** + * Returns true if the current pathname matches the supplied one, net of + * leading and trailing slash normalization. This is sufficient for an + * indexOnly route match. + */ +function pathIsActive(pathname, currentPathname) { + // Normalize leading slash for consistency. Leading slash on pathname has + // already been normalized in isActive. See caveat there. + if (currentPathname.charAt(0) !== '/') { + currentPathname = '/' + currentPathname; + } + + // Normalize the end of both path names too. Maybe `/foo/` shouldn't show + // `/foo` as active, but in this case, we would already have failed the + // match. + if (pathname.charAt(pathname.length - 1) !== '/') { + pathname += '/'; + } + if (currentPathname.charAt(currentPathname.length - 1) !== '/') { + currentPathname += '/'; + } + + return currentPathname === pathname; +} + +/** + * Returns true if the given pathname matches the active routes and params. + */ +function routeIsActive(pathname, routes, params) { + var remainingPathname = pathname, + paramNames = [], + paramValues = []; + + // for...of would work here but it's probably slower post-transpilation. + for (var i = 0, len = routes.length; i < len; ++i) { + var route = routes[i]; + var pattern = route.path || ''; + + if (pattern.charAt(0) === '/') { + remainingPathname = pathname; + paramNames = []; + paramValues = []; + } + + if (remainingPathname !== null && pattern) { + var matched = (0, _PatternUtils.matchPattern)(pattern, remainingPathname); + if (matched) { + remainingPathname = matched.remainingPathname; + paramNames = [].concat(paramNames, matched.paramNames); + paramValues = [].concat(paramValues, matched.paramValues); + } else { + remainingPathname = null; + } + + if (remainingPathname === '') { + // We have an exact match on the route. Just check that all the params + // match. + // FIXME: This doesn't work on repeated params. + return paramNames.every(function (paramName, index) { + return String(paramValues[index]) === String(params[paramName]); + }); + } + } + } + + return false; +} + +/** + * Returns true if all key/value pairs in the given query are + * currently active. + */ +function queryIsActive(query, activeQuery) { + if (activeQuery == null) return query == null; + + if (query == null) return true; + + return deepEqual(query, activeQuery); +} + +/** + * Returns true if a to the given pathname/query combination is + * currently active. + */ +function isActive(_ref, indexOnly, currentLocation, routes, params) { + var pathname = _ref.pathname; + var query = _ref.query; + + if (currentLocation == null) return false; + + // TODO: This is a bit ugly. It keeps around support for treating pathnames + // without preceding slashes as absolute paths, but possibly also works + // around the same quirks with basenames as in matchRoutes. + if (pathname.charAt(0) !== '/') { + pathname = '/' + pathname; + } + + if (!pathIsActive(pathname, currentLocation.pathname)) { + // The path check is necessary and sufficient for indexOnly, but otherwise + // we still need to check the routes. + if (indexOnly || !routeIsActive(pathname, routes, params)) { + return false; + } + } + + return queryIsActive(query, currentLocation.query); +} +module.exports = exports['default']; +},{"./PatternUtils":53}],75:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +exports.default = makeStateWithLocation; + +var _deprecateObjectProperties = require('./deprecateObjectProperties'); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function makeStateWithLocation(state, location) { + if (process.env.NODE_ENV !== 'production' && _deprecateObjectProperties.canUseMembrane) { + var stateWithLocation = _extends({}, state); + + // I don't use deprecateObjectProperties here because I want to keep the + // same code path between development and production, in that we just + // assign extra properties to the copy of the state object in both cases. + + var _loop = function _loop(prop) { + if (!Object.prototype.hasOwnProperty.call(location, prop)) { + return 'continue'; + } + + Object.defineProperty(stateWithLocation, prop, { + get: function get() { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, 'Accessing location properties directly from the first argument to `getComponent`, `getComponents`, `getChildRoutes`, and `getIndexRoute` is deprecated. That argument is now the router state (`nextState` or `partialNextState`) rather than the location. To access the location, use `nextState.location` or `partialNextState.location`.') : void 0; + return location[prop]; + } + }); + }; + + for (var prop in location) { + var _ret = _loop(prop); + + if (_ret === 'continue') continue; + } + + return stateWithLocation; + } + + return _extends({}, state, location); +} +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./deprecateObjectProperties":70,"./routerWarning":78,"_process":37}],76:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _invariant = require('invariant'); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _createMemoryHistory = require('./createMemoryHistory'); + +var _createMemoryHistory2 = _interopRequireDefault(_createMemoryHistory); + +var _createTransitionManager = require('./createTransitionManager'); + +var _createTransitionManager2 = _interopRequireDefault(_createTransitionManager); + +var _RouteUtils = require('./RouteUtils'); + +var _RouterUtils = require('./RouterUtils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +/** + * A high-level API to be used for server-side rendering. + * + * This function matches a location to a set of routes and calls + * callback(error, redirectLocation, renderProps) when finished. + * + * Note: You probably don't want to use this in a browser unless you're using + * server-side rendering with async routes. + */ +function match(_ref, callback) { + var history = _ref.history; + var routes = _ref.routes; + var location = _ref.location; + + var options = _objectWithoutProperties(_ref, ['history', 'routes', 'location']); + + !(history || location) ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'match needs a history or a location') : (0, _invariant2.default)(false) : void 0; + + history = history ? history : (0, _createMemoryHistory2.default)(options); + var transitionManager = (0, _createTransitionManager2.default)(history, (0, _RouteUtils.createRoutes)(routes)); + + var unlisten = void 0; + + if (location) { + // Allow match({ location: '/the/path', ... }) + location = history.createLocation(location); + } else { + // Pick up the location from the history via synchronous history.listen + // call if needed. + unlisten = history.listen(function (historyLocation) { + location = historyLocation; + }); + } + + var router = (0, _RouterUtils.createRouterObject)(history, transitionManager); + history = (0, _RouterUtils.createRoutingHistory)(history, transitionManager); + + transitionManager.match(location, function (error, redirectLocation, nextState) { + callback(error, redirectLocation, nextState && _extends({}, nextState, { + history: history, + router: router, + matchContext: { history: history, transitionManager: transitionManager, router: router } + })); + + // Defer removing the listener to here to prevent DOM histories from having + // to unwind DOM event listeners unnecessarily, in case callback renders a + // and attaches another history listener. + if (unlisten) { + unlisten(); + } + }); +} + +exports.default = match; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./RouteUtils":58,"./RouterUtils":61,"./createMemoryHistory":67,"./createTransitionManager":69,"_process":37,"invariant":25}],77:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; + +exports.default = matchRoutes; + +var _AsyncUtils = require('./AsyncUtils'); + +var _makeStateWithLocation = require('./makeStateWithLocation'); + +var _makeStateWithLocation2 = _interopRequireDefault(_makeStateWithLocation); + +var _PatternUtils = require('./PatternUtils'); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +var _RouteUtils = require('./RouteUtils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getChildRoutes(route, location, paramNames, paramValues, callback) { + if (route.childRoutes) { + return [null, route.childRoutes]; + } + if (!route.getChildRoutes) { + return []; + } + + var sync = true, + result = void 0; + + var partialNextState = { + location: location, + params: createParams(paramNames, paramValues) + }; + + var partialNextStateWithLocation = (0, _makeStateWithLocation2.default)(partialNextState, location); + + route.getChildRoutes(partialNextStateWithLocation, function (error, childRoutes) { + childRoutes = !error && (0, _RouteUtils.createRoutes)(childRoutes); + if (sync) { + result = [error, childRoutes]; + return; + } + + callback(error, childRoutes); + }); + + sync = false; + return result; // Might be undefined. +} + +function getIndexRoute(route, location, paramNames, paramValues, callback) { + if (route.indexRoute) { + callback(null, route.indexRoute); + } else if (route.getIndexRoute) { + var partialNextState = { + location: location, + params: createParams(paramNames, paramValues) + }; + + var partialNextStateWithLocation = (0, _makeStateWithLocation2.default)(partialNextState, location); + + route.getIndexRoute(partialNextStateWithLocation, function (error, indexRoute) { + callback(error, !error && (0, _RouteUtils.createRoutes)(indexRoute)[0]); + }); + } else if (route.childRoutes) { + (function () { + var pathless = route.childRoutes.filter(function (childRoute) { + return !childRoute.path; + }); + + (0, _AsyncUtils.loopAsync)(pathless.length, function (index, next, done) { + getIndexRoute(pathless[index], location, paramNames, paramValues, function (error, indexRoute) { + if (error || indexRoute) { + var routes = [pathless[index]].concat(Array.isArray(indexRoute) ? indexRoute : [indexRoute]); + done(error, routes); + } else { + next(); + } + }); + }, function (err, routes) { + callback(null, routes); + }); + })(); + } else { + callback(); + } +} + +function assignParams(params, paramNames, paramValues) { + return paramNames.reduce(function (params, paramName, index) { + var paramValue = paramValues && paramValues[index]; + + if (Array.isArray(params[paramName])) { + params[paramName].push(paramValue); + } else if (paramName in params) { + params[paramName] = [params[paramName], paramValue]; + } else { + params[paramName] = paramValue; + } + + return params; + }, params); +} + +function createParams(paramNames, paramValues) { + return assignParams({}, paramNames, paramValues); +} + +function matchRouteDeep(route, location, remainingPathname, paramNames, paramValues, callback) { + var pattern = route.path || ''; + + if (pattern.charAt(0) === '/') { + remainingPathname = location.pathname; + paramNames = []; + paramValues = []; + } + + // Only try to match the path if the route actually has a pattern, and if + // we're not just searching for potential nested absolute paths. + if (remainingPathname !== null && pattern) { + try { + var matched = (0, _PatternUtils.matchPattern)(pattern, remainingPathname); + if (matched) { + remainingPathname = matched.remainingPathname; + paramNames = [].concat(paramNames, matched.paramNames); + paramValues = [].concat(paramValues, matched.paramValues); + } else { + remainingPathname = null; + } + } catch (error) { + callback(error); + } + + // By assumption, pattern is non-empty here, which is the prerequisite for + // actually terminating a match. + if (remainingPathname === '') { + var _ret2 = function () { + var match = { + routes: [route], + params: createParams(paramNames, paramValues) + }; + + getIndexRoute(route, location, paramNames, paramValues, function (error, indexRoute) { + if (error) { + callback(error); + } else { + if (Array.isArray(indexRoute)) { + var _match$routes; + + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(indexRoute.every(function (route) { + return !route.path; + }), 'Index routes should not have paths') : void 0; + (_match$routes = match.routes).push.apply(_match$routes, indexRoute); + } else if (indexRoute) { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(!indexRoute.path, 'Index routes should not have paths') : void 0; + match.routes.push(indexRoute); + } + + callback(null, match); + } + }); + + return { + v: void 0 + }; + }(); + + if ((typeof _ret2 === 'undefined' ? 'undefined' : _typeof(_ret2)) === "object") return _ret2.v; + } + } + + if (remainingPathname != null || route.childRoutes) { + // Either a) this route matched at least some of the path or b) + // we don't have to load this route's children asynchronously. In + // either case continue checking for matches in the subtree. + var onChildRoutes = function onChildRoutes(error, childRoutes) { + if (error) { + callback(error); + } else if (childRoutes) { + // Check the child routes to see if any of them match. + matchRoutes(childRoutes, location, function (error, match) { + if (error) { + callback(error); + } else if (match) { + // A child route matched! Augment the match and pass it up the stack. + match.routes.unshift(route); + callback(null, match); + } else { + callback(); + } + }, remainingPathname, paramNames, paramValues); + } else { + callback(); + } + }; + + var result = getChildRoutes(route, location, paramNames, paramValues, onChildRoutes); + if (result) { + onChildRoutes.apply(undefined, result); + } + } else { + callback(); + } +} + +/** + * Asynchronously matches the given location to a set of routes and calls + * callback(error, state) when finished. The state object will have the + * following properties: + * + * - routes An array of routes that matched, in hierarchical order + * - params An object of URL parameters + * + * Note: This operation may finish synchronously if no routes have an + * asynchronous getChildRoutes method. + */ +function matchRoutes(routes, location, callback, remainingPathname) { + var paramNames = arguments.length <= 4 || arguments[4] === undefined ? [] : arguments[4]; + var paramValues = arguments.length <= 5 || arguments[5] === undefined ? [] : arguments[5]; + + if (remainingPathname === undefined) { + // TODO: This is a little bit ugly, but it works around a quirk in history + // that strips the leading slash from pathnames when using basenames with + // trailing slashes. + if (location.pathname.charAt(0) !== '/') { + location = _extends({}, location, { + pathname: '/' + location.pathname + }); + } + remainingPathname = location.pathname; + } + + (0, _AsyncUtils.loopAsync)(routes.length, function (index, next, done) { + matchRouteDeep(routes[index], location, remainingPathname, paramNames, paramValues, function (error, match) { + if (error || match) { + done(error, match); + } else { + next(); + } + }); + }, callback); +} +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./AsyncUtils":45,"./PatternUtils":53,"./RouteUtils":58,"./makeStateWithLocation":75,"./routerWarning":78,"_process":37}],78:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; +exports.default = routerWarning; +exports._resetWarned = _resetWarned; + +var _warning = require('warning'); + +var _warning2 = _interopRequireDefault(_warning); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var warned = {}; + +function routerWarning(falseToWarn, message) { + // Only issue deprecation warnings once. + if (message.indexOf('deprecated') !== -1) { + if (warned[message]) { + return; + } + + warned[message] = true; + } + + message = '[react-router] ' + message; + + for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { + args[_key - 2] = arguments[_key]; + } + + _warning2.default.apply(undefined, [falseToWarn, message].concat(args)); +} + +function _resetWarned() { + warned = {}; +} +},{"warning":261}],79:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; +exports.default = useRouterHistory; + +var _useQueries = require('history/lib/useQueries'); + +var _useQueries2 = _interopRequireDefault(_useQueries); + +var _useBasename = require('history/lib/useBasename'); + +var _useBasename2 = _interopRequireDefault(_useBasename); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function useRouterHistory(createHistory) { + return function (options) { + var history = (0, _useQueries2.default)((0, _useBasename2.default)(createHistory))(options); + history.__v2_compatible__ = true; + return history; + }; +} +module.exports = exports['default']; +},{"history/lib/useBasename":21,"history/lib/useQueries":22}],80:[function(require,module,exports){ +(function (process){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +var _useQueries = require('history/lib/useQueries'); + +var _useQueries2 = _interopRequireDefault(_useQueries); + +var _createTransitionManager = require('./createTransitionManager'); + +var _createTransitionManager2 = _interopRequireDefault(_createTransitionManager); + +var _routerWarning = require('./routerWarning'); + +var _routerWarning2 = _interopRequireDefault(_routerWarning); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } + +/** + * Returns a new createHistory function that may be used to create + * history objects that know about routing. + * + * Enhances history objects with the following methods: + * + * - listen((error, nextState) => {}) + * - listenBeforeLeavingRoute(route, (nextLocation) => {}) + * - match(location, (error, redirectLocation, nextState) => {}) + * - isActive(pathname, query, indexOnly=false) + */ +function useRoutes(createHistory) { + process.env.NODE_ENV !== 'production' ? (0, _routerWarning2.default)(false, '`useRoutes` is deprecated. Please use `createTransitionManager` instead.') : void 0; + + return function () { + var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; + + var routes = _ref.routes; + + var options = _objectWithoutProperties(_ref, ['routes']); + + var history = (0, _useQueries2.default)(createHistory)(options); + var transitionManager = (0, _createTransitionManager2.default)(history, routes); + return _extends({}, history, transitionManager); + }; +} + +exports.default = useRoutes; +module.exports = exports['default']; +}).call(this,require('_process')) + +},{"./createTransitionManager":69,"./routerWarning":78,"_process":37,"history/lib/useQueries":22}],81:[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +exports.default = withRouter; + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _hoistNonReactStatics = require('hoist-non-react-statics'); + +var _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics); + +var _PropTypes = require('./PropTypes'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getDisplayName(WrappedComponent) { + return WrappedComponent.displayName || WrappedComponent.name || 'Component'; +} + +function withRouter(WrappedComponent) { + var WithRouter = _react2.default.createClass({ + displayName: 'WithRouter', + + contextTypes: { router: _PropTypes.routerShape }, + render: function render() { + return _react2.default.createElement(WrappedComponent, _extends({}, this.props, { router: this.context.router })); + } + }); + + WithRouter.displayName = 'withRouter(' + getDisplayName(WrappedComponent) + ')'; + WithRouter.WrappedComponent = WrappedComponent; + + return (0, _hoistNonReactStatics2.default)(WithRouter, WrappedComponent); +} +module.exports = exports['default']; +},{"./PropTypes":54,"hoist-non-react-statics":24,"react":"react"}],82:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule AutoFocusUtils + */ + +'use strict'; + +var ReactDOMComponentTree = require('./ReactDOMComponentTree'); + +var focusNode = require('fbjs/lib/focusNode'); + +var AutoFocusUtils = { + focusDOMComponent: function () { + focusNode(ReactDOMComponentTree.getNodeFromInstance(this)); + } +}; + +module.exports = AutoFocusUtils; +},{"./ReactDOMComponentTree":123,"fbjs/lib/focusNode":235}],83:[function(require,module,exports){ +/** + * Copyright 2013-present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule BeforeInputEventPlugin + */ + +'use strict'; + +var EventConstants = require('./EventConstants'); +var EventPropagators = require('./EventPropagators'); +var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment'); +var FallbackCompositionState = require('./FallbackCompositionState'); +var SyntheticCompositionEvent = require('./SyntheticCompositionEvent'); +var SyntheticInputEvent = require('./SyntheticInputEvent'); + +var keyOf = require('fbjs/lib/keyOf'); + +var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space +var START_KEYCODE = 229; + +var canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window; + +var documentMode = null; +if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) { + documentMode = document.documentMode; +} + +// Webkit offers a very useful `textInput` event that can be used to +// directly represent `beforeInput`. The IE `textinput` event is not as +// useful, so we don't use it. +var canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto(); + +// In IE9+, we have access to composition events, but the data supplied +// by the native compositionend event may be incorrect. Japanese ideographic +// spaces, for instance (\u3000) are not recorded correctly. +var useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11); + +/** + * Opera <= 12 includes TextEvent in window, but does not fire + * text input events. Rely on keypress instead. + */ +function isPresto() { + var opera = window.opera; + return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12; +} + +var SPACEBAR_CODE = 32; +var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE); + +var topLevelTypes = EventConstants.topLevelTypes; + +// Events and their corresponding property names. +var eventTypes = { + beforeInput: { + phasedRegistrationNames: { + bubbled: keyOf({ onBeforeInput: null }), + captured: keyOf({ onBeforeInputCapture: null }) + }, + dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste] + }, + compositionEnd: { + phasedRegistrationNames: { + bubbled: keyOf({ onCompositionEnd: null }), + captured: keyOf({ onCompositionEndCapture: null }) + }, + dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionEnd, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] + }, + compositionStart: { + phasedRegistrationNames: { + bubbled: keyOf({ onCompositionStart: null }), + captured: keyOf({ onCompositionStartCapture: null }) + }, + dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionStart, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] + }, + compositionUpdate: { + phasedRegistrationNames: { + bubbled: keyOf({ onCompositionUpdate: null }), + captured: keyOf({ onCompositionUpdateCapture: null }) + }, + dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionUpdate, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown] + } +}; + +// Track whether we've ever handled a keypress on the space key. +var hasSpaceKeypress = false; + +/** + * Return whether a native keypress event is assumed to be a command. + * This is required because Firefox fires `keypress` events for key commands + * (cut, copy, select-all, etc.) even though no character is inserted. + */ +function isKeypressCommand(nativeEvent) { + return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && + // ctrlKey && altKey is equivalent to AltGr, and is not a command. + !(nativeEvent.ctrlKey && nativeEvent.altKey); +} + +/** + * Translate native top level events into event types. + * + * @param {string} topLevelType + * @return {object} + */ +function getCompositionEventType(topLevelType) { + switch (topLevelType) { + case topLevelTypes.topCompositionStart: + return eventTypes.compositionStart; + case topLevelTypes.topCompositionEnd: + return eventTypes.compositionEnd; + case topLevelTypes.topCompositionUpdate: + return eventTypes.compositionUpdate; + } +} + +/** + * Does our fallback best-guess model think this event signifies that + * composition has begun? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackCompositionStart(topLevelType, nativeEvent) { + return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE; +} + +/** + * Does our fallback mode think that this event is the end of composition? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackCompositionEnd(topLevelType, nativeEvent) { + switch (topLevelType) { + case topLevelTypes.topKeyUp: + // Command keys insert or clear IME input. + return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; + case topLevelTypes.topKeyDown: + // Expect IME keyCode on each keydown. If we get any other + // code we must have exited earlier. + return nativeEvent.keyCode !== START_KEYCODE; + case topLevelTypes.topKeyPress: + case topLevelTypes.topMouseDown: + case topLevelTypes.topBlur: + // Events are not possible without cancelling IME. + return true; + default: + return false; + } +} + +/** + * Google Input Tools provides composition data via a CustomEvent, + * with the `data` property populated in the `detail` object. If this + * is available on the event object, use it. If not, this is a plain + * composition event and we have nothing special to extract. + * + * @param {object} nativeEvent + * @return {?string} + */ +function getDataFromCustomEvent(nativeEvent) { + var detail = nativeEvent.detail; + if (typeof detail === 'object' && 'data' in detail) { + return detail.data; + } + return null; +} + +// Track the current IME composition fallback object, if any. +var currentComposition = null; + +/** + * @return {?object} A SyntheticCompositionEvent. + */ +function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var eventType; + var fallbackData; + + if (canUseCompositionEvent) { + eventType = getCompositionEventType(topLevelType); + } else if (!currentComposition) { + if (isFallbackCompositionStart(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionStart; + } + } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionEnd; + } + + if (!eventType) { + return null; + } + + if (useFallbackCompositionData) { + // The current composition is stored statically and must not be + // overwritten while composition continues. + if (!currentComposition && eventType === eventTypes.compositionStart) { + currentComposition = FallbackCompositionState.getPooled(nativeEventTarget); + } else if (eventType === eventTypes.compositionEnd) { + if (currentComposition) { + fallbackData = currentComposition.getData(); + } + } + } + + var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget); + + if (fallbackData) { + // Inject data generated from fallback path into the synthetic event. + // This matches the property of native CompositionEventInterface. + event.data = fallbackData; + } else { + var customData = getDataFromCustomEvent(nativeEvent); + if (customData !== null) { + event.data = customData; + } + } + + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; +} + +/** + * @param {string} topLevelType Record from `EventConstants`. + * @param {object} nativeEvent Native browser event. + * @return {?string} The string corresponding to this `beforeInput` event. + */ +function getNativeBeforeInputChars(topLevelType, nativeEvent) { + switch (topLevelType) { + case topLevelTypes.topCompositionEnd: + return getDataFromCustomEvent(nativeEvent); + case topLevelTypes.topKeyPress: + /** + * If native `textInput` events are available, our goal is to make + * use of them. However, there is a special case: the spacebar key. + * In Webkit, preventing default on a spacebar `textInput` event + * cancels character insertion, but it *also* causes the browser + * to fall back to its default spacebar behavior of scrolling the + * page. + * + * Tracking at: + * https://code.google.com/p/chromium/issues/detail?id=355103 + * + * To avoid this issue, use the keypress event as if no `textInput` + * event is available. + */ + var which = nativeEvent.which; + if (which !== SPACEBAR_CODE) { + return null; + } + + hasSpaceKeypress = true; + return SPACEBAR_CHAR; + + case topLevelTypes.topTextInput: + // Record the characters to be added to the DOM. + var chars = nativeEvent.data; + + // If it's a spacebar character, assume that we have already handled + // it at the keypress level and bail immediately. Android Chrome + // doesn't give us keycodes, so we need to blacklist it. + if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { + return null; + } + + return chars; + + default: + // For other native event types, do nothing. + return null; + } +} + +/** + * For browsers that do not provide the `textInput` event, extract the + * appropriate string to use for SyntheticInputEvent. + * + * @param {string} topLevelType Record from `EventConstants`. + * @param {object} nativeEvent Native browser event. + * @return {?string} The fallback string for this `beforeInput` event. + */ +function getFallbackBeforeInputChars(topLevelType, nativeEvent) { + // If we are currently composing (IME) and using a fallback to do so, + // try to extract the composed characters from the fallback object. + if (currentComposition) { + if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) { + var chars = currentComposition.getData(); + FallbackCompositionState.release(currentComposition); + currentComposition = null; + return chars; + } + return null; + } + + switch (topLevelType) { + case topLevelTypes.topPaste: + // If a paste event occurs after a keypress, throw out the input + // chars. Paste events should not lead to BeforeInput events. + return null; + case topLevelTypes.topKeyPress: + /** + * As of v27, Firefox may fire keypress events even when no character + * will be inserted. A few possibilities: + * + * - `which` is `0`. Arrow keys, Esc key, etc. + * + * - `which` is the pressed key code, but no char is available. + * Ex: 'AltGr + d` in Polish. There is no modified character for + * this key combination and no character is inserted into the + * document, but FF fires the keypress for char code `100` anyway. + * No `input` event will occur. + * + * - `which` is the pressed key code, but a command combination is + * being used. Ex: `Cmd+C`. No character is inserted, and no + * `input` event will occur. + */ + if (nativeEvent.which && !isKeypressCommand(nativeEvent)) { + return String.fromCharCode(nativeEvent.which); + } + return null; + case topLevelTypes.topCompositionEnd: + return useFallbackCompositionData ? null : nativeEvent.data; + default: + return null; + } +} + +/** + * Extract a SyntheticInputEvent for `beforeInput`, based on either native + * `textInput` or fallback behavior. + * + * @return {?object} A SyntheticInputEvent. + */ +function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var chars; + + if (canUseTextInputEvent) { + chars = getNativeBeforeInputChars(topLevelType, nativeEvent); + } else { + chars = getFallbackBeforeInputChars(topLevelType, nativeEvent); + } + + // If no characters are being inserted, no BeforeInput event should + // be fired. + if (!chars) { + return null; + } + + var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget); + + event.data = chars; + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; +} + +/** + * Create an `onBeforeInput` event to match + * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. + * + * This event plugin is based on the native `textInput` event + * available in Chrome, Safari, Opera, and IE. This event fires after + * `onKeyPress` and `onCompositionEnd`, but before `onInput`. + * + * `beforeInput` is spec'd but not implemented in any browsers, and + * the `input` event does not provide any useful information about what has + * actually been added, contrary to the spec. Thus, `textInput` is the best + * available event to identify the characters that have actually been inserted + * into the target node. + * + * This plugin is also responsible for emitting `composition` events, thus + * allowing us to share composition fallback code for both `beforeInput` and + * `composition` event types. + */ +var BeforeInputEventPlugin = { + + eventTypes: eventTypes, + + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)]; + } +}; + +module.exports = BeforeInputEventPlugin; +},{"./EventConstants":97,"./EventPropagators":101,"./FallbackCompositionState":102,"./SyntheticCompositionEvent":182,"./SyntheticInputEvent":186,"fbjs/lib/ExecutionEnvironment":227,"fbjs/lib/keyOf":245}],84:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule CSSProperty + */ + +'use strict'; + +/** + * CSS properties which accept numbers but are not in units of "px". + */ + +var isUnitlessNumber = { + animationIterationCount: true, + borderImageOutset: true, + borderImageSlice: true, + borderImageWidth: true, + boxFlex: true, + boxFlexGroup: true, + boxOrdinalGroup: true, + columnCount: true, + flex: true, + flexGrow: true, + flexPositive: true, + flexShrink: true, + flexNegative: true, + flexOrder: true, + gridRow: true, + gridColumn: true, + fontWeight: true, + lineClamp: true, + lineHeight: true, + opacity: true, + order: true, + orphans: true, + tabSize: true, + widows: true, + zIndex: true, + zoom: true, + + // SVG-related properties + fillOpacity: true, + floodOpacity: true, + stopOpacity: true, + strokeDasharray: true, + strokeDashoffset: true, + strokeMiterlimit: true, + strokeOpacity: true, + strokeWidth: true +}; + +/** + * @param {string} prefix vendor-specific prefix, eg: Webkit + * @param {string} key style name, eg: transitionDuration + * @return {string} style name prefixed with `prefix`, properly camelCased, eg: + * WebkitTransitionDuration + */ +function prefixKey(prefix, key) { + return prefix + key.charAt(0).toUpperCase() + key.substring(1); +} + +/** + * Support style names that may come passed in prefixed by adding permutations + * of vendor prefixes. + */ +var prefixes = ['Webkit', 'ms', 'Moz', 'O']; + +// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an +// infinite loop, because it iterates over the newly added props too. +Object.keys(isUnitlessNumber).forEach(function (prop) { + prefixes.forEach(function (prefix) { + isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; + }); +}); + +/** + * Most style properties can be unset by doing .style[prop] = '' but IE8 + * doesn't like doing that with shorthand properties so for the properties that + * IE8 breaks on, which are listed here, we instead unset each of the + * individual properties. See http://bugs.jquery.com/ticket/12385. + * The 4-value 'clock' properties like margin, padding, border-width seem to + * behave without any problems. Curiously, list-style works too without any + * special prodding. + */ +var shorthandPropertyExpansions = { + background: { + backgroundAttachment: true, + backgroundColor: true, + backgroundImage: true, + backgroundPositionX: true, + backgroundPositionY: true, + backgroundRepeat: true + }, + backgroundPosition: { + backgroundPositionX: true, + backgroundPositionY: true + }, + border: { + borderWidth: true, + borderStyle: true, + borderColor: true + }, + borderBottom: { + borderBottomWidth: true, + borderBottomStyle: true, + borderBottomColor: true + }, + borderLeft: { + borderLeftWidth: true, + borderLeftStyle: true, + borderLeftColor: true + }, + borderRight: { + borderRightWidth: true, + borderRightStyle: true, + borderRightColor: true + }, + borderTop: { + borderTopWidth: true, + borderTopStyle: true, + borderTopColor: true + }, + font: { + fontStyle: true, + fontVariant: true, + fontWeight: true, + fontSize: true, + lineHeight: true, + fontFamily: true + }, + outline: { + outlineWidth: true, + outlineStyle: true, + outlineColor: true + } +}; + +var CSSProperty = { + isUnitlessNumber: isUnitlessNumber, + shorthandPropertyExpansions: shorthandPropertyExpansions +}; + +module.exports = CSSProperty; },{}],85:[function(require,module,exports){ -"use strict";function checkMask(t,e){return(t&e)===e}var _prodInvariant=require("./reactProdInvariant"),invariant=require("fbjs/lib/invariant"),DOMPropertyInjection={MUST_USE_PROPERTY:1,HAS_BOOLEAN_VALUE:4,HAS_NUMERIC_VALUE:8,HAS_POSITIVE_NUMERIC_VALUE:24,HAS_OVERLOADED_BOOLEAN_VALUE:32,injectDOMPropertyConfig:function(t){var e=DOMPropertyInjection,r=t.Properties||{},a=t.DOMAttributeNamespaces||{},u=t.DOMAttributeNames||{},o=t.DOMPropertyNames||{},i=t.DOMMutationMethods||{};t.isCustomAttribute&&DOMProperty._isCustomAttributeFunctions.push(t.isCustomAttribute);for(var s in r){DOMProperty.properties.hasOwnProperty(s)?_prodInvariant("48",s):void 0;var n=s.toLowerCase(),A=r[s],_={attributeName:n,attributeNamespace:null,propertyName:s,mutationMethod:null,mustUseProperty:checkMask(A,e.MUST_USE_PROPERTY),hasBooleanValue:checkMask(A,e.HAS_BOOLEAN_VALUE),hasNumericValue:checkMask(A,e.HAS_NUMERIC_VALUE),hasPositiveNumericValue:checkMask(A,e.HAS_POSITIVE_NUMERIC_VALUE),hasOverloadedBooleanValue:checkMask(A,e.HAS_OVERLOADED_BOOLEAN_VALUE)};if(_.hasBooleanValue+_.hasNumericValue+_.hasOverloadedBooleanValue<=1?void 0:_prodInvariant("50",s),u.hasOwnProperty(s)){var E=u[s];_.attributeName=E}a.hasOwnProperty(s)&&(_.attributeNamespace=a[s]),o.hasOwnProperty(s)&&(_.propertyName=o[s]),i.hasOwnProperty(s)&&(_.mutationMethod=i[s]),DOMProperty.properties[s]=_}}},ATTRIBUTE_NAME_START_CHAR=":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",DOMProperty={ID_ATTRIBUTE_NAME:"data-reactid",ROOT_ATTRIBUTE_NAME:"data-reactroot",ATTRIBUTE_NAME_START_CHAR:ATTRIBUTE_NAME_START_CHAR,ATTRIBUTE_NAME_CHAR:ATTRIBUTE_NAME_START_CHAR+"\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040",properties:{},getPossibleStandardName:null,_isCustomAttributeFunctions:[],isCustomAttribute:function(t){for(var e=0;e-1?void 0:_prodInvariant("96",e),!EventPluginRegistry.plugins[i]){n.extractEvents?void 0:_prodInvariant("97",e),EventPluginRegistry.plugins[i]=n;var r=n.eventTypes;for(var t in r)publishEventForPlugin(r[t],n,t)?void 0:_prodInvariant("98",t,e)}}}function publishEventForPlugin(e,n,i){EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(i)?_prodInvariant("99",i):void 0,EventPluginRegistry.eventNameDispatchConfigs[i]=e;var r=e.phasedRegistrationNames;if(r){for(var t in r)if(r.hasOwnProperty(t)){var a=r[t];publishRegistrationName(a,n,i)}return!0}return!!e.registrationName&&(publishRegistrationName(e.registrationName,n,i),!0)}function publishRegistrationName(e,n,i){EventPluginRegistry.registrationNameModules[e]?_prodInvariant("100",e):void 0,EventPluginRegistry.registrationNameModules[e]=n,EventPluginRegistry.registrationNameDependencies[e]=n.eventTypes[i].dependencies}var _prodInvariant=require("./reactProdInvariant"),invariant=require("fbjs/lib/invariant"),EventPluginOrder=null,namesToPlugins={},EventPluginRegistry={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},possibleRegistrationNames:null,injectEventPluginOrder:function(e){EventPluginOrder?_prodInvariant("101"):void 0,EventPluginOrder=Array.prototype.slice.call(e),recomputePluginOrdering()},injectEventPluginsByName:function(e){var n=!1;for(var i in e)if(e.hasOwnProperty(i)){var r=e[i];namesToPlugins.hasOwnProperty(i)&&namesToPlugins[i]===r||(namesToPlugins[i]?_prodInvariant("102",i):void 0,namesToPlugins[i]=r,n=!0)}n&&recomputePluginOrdering()},getPluginModuleForEvent:function(e){var n=e.dispatchConfig;if(n.registrationName)return EventPluginRegistry.registrationNameModules[n.registrationName]||null;for(var i in n.phasedRegistrationNames)if(n.phasedRegistrationNames.hasOwnProperty(i)){var r=EventPluginRegistry.registrationNameModules[n.phasedRegistrationNames[i]];if(r)return r}return null},_resetEventPlugins:function(){EventPluginOrder=null;for(var e in namesToPlugins)namesToPlugins.hasOwnProperty(e)&&delete namesToPlugins[e];EventPluginRegistry.plugins.length=0;var n=EventPluginRegistry.eventNameDispatchConfigs;for(var i in n)n.hasOwnProperty(i)&&delete n[i];var r=EventPluginRegistry.registrationNameModules;for(var t in r)r.hasOwnProperty(t)&&delete r[t]}};module.exports=EventPluginRegistry; + var warnedStyleNames = {}; + var warnedStyleValues = {}; + var warnedForNaNValue = false; -},{"./reactProdInvariant":202,"fbjs/lib/invariant":224}],94:[function(require,module,exports){ -"use strict";function isEndish(e){return e===topLevelTypes.topMouseUp||e===topLevelTypes.topTouchEnd||e===topLevelTypes.topTouchCancel}function isMoveish(e){return e===topLevelTypes.topMouseMove||e===topLevelTypes.topTouchMove}function isStartish(e){return e===topLevelTypes.topMouseDown||e===topLevelTypes.topTouchStart}function executeDispatch(e,t,r,n){var s=e.type||"unknown-event";e.currentTarget=EventPluginUtils.getNodeFromInstance(n),t?ReactErrorUtils.invokeGuardedCallbackWithCatch(s,r,e):ReactErrorUtils.invokeGuardedCallback(s,r,e),e.currentTarget=null}function executeDispatchesInOrder(e,t){var r=e._dispatchListeners,n=e._dispatchInstances;if(Array.isArray(r))for(var s=0;s1?1-e:void 0;return this._fallbackText=a.slice(t,r),this._fallbackText}}),PooledClass.addPoolingTo(FallbackCompositionState),module.exports=FallbackCompositionState; + var warnBadVendoredStyleName = function (name, owner) { + if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { + return; + } -},{"./PooledClass":100,"./getTextContentAccessor":195,"object-assign":31}],97:[function(require,module,exports){ -"use strict";var DOMProperty=require("./DOMProperty"),MUST_USE_PROPERTY=DOMProperty.injection.MUST_USE_PROPERTY,HAS_BOOLEAN_VALUE=DOMProperty.injection.HAS_BOOLEAN_VALUE,HAS_NUMERIC_VALUE=DOMProperty.injection.HAS_NUMERIC_VALUE,HAS_POSITIVE_NUMERIC_VALUE=DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE,HAS_OVERLOADED_BOOLEAN_VALUE=DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE,HTMLDOMPropertyConfig={isCustomAttribute:RegExp.prototype.test.bind(new RegExp("^(data|aria)-["+DOMProperty.ATTRIBUTE_NAME_CHAR+"]*$")),Properties:{accept:0,acceptCharset:0,accessKey:0,action:0,allowFullScreen:HAS_BOOLEAN_VALUE,allowTransparency:0,alt:0,async:HAS_BOOLEAN_VALUE,autoComplete:0,autoPlay:HAS_BOOLEAN_VALUE,capture:HAS_BOOLEAN_VALUE,cellPadding:0,cellSpacing:0,charSet:0,challenge:0,checked:MUST_USE_PROPERTY|HAS_BOOLEAN_VALUE,cite:0,classID:0,className:0,cols:HAS_POSITIVE_NUMERIC_VALUE,colSpan:0,content:0,contentEditable:0,contextMenu:0,controls:HAS_BOOLEAN_VALUE,coords:0,crossOrigin:0,data:0,dateTime:0,default:HAS_BOOLEAN_VALUE,defer:HAS_BOOLEAN_VALUE,dir:0,disabled:HAS_BOOLEAN_VALUE,download:HAS_OVERLOADED_BOOLEAN_VALUE,draggable:0,encType:0,form:0,formAction:0,formEncType:0,formMethod:0,formNoValidate:HAS_BOOLEAN_VALUE,formTarget:0,frameBorder:0,headers:0,height:0,hidden:HAS_BOOLEAN_VALUE,high:0,href:0,hrefLang:0,htmlFor:0,httpEquiv:0,icon:0,id:0,inputMode:0,integrity:0,is:0,keyParams:0,keyType:0,kind:0,label:0,lang:0,list:0,loop:HAS_BOOLEAN_VALUE,low:0,manifest:0,marginHeight:0,marginWidth:0,max:0,maxLength:0,media:0,mediaGroup:0,method:0,min:0,minLength:0,multiple:MUST_USE_PROPERTY|HAS_BOOLEAN_VALUE,muted:MUST_USE_PROPERTY|HAS_BOOLEAN_VALUE,name:0,nonce:0,noValidate:HAS_BOOLEAN_VALUE,open:HAS_BOOLEAN_VALUE,optimum:0,pattern:0,placeholder:0,poster:0,preload:0,profile:0,radioGroup:0,readOnly:HAS_BOOLEAN_VALUE,rel:0,required:HAS_BOOLEAN_VALUE,reversed:HAS_BOOLEAN_VALUE,role:0,rows:HAS_POSITIVE_NUMERIC_VALUE,rowSpan:HAS_NUMERIC_VALUE,sandbox:0,scope:0,scoped:HAS_BOOLEAN_VALUE,scrolling:0,seamless:HAS_BOOLEAN_VALUE,selected:MUST_USE_PROPERTY|HAS_BOOLEAN_VALUE,shape:0,size:HAS_POSITIVE_NUMERIC_VALUE,sizes:0,span:HAS_POSITIVE_NUMERIC_VALUE,spellCheck:0,src:0,srcDoc:0,srcLang:0,srcSet:0,start:HAS_NUMERIC_VALUE,step:0,style:0,summary:0,tabIndex:0,target:0,title:0,type:0,useMap:0,value:0,width:0,wmode:0,wrap:0,about:0,datatype:0,inlist:0,prefix:0,property:0,resource:0,typeof:0,vocab:0,autoCapitalize:0,autoCorrect:0,autoSave:0,color:0,itemProp:0,itemScope:HAS_BOOLEAN_VALUE,itemType:0,itemID:0,itemRef:0,results:0,security:0,unselectable:0},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{}};module.exports=HTMLDOMPropertyConfig; + warnedStyleNames[name] = true; + process.env.NODE_ENV !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0; + }; -},{"./DOMProperty":85}],98:[function(require,module,exports){ -"use strict";function escape(e){var n=/[=:]/g,r={"=":"=0",":":"=2"},s=(""+e).replace(n,function(e){return r[e]});return"$"+s}function unescape(e){var n=/(=0|=2)/g,r={"=0":"=","=2":":"},s="."===e[0]&&"$"===e[1]?e.substring(2):e.substring(1);return(""+s).replace(n,function(e){return r[e]})}var KeyEscapeUtils={escape:escape,unescape:unescape};module.exports=KeyEscapeUtils; + var warnStyleValueWithSemicolon = function (name, value, owner) { + if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) { + return; + } -},{}],99:[function(require,module,exports){ -"use strict";function _assertSingleLink(e){null!=e.checkedLink&&null!=e.valueLink?_prodInvariant("87"):void 0}function _assertValueLink(e){_assertSingleLink(e),null!=e.value||null!=e.onChange?_prodInvariant("88"):void 0}function _assertCheckedLink(e){_assertSingleLink(e),null!=e.checked||null!=e.onChange?_prodInvariant("89"):void 0}function getDeclarationErrorAddendum(e){if(e){var n=e.getName();if(n)return" Check the render method of `"+n+"`."}return""}var _prodInvariant=require("./reactProdInvariant"),ReactPropTypes=require("./ReactPropTypes"),ReactPropTypeLocations=require("./ReactPropTypeLocations"),invariant=require("fbjs/lib/invariant"),warning=require("fbjs/lib/warning"),hasReadOnlyValue={button:!0,checkbox:!0,image:!0,hidden:!0,radio:!0,reset:!0,submit:!0},propTypes={value:function(e,n,r){return!e[n]||hasReadOnlyValue[e.type]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.")},checked:function(e,n,r){return!e[n]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.")},onChange:ReactPropTypes.func},loggedTypeFailures={},LinkedValueUtils={checkPropTypes:function(e,n,r){for(var a in propTypes){if(propTypes.hasOwnProperty(a))var i=propTypes[a](n,a,e,ReactPropTypeLocations.prop);if(i instanceof Error&&!(i.message in loggedTypeFailures)){loggedTypeFailures[i.message]=!0;getDeclarationErrorAddendum(r)}}},getValue:function(e){return e.valueLink?(_assertValueLink(e),e.valueLink.value):e.value},getChecked:function(e){return e.checkedLink?(_assertCheckedLink(e),e.checkedLink.value):e.checked},executeOnChange:function(e,n){return e.valueLink?(_assertValueLink(e),e.valueLink.requestChange(n.target.value)):e.checkedLink?(_assertCheckedLink(e),e.checkedLink.requestChange(n.target.checked)):e.onChange?e.onChange.call(void 0,n):void 0}};module.exports=LinkedValueUtils; + warnedStyleValues[value] = true; + process.env.NODE_ENV !== 'production' ? warning(false, 'Style property values shouldn\'t contain a semicolon.%s ' + 'Try "%s: %s" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0; + }; -},{"./ReactPropTypeLocations":150,"./ReactPropTypes":151,"./reactProdInvariant":202,"fbjs/lib/invariant":224,"fbjs/lib/warning":232}],100:[function(require,module,exports){ -"use strict";var _prodInvariant=require("./reactProdInvariant"),invariant=require("fbjs/lib/invariant"),oneArgumentPooler=function(o){var e=this;if(e.instancePool.length){var n=e.instancePool.pop();return e.call(n,o),n}return new e(o)},twoArgumentPooler=function(o,e){var n=this;if(n.instancePool.length){var r=n.instancePool.pop();return n.call(r,o,e),r}return new n(o,e)},threeArgumentPooler=function(o,e,n){var r=this;if(r.instancePool.length){var t=r.instancePool.pop();return r.call(t,o,e,n),t}return new r(o,e,n)},fourArgumentPooler=function(o,e,n,r){var t=this;if(t.instancePool.length){var l=t.instancePool.pop();return t.call(l,o,e,n,r),l}return new t(o,e,n,r)},fiveArgumentPooler=function(o,e,n,r,t){var l=this;if(l.instancePool.length){var a=l.instancePool.pop();return l.call(a,o,e,n,r,t),a}return new l(o,e,n,r,t)},standardReleaser=function(o){var e=this;o instanceof e?void 0:_prodInvariant("25"),o.destructor(),e.instancePool.length -1) { + warnHyphenatedStyleName(name, owner); + } else if (badVendoredStyleNamePattern.test(name)) { + warnBadVendoredStyleName(name, owner); + } else if (badStyleValueWithSemicolonPattern.test(value)) { + warnStyleValueWithSemicolon(name, value, owner); + } -},{"./KeyEscapeUtils":98,"./ReactReconciler":153,"./instantiateReactComponent":197,"./shouldUpdateReactComponent":206,"./traverseAllChildren":207,"fbjs/lib/warning":232}],104:[function(require,module,exports){ -"use strict";function escapeUserProvidedKey(e){return(""+e).replace(userProvidedKeyEscapeRegex,"$&/")}function ForEachBookKeeping(e,n){this.func=e,this.context=n,this.count=0}function forEachSingleChild(e,n,t){var r=e.func,o=e.context;r.call(o,n,e.count++)}function forEachChildren(e,n,t){if(null==e)return e;var r=ForEachBookKeeping.getPooled(n,t);traverseAllChildren(e,forEachSingleChild,r),ForEachBookKeeping.release(r)}function MapBookKeeping(e,n,t,r){this.result=e,this.keyPrefix=n,this.func=t,this.context=r,this.count=0}function mapSingleChildIntoContext(e,n,t){var r=e.result,o=e.keyPrefix,l=e.func,i=e.context,u=l.call(i,n,e.count++);Array.isArray(u)?mapIntoWithKeyPrefixInternal(u,r,t,emptyFunction.thatReturnsArgument):null!=u&&(ReactElement.isValidElement(u)&&(u=ReactElement.cloneAndReplaceKey(u,o+(!u.key||n&&n.key===u.key?"":escapeUserProvidedKey(u.key)+"/")+t)),r.push(u))}function mapIntoWithKeyPrefixInternal(e,n,t,r,o){var l="";null!=t&&(l=escapeUserProvidedKey(t)+"/");var i=MapBookKeeping.getPooled(n,l,r,o);traverseAllChildren(e,mapSingleChildIntoContext,i),MapBookKeeping.release(i)}function mapChildren(e,n,t){if(null==e)return e;var r=[];return mapIntoWithKeyPrefixInternal(e,r,null,n,t),r}function forEachSingleChildDummy(e,n,t){return null}function countChildren(e,n){return traverseAllChildren(e,forEachSingleChildDummy,null)}function toArray(e){var n=[];return mapIntoWithKeyPrefixInternal(e,n,null,emptyFunction.thatReturnsArgument),n}var PooledClass=require("./PooledClass"),ReactElement=require("./ReactElement"),emptyFunction=require("fbjs/lib/emptyFunction"),traverseAllChildren=require("./traverseAllChildren"),twoArgumentPooler=PooledClass.twoArgumentPooler,fourArgumentPooler=PooledClass.fourArgumentPooler,userProvidedKeyEscapeRegex=/\/+/g;ForEachBookKeeping.prototype.destructor=function(){this.func=null,this.context=null,this.count=0},PooledClass.addPoolingTo(ForEachBookKeeping,twoArgumentPooler),MapBookKeeping.prototype.destructor=function(){this.result=null,this.keyPrefix=null,this.func=null,this.context=null,this.count=0},PooledClass.addPoolingTo(MapBookKeeping,fourArgumentPooler);var ReactChildren={forEach:forEachChildren,map:mapChildren,mapIntoWithKeyPrefixInternal:mapIntoWithKeyPrefixInternal,count:countChildren,toArray:toArray};module.exports=ReactChildren; + if (typeof value === 'number' && isNaN(value)) { + warnStyleValueIsNaN(name, value, owner); + } + }; +} -},{"./PooledClass":100,"./ReactElement":131,"./traverseAllChildren":207,"fbjs/lib/emptyFunction":216}],105:[function(require,module,exports){ -"use strict";function validateTypeDef(e,t,n){for(var i in t)t.hasOwnProperty(i)}function validateMethodOverride(e,t){var n=ReactClassInterface.hasOwnProperty(t)?ReactClassInterface[t]:null;ReactClassMixin.hasOwnProperty(t)&&(n!==SpecPolicy.OVERRIDE_BASE?_prodInvariant("73",t):void 0),e&&(n!==SpecPolicy.DEFINE_MANY&&n!==SpecPolicy.DEFINE_MANY_MERGED?_prodInvariant("74",t):void 0)}function mixSpecIntoComponent(e,t){if(t){"function"==typeof t?_prodInvariant("75"):void 0,ReactElement.isValidElement(t)?_prodInvariant("76"):void 0;var n=e.prototype,i=n.__reactAutoBindPairs;t.hasOwnProperty(MIXINS_KEY)&&RESERVED_SPEC_KEYS.mixins(e,t.mixins);for(var o in t)if(t.hasOwnProperty(o)&&o!==MIXINS_KEY){var r=t[o],a=n.hasOwnProperty(o);if(validateMethodOverride(a,o),RESERVED_SPEC_KEYS.hasOwnProperty(o))RESERVED_SPEC_KEYS[o](e,r);else{var c=ReactClassInterface.hasOwnProperty(o),p="function"==typeof r,s=p&&!c&&!a&&t.autobind!==!1;if(s)i.push(o,r),n[o]=r;else if(a){var l=ReactClassInterface[o];!c||l!==SpecPolicy.DEFINE_MANY_MERGED&&l!==SpecPolicy.DEFINE_MANY?_prodInvariant("77",l,o):void 0,l===SpecPolicy.DEFINE_MANY_MERGED?n[o]=createMergedResultFunction(n[o],r):l===SpecPolicy.DEFINE_MANY&&(n[o]=createChainedFunction(n[o],r))}else n[o]=r}}}}function mixStaticSpecIntoComponent(e,t){if(t)for(var n in t){var i=t[n];if(t.hasOwnProperty(n)){var o=n in RESERVED_SPEC_KEYS;o?_prodInvariant("78",n):void 0;var r=n in e;r?_prodInvariant("79",n):void 0,e[n]=i}}}function mergeIntoWithNoDuplicateKeys(e,t){e&&t&&"object"==typeof e&&"object"==typeof t?void 0:_prodInvariant("80");for(var n in t)t.hasOwnProperty(n)&&(void 0!==e[n]?_prodInvariant("81",n):void 0,e[n]=t[n]);return e}function createMergedResultFunction(e,t){return function(){var n=e.apply(this,arguments),i=t.apply(this,arguments);if(null==n)return i;if(null==i)return n;var o={};return mergeIntoWithNoDuplicateKeys(o,n),mergeIntoWithNoDuplicateKeys(o,i),o}}function createChainedFunction(e,t){return function(){e.apply(this,arguments),t.apply(this,arguments)}}function bindAutoBindMethod(e,t){var n=t.bind(e);return n}function bindAutoBindMethods(e){for(var t=e.__reactAutoBindPairs,n=0;n createMarkupForStyles({width: '200px', height: 0}) + * "width:200px;height:0;" + * + * Undefined values are ignored so that declarative programming is easier. + * The result should be HTML-escaped before insertion into the DOM. + * + * @param {object} styles + * @param {ReactDOMComponent} component + * @return {?string} + */ + createMarkupForStyles: function (styles, component) { + var serialized = ''; + for (var styleName in styles) { + if (!styles.hasOwnProperty(styleName)) { + continue; + } + var styleValue = styles[styleName]; + if (process.env.NODE_ENV !== 'production') { + warnValidStyle(styleName, styleValue, component); + } + if (styleValue != null) { + serialized += processStyleName(styleName) + ':'; + serialized += dangerousStyleValue(styleName, styleValue, component) + ';'; + } + } + return serialized || null; + }, -},{"./ReactNoopUpdateQueue":147,"./canDefineProperty":180,"./reactProdInvariant":202,"fbjs/lib/emptyObject":217,"fbjs/lib/invariant":224,"fbjs/lib/warning":232}],107:[function(require,module,exports){ -"use strict";var DOMChildrenOperations=require("./DOMChildrenOperations"),ReactDOMIDOperations=require("./ReactDOMIDOperations"),ReactComponentBrowserEnvironment={processChildrenUpdates:ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,replaceNodeWithMarkup:DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup,unmountIDFromEnvironment:function(e){}};module.exports=ReactComponentBrowserEnvironment; + /** + * Sets the value for multiple styles on a node. If a value is specified as + * '' (empty string), the corresponding style property will be unset. + * + * @param {DOMElement} node + * @param {object} styles + * @param {ReactDOMComponent} component + */ + setValueForStyles: function (node, styles, component) { + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation(component._debugID, 'update styles', styles); + } -},{"./DOMChildrenOperations":82,"./ReactDOMIDOperations":120}],108:[function(require,module,exports){ -"use strict";var _prodInvariant=require("./reactProdInvariant"),invariant=require("fbjs/lib/invariant"),injected=!1,ReactComponentEnvironment={unmountIDFromEnvironment:null,replaceNodeWithMarkup:null,processChildrenUpdates:null,injection:{injectEnvironment:function(n){injected?_prodInvariant("104"):void 0,ReactComponentEnvironment.unmountIDFromEnvironment=n.unmountIDFromEnvironment,ReactComponentEnvironment.replaceNodeWithMarkup=n.replaceNodeWithMarkup,ReactComponentEnvironment.processChildrenUpdates=n.processChildrenUpdates,injected=!0}}};module.exports=ReactComponentEnvironment; + var style = node.style; + for (var styleName in styles) { + if (!styles.hasOwnProperty(styleName)) { + continue; + } + if (process.env.NODE_ENV !== 'production') { + warnValidStyle(styleName, styles[styleName], component); + } + var styleValue = dangerousStyleValue(styleName, styles[styleName], component); + if (styleName === 'float' || styleName === 'cssFloat') { + styleName = styleFloatAccessor; + } + if (styleValue) { + style[styleName] = styleValue; + } else { + var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName]; + if (expansion) { + // Shorthand property that IE8 won't like unsetting, so unset each + // component to placate it + for (var individualStyleName in expansion) { + style[individualStyleName] = ''; + } + } else { + style[styleName] = ''; + } + } + } + } -},{"./reactProdInvariant":202,"fbjs/lib/invariant":224}],109:[function(require,module,exports){ -"use strict";function StatelessComponent(e){}function warnIfInvalidElement(e,t){}function invokeComponentDidMountWithTimer(){var e=this._instance;0!==this._debugID&&ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID,"componentDidMount"),e.componentDidMount(),0!==this._debugID&&ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID,"componentDidMount")}function invokeComponentDidUpdateWithTimer(e,t,n){var o=this._instance;0!==this._debugID&&ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID,"componentDidUpdate"),o.componentDidUpdate(e,t,n),0!==this._debugID&&ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID,"componentDidUpdate")}function shouldConstruct(e){return e.prototype&&e.prototype.isReactComponent}var _prodInvariant=require("./reactProdInvariant"),_assign=require("object-assign"),ReactComponentEnvironment=require("./ReactComponentEnvironment"),ReactCurrentOwner=require("./ReactCurrentOwner"),ReactElement=require("./ReactElement"),ReactErrorUtils=require("./ReactErrorUtils"),ReactInstanceMap=require("./ReactInstanceMap"),ReactInstrumentation=require("./ReactInstrumentation"),ReactNodeTypes=require("./ReactNodeTypes"),ReactPropTypeLocations=require("./ReactPropTypeLocations"),ReactReconciler=require("./ReactReconciler"),checkReactTypeSpec=require("./checkReactTypeSpec"),emptyObject=require("fbjs/lib/emptyObject"),invariant=require("fbjs/lib/invariant"),shouldUpdateReactComponent=require("./shouldUpdateReactComponent"),warning=require("fbjs/lib/warning");StatelessComponent.prototype.render=function(){var e=ReactInstanceMap.get(this)._currentElement.type,t=e(this.props,this.context,this.updater);return warnIfInvalidElement(e,t),t};var nextMountID=1,ReactCompositeComponentMixin={construct:function(e){this._currentElement=e,this._rootNodeID=null,this._instance=null,this._hostParent=null,this._hostContainerInfo=null,this._updateBatchNumber=null,this._pendingElement=null,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._renderedNodeType=null,this._renderedComponent=null,this._context=null,this._mountOrder=0,this._topLevelWrapper=null,this._pendingCallbacks=null,this._calledComponentWillUnmount=!1},mountComponent:function(e,t,n,o){this._context=o,this._mountOrder=nextMountID++,this._hostParent=t,this._hostContainerInfo=n;var i,r=this._currentElement.props,a=this._processContext(o),s=this._currentElement.type,c=e.getUpdateQueue(),p=this._constructComponent(r,a,c);shouldConstruct(s)||null!=p&&null!=p.render||(i=p,warnIfInvalidElement(s,i),null===p||p===!1||ReactElement.isValidElement(p)?void 0:_prodInvariant("105",s.displayName||s.name||"Component"),p=new StatelessComponent(s));p.props=r,p.context=a,p.refs=emptyObject,p.updater=c,this._instance=p,ReactInstanceMap.set(p,this);var u=p.state;void 0===u&&(p.state=u=null),"object"!=typeof u||Array.isArray(u)?_prodInvariant("106",this.getName()||"ReactCompositeComponent"):void 0,this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1;var l;return l=p.unstable_handleError?this.performInitialMountWithErrorHandling(i,t,n,e,o):this.performInitialMount(i,t,n,e,o),p.componentDidMount&&e.getReactMountReady().enqueue(p.componentDidMount,p),l},_constructComponent:function(e,t,n){return this._constructComponentWithoutOwner(e,t,n)},_constructComponentWithoutOwner:function(e,t,n){var o,i=this._currentElement.type;return o=shouldConstruct(i)?new i(e,t,n):i(e,t,n)},performInitialMountWithErrorHandling:function(e,t,n,o,i){var r,a=o.checkpoint();try{r=this.performInitialMount(e,t,n,o,i)}catch(s){o.rollback(a),this._instance.unstable_handleError(s),this._pendingStateQueue&&(this._instance.state=this._processPendingState(this._instance.props,this._instance.context)),a=o.checkpoint(),this._renderedComponent.unmountComponent(!0),o.rollback(a),r=this.performInitialMount(e,t,n,o,i)}return r},performInitialMount:function(e,t,n,o,i){var r=this._instance;r.componentWillMount&&(r.componentWillMount(),this._pendingStateQueue&&(r.state=this._processPendingState(r.props,r.context))),void 0===e&&(e=this._renderValidatedComponent());var a=ReactNodeTypes.getType(e);this._renderedNodeType=a;var s=this._instantiateReactComponent(e,a!==ReactNodeTypes.EMPTY);this._renderedComponent=s;var c=ReactReconciler.mountComponent(s,o,t,n,this._processChildContext(i));return c},getHostNode:function(){return ReactReconciler.getHostNode(this._renderedComponent)},unmountComponent:function(e){if(this._renderedComponent){var t=this._instance;if(t.componentWillUnmount&&!t._calledComponentWillUnmount)if(t._calledComponentWillUnmount=!0,e){var n=this.getName()+".componentWillUnmount()";ReactErrorUtils.invokeGuardedCallback(n,t.componentWillUnmount.bind(t))}else t.componentWillUnmount();this._renderedComponent&&(ReactReconciler.unmountComponent(this._renderedComponent,e),this._renderedNodeType=null,this._renderedComponent=null,this._instance=null),this._pendingStateQueue=null,this._pendingReplaceState=!1,this._pendingForceUpdate=!1,this._pendingCallbacks=null,this._pendingElement=null,this._context=null,this._rootNodeID=null,this._topLevelWrapper=null,ReactInstanceMap.remove(t)}},_maskContext:function(e){var t=this._currentElement.type,n=t.contextTypes;if(!n)return emptyObject;var o={};for(var i in n)o[i]=e[i];return o},_processContext:function(e){var t=this._maskContext(e);return t},_processChildContext:function(e){var t=this._currentElement.type,n=this._instance,o=n.getChildContext&&n.getChildContext();if(o){"object"!=typeof t.childContextTypes?_prodInvariant("107",this.getName()||"ReactCompositeComponent"):void 0;for(var i in o)i in t.childContextTypes?void 0:_prodInvariant("108",this.getName()||"ReactCompositeComponent",i);return _assign({},e,o)}return e},_checkContextTypes:function(e,t,n){checkReactTypeSpec(e,t,n,this.getName(),null,this._debugID)},receiveComponent:function(e,t,n){var o=this._currentElement,i=this._context;this._pendingElement=null,this.updateComponent(t,o,e,i,n)},performUpdateIfNecessary:function(e){null!=this._pendingElement?ReactReconciler.receiveComponent(this,this._pendingElement,e,this._context):null!==this._pendingStateQueue||this._pendingForceUpdate?this.updateComponent(e,this._currentElement,this._currentElement,this._context,this._context):this._updateBatchNumber=null},updateComponent:function(e,t,n,o,i){var r=this._instance;null==r?_prodInvariant("136",this.getName()||"ReactCompositeComponent"):void 0;var a,s,c=!1;this._context===i?a=r.context:(a=this._processContext(i),c=!0),s=n.props,t!==n&&(c=!0),c&&r.componentWillReceiveProps&&r.componentWillReceiveProps(s,a);var p=this._processPendingState(s,a),u=!0;!this._pendingForceUpdate&&r.shouldComponentUpdate&&(u=r.shouldComponentUpdate(s,p,a)),this._updateBatchNumber=null,u?(this._pendingForceUpdate=!1,this._performComponentUpdate(n,s,p,a,e,i)):(this._currentElement=n,this._context=i,r.props=s,r.state=p,r.context=a)},_processPendingState:function(e,t){var n=this._instance,o=this._pendingStateQueue,i=this._pendingReplaceState;if(this._pendingReplaceState=!1,this._pendingStateQueue=null,!o)return n.state;if(i&&1===o.length)return o[0];for(var r=_assign({},i?o[0]:n.state),a=i?1:0;a=0||null!=t.is}function ReactDOMComponent(e){var t=e.type;validateDangerousTag(t),this._currentElement=e,this._tag=t.toLowerCase(),this._namespaceURI=null,this._renderedChildren=null,this._previousStyle=null,this._previousStyleCopy=null,this._hostNode=null,this._hostParent=null,this._rootNodeID=null,this._domID=null,this._hostContainerInfo=null,this._wrapperState=null,this._topLevelWrapper=null,this._flags=0}var _prodInvariant=require("./reactProdInvariant"),_assign=require("object-assign"),AutoFocusUtils=require("./AutoFocusUtils"),CSSPropertyOperations=require("./CSSPropertyOperations"),DOMLazyTree=require("./DOMLazyTree"),DOMNamespaces=require("./DOMNamespaces"),DOMProperty=require("./DOMProperty"),DOMPropertyOperations=require("./DOMPropertyOperations"),EventConstants=require("./EventConstants"),EventPluginHub=require("./EventPluginHub"),EventPluginRegistry=require("./EventPluginRegistry"),ReactBrowserEventEmitter=require("./ReactBrowserEventEmitter"),ReactComponentBrowserEnvironment=require("./ReactComponentBrowserEnvironment"),ReactDOMButton=require("./ReactDOMButton"),ReactDOMComponentFlags=require("./ReactDOMComponentFlags"),ReactDOMComponentTree=require("./ReactDOMComponentTree"),ReactDOMInput=require("./ReactDOMInput"),ReactDOMOption=require("./ReactDOMOption"),ReactDOMSelect=require("./ReactDOMSelect"),ReactDOMTextarea=require("./ReactDOMTextarea"),ReactInstrumentation=require("./ReactInstrumentation"),ReactMultiChild=require("./ReactMultiChild"),ReactServerRenderingTransaction=require("./ReactServerRenderingTransaction"),emptyFunction=require("fbjs/lib/emptyFunction"),escapeTextContentForBrowser=require("./escapeTextContentForBrowser"),invariant=require("fbjs/lib/invariant"),isEventSupported=require("./isEventSupported"),keyOf=require("fbjs/lib/keyOf"),shallowEqual=require("fbjs/lib/shallowEqual"),validateDOMNesting=require("./validateDOMNesting"),warning=require("fbjs/lib/warning"),Flags=ReactDOMComponentFlags,deleteListener=EventPluginHub.deleteListener,getNode=ReactDOMComponentTree.getNodeFromInstance,listenTo=ReactBrowserEventEmitter.listenTo,registrationNameModules=EventPluginRegistry.registrationNameModules,CONTENT_TYPES={string:!0,number:!0},STYLE=keyOf({style:null}),HTML=keyOf({__html:null}),RESERVED_PROPS={children:null,dangerouslySetInnerHTML:null,suppressContentEditableWarning:null},DOC_FRAGMENT_TYPE=11,styleMutationWarning={},setContentChildForInstrumentation=emptyFunction,mediaEvents={topAbort:"abort",topCanPlay:"canplay",topCanPlayThrough:"canplaythrough",topDurationChange:"durationchange",topEmptied:"emptied",topEncrypted:"encrypted",topEnded:"ended",topError:"error",topLoadedData:"loadeddata",topLoadedMetadata:"loadedmetadata",topLoadStart:"loadstart",topPause:"pause",topPlay:"play",topPlaying:"playing",topProgress:"progress",topRateChange:"ratechange",topSeeked:"seeked",topSeeking:"seeking",topStalled:"stalled",topSuspend:"suspend",topTimeUpdate:"timeupdate",topVolumeChange:"volumechange",topWaiting:"waiting"},omittedCloseTags={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},newlineEatingTags={listing:!0,pre:!0,textarea:!0},voidElementTags=_assign({menuitem:!0},omittedCloseTags),VALID_TAG_REGEX=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,validatedTagCache={},hasOwnProperty={}.hasOwnProperty,globalIdCounter=1;ReactDOMComponent.displayName="ReactDOMComponent",ReactDOMComponent.Mixin={mountComponent:function(e,t,r,n){this._rootNodeID=globalIdCounter++,this._domID=r._idCounter++,this._hostParent=t,this._hostContainerInfo=r;var a=this._currentElement.props;switch(this._tag){case"audio":case"form":case"iframe":case"img":case"link":case"object":case"source":case"video":this._wrapperState={listeners:null},e.getReactMountReady().enqueue(trapBubbledEventsLocal,this);break;case"button":a=ReactDOMButton.getHostProps(this,a,t);break;case"input":ReactDOMInput.mountWrapper(this,a,t),a=ReactDOMInput.getHostProps(this,a),e.getReactMountReady().enqueue(trapBubbledEventsLocal,this);break;case"option":ReactDOMOption.mountWrapper(this,a,t),a=ReactDOMOption.getHostProps(this,a);break;case"select":ReactDOMSelect.mountWrapper(this,a,t),a=ReactDOMSelect.getHostProps(this,a),e.getReactMountReady().enqueue(trapBubbledEventsLocal,this);break;case"textarea":ReactDOMTextarea.mountWrapper(this,a,t),a=ReactDOMTextarea.getHostProps(this,a),e.getReactMountReady().enqueue(trapBubbledEventsLocal,this)}assertValidProps(this,a);var o,s;null!=t?(o=t._namespaceURI,s=t._tag):r._tag&&(o=r._namespaceURI,s=r._tag),(null==o||o===DOMNamespaces.svg&&"foreignobject"===s)&&(o=DOMNamespaces.html),o===DOMNamespaces.html&&("svg"===this._tag?o=DOMNamespaces.svg:"math"===this._tag&&(o=DOMNamespaces.mathml)),this._namespaceURI=o;var i;if(e.useCreateElement){var u,l=r._ownerDocument;if(o===DOMNamespaces.html)if("script"===this._tag){var p=l.createElement("div"),c=this._currentElement.type;p.innerHTML="<"+c+">",u=p.removeChild(p.firstChild)}else u=a.is?l.createElement(this._currentElement.type,a.is):l.createElement(this._currentElement.type);else u=l.createElementNS(o,this._currentElement.type);ReactDOMComponentTree.precacheNode(this,u),this._flags|=Flags.hasCachedChildNodes,this._hostParent||DOMPropertyOperations.setAttributeForRoot(u),this._updateDOMProperties(null,a,e);var d=DOMLazyTree(u);this._createInitialChildren(e,a,n,d),i=d}else{var h=this._createOpenTagMarkupAndPutListeners(e,a),g=this._createContentMarkup(e,a,n);i=!g&&omittedCloseTags[this._tag]?h+"/>":h+">"+g+""}switch(this._tag){case"input":e.getReactMountReady().enqueue(inputPostMount,this),a.autoFocus&&e.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent,this);break;case"textarea":e.getReactMountReady().enqueue(textareaPostMount,this),a.autoFocus&&e.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent,this);break;case"select":a.autoFocus&&e.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent,this);break;case"button":a.autoFocus&&e.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent,this);break;case"option":e.getReactMountReady().enqueue(optionPostMount,this)}return i},_createOpenTagMarkupAndPutListeners:function(e,t){var r="<"+this._currentElement.type;for(var n in t)if(t.hasOwnProperty(n)){var a=t[n];if(null!=a)if(registrationNameModules.hasOwnProperty(n))a&&enqueuePutListener(this,n,a,e);else{n===STYLE&&(a&&(a=this._previousStyleCopy=_assign({},t.style)),a=CSSPropertyOperations.createMarkupForStyles(a,this));var o=null;null!=this._tag&&isCustomComponent(this._tag,t)?RESERVED_PROPS.hasOwnProperty(n)||(o=DOMPropertyOperations.createMarkupForCustomAttribute(n,a)):o=DOMPropertyOperations.createMarkupForProperty(n,a),o&&(r+=" "+o)}}return e.renderToStaticMarkup?r:(this._hostParent||(r+=" "+DOMPropertyOperations.createMarkupForRoot()),r+=" "+DOMPropertyOperations.createMarkupForID(this._domID))},_createContentMarkup:function(e,t,r){var n="",a=t.dangerouslySetInnerHTML;if(null!=a)null!=a.__html&&(n=a.__html);else{var o=CONTENT_TYPES[typeof t.children]?t.children:null,s=null!=o?null:t.children;if(null!=o)n=escapeTextContentForBrowser(o);else if(null!=s){var i=this.mountChildren(s,e,r);n=i.join("")}}return newlineEatingTags[this._tag]&&"\n"===n.charAt(0)?"\n"+n:n},_createInitialChildren:function(e,t,r,n){var a=t.dangerouslySetInnerHTML;if(null!=a)null!=a.__html&&DOMLazyTree.queueHTML(n,a.__html);else{var o=CONTENT_TYPES[typeof t.children]?t.children:null,s=null!=o?null:t.children;if(null!=o)DOMLazyTree.queueText(n,o);else if(null!=s)for(var i=this.mountChildren(s,e,r),u=0;u"},receiveComponent:function(){},getHostNode:function(){return ReactDOMComponentTree.getNodeFromInstance(this)},unmountComponent:function(){ReactDOMComponentTree.uncacheNode(this)}}),module.exports=ReactDOMEmptyComponent; +_assign(CallbackQueue.prototype, { -},{"./DOMLazyTree":83,"./ReactDOMComponentTree":115,"object-assign":31}],118:[function(require,module,exports){ -"use strict";function createDOMFactory(e){return ReactElement.createFactory(e)}var ReactElement=require("./ReactElement"),mapObject=require("fbjs/lib/mapObject"),ReactDOMFactories=mapObject({a:"a",abbr:"abbr",address:"address",area:"area",article:"article",aside:"aside",audio:"audio",b:"b",base:"base",bdi:"bdi",bdo:"bdo",big:"big",blockquote:"blockquote",body:"body",br:"br",button:"button",canvas:"canvas",caption:"caption",cite:"cite",code:"code",col:"col",colgroup:"colgroup",data:"data",datalist:"datalist",dd:"dd",del:"del",details:"details",dfn:"dfn",dialog:"dialog",div:"div",dl:"dl",dt:"dt",em:"em",embed:"embed",fieldset:"fieldset",figcaption:"figcaption",figure:"figure",footer:"footer",form:"form",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",h6:"h6",head:"head",header:"header",hgroup:"hgroup",hr:"hr",html:"html",i:"i",iframe:"iframe",img:"img",input:"input",ins:"ins",kbd:"kbd",keygen:"keygen",label:"label",legend:"legend",li:"li",link:"link",main:"main",map:"map",mark:"mark",menu:"menu",menuitem:"menuitem",meta:"meta",meter:"meter",nav:"nav",noscript:"noscript",object:"object",ol:"ol",optgroup:"optgroup",option:"option",output:"output",p:"p",param:"param",picture:"picture",pre:"pre",progress:"progress",q:"q",rp:"rp",rt:"rt",ruby:"ruby",s:"s",samp:"samp",script:"script",section:"section",select:"select",small:"small",source:"source",span:"span",strong:"strong",style:"style",sub:"sub",summary:"summary",sup:"sup",table:"table",tbody:"tbody",td:"td",textarea:"textarea",tfoot:"tfoot",th:"th",thead:"thead",time:"time",title:"title",tr:"tr",track:"track",u:"u",ul:"ul",var:"var",video:"video",wbr:"wbr",circle:"circle",clipPath:"clipPath",defs:"defs",ellipse:"ellipse",g:"g",image:"image",line:"line",linearGradient:"linearGradient",mask:"mask",path:"path",pattern:"pattern",polygon:"polygon",polyline:"polyline",radialGradient:"radialGradient",rect:"rect",stop:"stop",svg:"svg",text:"text",tspan:"tspan"},createDOMFactory);module.exports=ReactDOMFactories; + /** + * Enqueues a callback to be invoked when `notifyAll` is invoked. + * + * @param {function} callback Invoked when `notifyAll` is invoked. + * @param {?object} context Context to call `callback` with. + * @internal + */ + enqueue: function (callback, context) { + this._callbacks = this._callbacks || []; + this._contexts = this._contexts || []; + this._callbacks.push(callback); + this._contexts.push(context); + }, -},{"./ReactElement":131,"fbjs/lib/mapObject":229}],119:[function(require,module,exports){ -"use strict";var ReactDOMFeatureFlags={useCreateElement:!0};module.exports=ReactDOMFeatureFlags; + /** + * Invokes all enqueued callbacks and clears the queue. This is invoked after + * the DOM representation of a component has been created or updated. + * + * @internal + */ + notifyAll: function () { + var callbacks = this._callbacks; + var contexts = this._contexts; + if (callbacks) { + !(callbacks.length === contexts.length) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : _prodInvariant('24') : void 0; + this._callbacks = null; + this._contexts = null; + for (var i = 0; i < callbacks.length; i++) { + callbacks[i].call(contexts[i]); + } + callbacks.length = 0; + contexts.length = 0; + } + }, -},{}],120:[function(require,module,exports){ -"use strict";var DOMChildrenOperations=require("./DOMChildrenOperations"),ReactDOMComponentTree=require("./ReactDOMComponentTree"),ReactDOMIDOperations={dangerouslyProcessChildrenUpdates:function(e,r){var t=ReactDOMComponentTree.getNodeFromInstance(e);DOMChildrenOperations.processUpdates(t,r)}};module.exports=ReactDOMIDOperations; + checkpoint: function () { + return this._callbacks ? this._callbacks.length : 0; + }, -},{"./DOMChildrenOperations":82,"./ReactDOMComponentTree":115}],121:[function(require,module,exports){ -"use strict";function forceUpdateIfMounted(){this._rootNodeID&&ReactDOMInput.updateWrapper(this)}function isControlled(e){var t="checkbox"===e.type||"radio"===e.type;return t?void 0!==e.checked:void 0!==e.value}function _handleChange(e){var t=this._currentElement.props,a=LinkedValueUtils.executeOnChange(t,e);ReactUpdates.asap(forceUpdateIfMounted,this);var n=t.name;if("radio"===t.type&&null!=n){for(var r=ReactDOMComponentTree.getNodeFromInstance(this),l=r;l.parentNode;)l=l.parentNode;for(var d=l.querySelectorAll("input[name="+JSON.stringify(""+n)+'][type="radio"]'),u=0;u 8); +} + +function manualDispatchChangeEvent(nativeEvent) { + var event = SyntheticEvent.getPooled(eventTypes.change, activeElementInst, nativeEvent, getEventTarget(nativeEvent)); + EventPropagators.accumulateTwoPhaseDispatches(event); + + // If change and propertychange bubbled, we'd just bind to it like all the + // other events and have it go through ReactBrowserEventEmitter. Since it + // doesn't, we manually listen for the events and so we have to enqueue and + // process the abstract event manually. + // + // Batching is necessary here in order to ensure that all event handlers run + // before the next rerender (including event handlers attached to ancestor + // elements instead of directly on the input). Without this, controlled + // components don't work properly in conjunction with event bubbling because + // the component is rerendered and the value reverted before all the event + // handlers can run. See https://github.com/facebook/react/issues/708. + ReactUpdates.batchedUpdates(runEventInBatch, event); +} + +function runEventInBatch(event) { + EventPluginHub.enqueueEvents(event); + EventPluginHub.processEventQueue(false); +} + +function startWatchingForChangeEventIE8(target, targetInst) { + activeElement = target; + activeElementInst = targetInst; + activeElement.attachEvent('onchange', manualDispatchChangeEvent); +} + +function stopWatchingForChangeEventIE8() { + if (!activeElement) { + return; + } + activeElement.detachEvent('onchange', manualDispatchChangeEvent); + activeElement = null; + activeElementInst = null; +} + +function getTargetInstForChangeEvent(topLevelType, targetInst) { + if (topLevelType === topLevelTypes.topChange) { + return targetInst; + } +} +function handleEventsForChangeEventIE8(topLevelType, target, targetInst) { + if (topLevelType === topLevelTypes.topFocus) { + // stopWatching() should be a noop here but we call it just in case we + // missed a blur event somehow. + stopWatchingForChangeEventIE8(); + startWatchingForChangeEventIE8(target, targetInst); + } else if (topLevelType === topLevelTypes.topBlur) { + stopWatchingForChangeEventIE8(); + } +} + +/** + * SECTION: handle `input` event + */ +var isInputEventSupported = false; +if (ExecutionEnvironment.canUseDOM) { + // IE9 claims to support the input event but fails to trigger it when + // deleting text, so we ignore its input events. + // IE10+ fire input events to often, such when a placeholder + // changes or when an input with a placeholder is focused. + isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 11); +} + +/** + * (For IE <=11) Replacement getter/setter for the `value` property that gets + * set on the active element. + */ +var newValueProp = { + get: function () { + return activeElementValueProp.get.call(this); + }, + set: function (val) { + // Cast to a string so we can do equality checks. + activeElementValue = '' + val; + activeElementValueProp.set.call(this, val); + } +}; + +/** + * (For IE <=11) Starts tracking propertychange events on the passed-in element + * and override the value property so that we can distinguish user events from + * value changes in JS. + */ +function startWatchingForValueChange(target, targetInst) { + activeElement = target; + activeElementInst = targetInst; + activeElementValue = target.value; + activeElementValueProp = Object.getOwnPropertyDescriptor(target.constructor.prototype, 'value'); + + // Not guarded in a canDefineProperty check: IE8 supports defineProperty only + // on DOM elements + Object.defineProperty(activeElement, 'value', newValueProp); + if (activeElement.attachEvent) { + activeElement.attachEvent('onpropertychange', handlePropertyChange); + } else { + activeElement.addEventListener('propertychange', handlePropertyChange, false); + } +} + +/** + * (For IE <=11) Removes the event listeners from the currently-tracked element, + * if any exists. + */ +function stopWatchingForValueChange() { + if (!activeElement) { + return; + } + + // delete restores the original property definition + delete activeElement.value; + + if (activeElement.detachEvent) { + activeElement.detachEvent('onpropertychange', handlePropertyChange); + } else { + activeElement.removeEventListener('propertychange', handlePropertyChange, false); + } + + activeElement = null; + activeElementInst = null; + activeElementValue = null; + activeElementValueProp = null; +} + +/** + * (For IE <=11) Handles a propertychange event, sending a `change` event if + * the value of the active element has changed. + */ +function handlePropertyChange(nativeEvent) { + if (nativeEvent.propertyName !== 'value') { + return; + } + var value = nativeEvent.srcElement.value; + if (value === activeElementValue) { + return; + } + activeElementValue = value; + + manualDispatchChangeEvent(nativeEvent); +} + +/** + * If a `change` event should be fired, returns the target's ID. + */ +function getTargetInstForInputEvent(topLevelType, targetInst) { + if (topLevelType === topLevelTypes.topInput) { + // In modern browsers (i.e., not IE8 or IE9), the input event is exactly + // what we want so fall through here and trigger an abstract event + return targetInst; + } +} + +function handleEventsForInputEventIE(topLevelType, target, targetInst) { + if (topLevelType === topLevelTypes.topFocus) { + // In IE8, we can capture almost all .value changes by adding a + // propertychange handler and looking for events with propertyName + // equal to 'value' + // In IE9-11, propertychange fires for most input events but is buggy and + // doesn't fire when text is deleted, but conveniently, selectionchange + // appears to fire in all of the remaining cases so we catch those and + // forward the event if the value has changed + // In either case, we don't want to call the event handler if the value + // is changed from JS so we redefine a setter for `.value` that updates + // our activeElementValue variable, allowing us to ignore those changes + // + // stopWatching() should be a noop here but we call it just in case we + // missed a blur event somehow. + stopWatchingForValueChange(); + startWatchingForValueChange(target, targetInst); + } else if (topLevelType === topLevelTypes.topBlur) { + stopWatchingForValueChange(); + } +} + +// For IE8 and IE9. +function getTargetInstForInputEventIE(topLevelType, targetInst) { + if (topLevelType === topLevelTypes.topSelectionChange || topLevelType === topLevelTypes.topKeyUp || topLevelType === topLevelTypes.topKeyDown) { + // On the selectionchange event, the target is just document which isn't + // helpful for us so just check activeElement instead. + // + // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire + // propertychange on the first input event after setting `value` from a + // script and fires only keydown, keypress, keyup. Catching keyup usually + // gets it and catching keydown lets us fire an event for the first + // keystroke if user does a key repeat (it'll be a little delayed: right + // before the second keystroke). Other input methods (e.g., paste) seem to + // fire selectionchange normally. + if (activeElement && activeElement.value !== activeElementValue) { + activeElementValue = activeElement.value; + return activeElementInst; + } + } +} + +/** + * SECTION: handle `click` event + */ +function shouldUseClickEvent(elem) { + // Use the `click` event to detect changes to checkbox and radio inputs. + // This approach works across all browsers, whereas `change` does not fire + // until `blur` in IE8. + return elem.nodeName && elem.nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio'); +} + +function getTargetInstForClickEvent(topLevelType, targetInst) { + if (topLevelType === topLevelTypes.topClick) { + return targetInst; + } +} + +/** + * This plugin creates an `onChange` event that normalizes change events + * across form elements. This event fires at a time when it's possible to + * change the element's value without seeing a flicker. + * + * Supported elements are: + * - input (see `isTextInputElement`) + * - textarea + * - select + */ +var ChangeEventPlugin = { + + eventTypes: eventTypes, + + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window; + + var getTargetInstFunc, handleEventFunc; + if (shouldUseChangeEvent(targetNode)) { + if (doesChangeEventBubble) { + getTargetInstFunc = getTargetInstForChangeEvent; + } else { + handleEventFunc = handleEventsForChangeEventIE8; + } + } else if (isTextInputElement(targetNode)) { + if (isInputEventSupported) { + getTargetInstFunc = getTargetInstForInputEvent; + } else { + getTargetInstFunc = getTargetInstForInputEventIE; + handleEventFunc = handleEventsForInputEventIE; + } + } else if (shouldUseClickEvent(targetNode)) { + getTargetInstFunc = getTargetInstForClickEvent; + } + + if (getTargetInstFunc) { + var inst = getTargetInstFunc(topLevelType, targetInst); + if (inst) { + var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, nativeEventTarget); + event.type = 'change'; + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; + } + } + + if (handleEventFunc) { + handleEventFunc(topLevelType, targetNode, targetInst); + } + } + +}; + +module.exports = ChangeEventPlugin; +},{"./EventConstants":97,"./EventPluginHub":98,"./EventPropagators":101,"./ReactDOMComponentTree":123,"./ReactUpdates":175,"./SyntheticEvent":184,"./getEventTarget":208,"./isEventSupported":215,"./isTextInputElement":216,"fbjs/lib/ExecutionEnvironment":227,"fbjs/lib/keyOf":245}],88:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule DOMChildrenOperations + */ + +'use strict'; + +var DOMLazyTree = require('./DOMLazyTree'); +var Danger = require('./Danger'); +var ReactMultiChildUpdateTypes = require('./ReactMultiChildUpdateTypes'); +var ReactDOMComponentTree = require('./ReactDOMComponentTree'); +var ReactInstrumentation = require('./ReactInstrumentation'); + +var createMicrosoftUnsafeLocalFunction = require('./createMicrosoftUnsafeLocalFunction'); +var setInnerHTML = require('./setInnerHTML'); +var setTextContent = require('./setTextContent'); + +function getNodeAfter(parentNode, node) { + // Special case for text components, which return [open, close] comments + // from getHostNode. + if (Array.isArray(node)) { + node = node[1]; + } + return node ? node.nextSibling : parentNode.firstChild; +} + +/** + * Inserts `childNode` as a child of `parentNode` at the `index`. + * + * @param {DOMElement} parentNode Parent node in which to insert. + * @param {DOMElement} childNode Child node to insert. + * @param {number} index Index at which to insert the child. + * @internal + */ +var insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) { + // We rely exclusively on `insertBefore(node, null)` instead of also using + // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so + // we are careful to use `null`.) + parentNode.insertBefore(childNode, referenceNode); +}); + +function insertLazyTreeChildAt(parentNode, childTree, referenceNode) { + DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode); +} + +function moveChild(parentNode, childNode, referenceNode) { + if (Array.isArray(childNode)) { + moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode); + } else { + insertChildAt(parentNode, childNode, referenceNode); + } +} + +function removeChild(parentNode, childNode) { + if (Array.isArray(childNode)) { + var closingComment = childNode[1]; + childNode = childNode[0]; + removeDelimitedText(parentNode, childNode, closingComment); + parentNode.removeChild(closingComment); + } + parentNode.removeChild(childNode); +} + +function moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) { + var node = openingComment; + while (true) { + var nextNode = node.nextSibling; + insertChildAt(parentNode, node, referenceNode); + if (node === closingComment) { + break; + } + node = nextNode; + } +} + +function removeDelimitedText(parentNode, startNode, closingComment) { + while (true) { + var node = startNode.nextSibling; + if (node === closingComment) { + // The closing comment is removed by ReactMultiChild. + break; + } else { + parentNode.removeChild(node); + } + } +} + +function replaceDelimitedText(openingComment, closingComment, stringText) { + var parentNode = openingComment.parentNode; + var nodeAfterComment = openingComment.nextSibling; + if (nodeAfterComment === closingComment) { + // There are no text nodes between the opening and closing comments; insert + // a new one if stringText isn't empty. + if (stringText) { + insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment); + } + } else { + if (stringText) { + // Set the text content of the first node after the opening comment, and + // remove all following nodes up until the closing comment. + setTextContent(nodeAfterComment, stringText); + removeDelimitedText(parentNode, nodeAfterComment, closingComment); + } else { + removeDelimitedText(parentNode, openingComment, closingComment); + } + } + + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(openingComment)._debugID, 'replace text', stringText); + } +} + +var dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup; +if (process.env.NODE_ENV !== 'production') { + dangerouslyReplaceNodeWithMarkup = function (oldChild, markup, prevInstance) { + Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup); + if (prevInstance._debugID !== 0) { + ReactInstrumentation.debugTool.onHostOperation(prevInstance._debugID, 'replace with', markup.toString()); + } else { + var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node); + if (nextInstance._debugID !== 0) { + ReactInstrumentation.debugTool.onHostOperation(nextInstance._debugID, 'mount', markup.toString()); + } + } + }; +} + +/** + * Operations for updating with DOM children. + */ +var DOMChildrenOperations = { + + dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup, + + replaceDelimitedText: replaceDelimitedText, + + /** + * Updates a component's children by processing a series of updates. The + * update configurations are each expected to have a `parentNode` property. + * + * @param {array} updates List of update configurations. + * @internal + */ + processUpdates: function (parentNode, updates) { + if (process.env.NODE_ENV !== 'production') { + var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(parentNode)._debugID; + } + + for (var k = 0; k < updates.length; k++) { + var update = updates[k]; + switch (update.type) { + case ReactMultiChildUpdateTypes.INSERT_MARKUP: + insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode)); + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'insert child', { toIndex: update.toIndex, content: update.content.toString() }); + } + break; + case ReactMultiChildUpdateTypes.MOVE_EXISTING: + moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode)); + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'move child', { fromIndex: update.fromIndex, toIndex: update.toIndex }); + } + break; + case ReactMultiChildUpdateTypes.SET_MARKUP: + setInnerHTML(parentNode, update.content); + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace children', update.content.toString()); + } + break; + case ReactMultiChildUpdateTypes.TEXT_CONTENT: + setTextContent(parentNode, update.content); + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace text', update.content.toString()); + } + break; + case ReactMultiChildUpdateTypes.REMOVE_NODE: + removeChild(parentNode, update.fromNode); + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'remove child', { fromIndex: update.fromIndex }); + } + break; + } + } + } + +}; + +module.exports = DOMChildrenOperations; +}).call(this,require('_process')) + +},{"./DOMLazyTree":89,"./Danger":93,"./ReactDOMComponentTree":123,"./ReactInstrumentation":155,"./ReactMultiChildUpdateTypes":160,"./createMicrosoftUnsafeLocalFunction":199,"./setInnerHTML":221,"./setTextContent":222,"_process":37}],89:[function(require,module,exports){ +/** + * Copyright 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule DOMLazyTree + */ + +'use strict'; + +var DOMNamespaces = require('./DOMNamespaces'); +var setInnerHTML = require('./setInnerHTML'); + +var createMicrosoftUnsafeLocalFunction = require('./createMicrosoftUnsafeLocalFunction'); +var setTextContent = require('./setTextContent'); + +var ELEMENT_NODE_TYPE = 1; +var DOCUMENT_FRAGMENT_NODE_TYPE = 11; + +/** + * In IE (8-11) and Edge, appending nodes with no children is dramatically + * faster than appending a full subtree, so we essentially queue up the + * .appendChild calls here and apply them so each node is added to its parent + * before any children are added. + * + * In other browsers, doing so is slower or neutral compared to the other order + * (in Firefox, twice as slow) so we only do this inversion in IE. + * + * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode. + */ +var enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\bEdge\/\d/.test(navigator.userAgent); + +function insertTreeChildren(tree) { + if (!enableLazy) { + return; + } + var node = tree.node; + var children = tree.children; + if (children.length) { + for (var i = 0; i < children.length; i++) { + insertTreeBefore(node, children[i], null); + } + } else if (tree.html != null) { + setInnerHTML(node, tree.html); + } else if (tree.text != null) { + setTextContent(node, tree.text); + } +} + +var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) { + // DocumentFragments aren't actually part of the DOM after insertion so + // appending children won't update the DOM. We need to ensure the fragment + // is properly populated first, breaking out of our lazy approach for just + // this level. Also, some plugins (like Flash Player) will read + // nodes immediately upon insertion into the DOM, so + // must also be populated prior to insertion into the DOM. + if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE || tree.node.nodeType === ELEMENT_NODE_TYPE && tree.node.nodeName.toLowerCase() === 'object' && (tree.node.namespaceURI == null || tree.node.namespaceURI === DOMNamespaces.html)) { + insertTreeChildren(tree); + parentNode.insertBefore(tree.node, referenceNode); + } else { + parentNode.insertBefore(tree.node, referenceNode); + insertTreeChildren(tree); + } +}); + +function replaceChildWithTree(oldNode, newTree) { + oldNode.parentNode.replaceChild(newTree.node, oldNode); + insertTreeChildren(newTree); +} + +function queueChild(parentTree, childTree) { + if (enableLazy) { + parentTree.children.push(childTree); + } else { + parentTree.node.appendChild(childTree.node); + } +} + +function queueHTML(tree, html) { + if (enableLazy) { + tree.html = html; + } else { + setInnerHTML(tree.node, html); + } +} + +function queueText(tree, text) { + if (enableLazy) { + tree.text = text; + } else { + setTextContent(tree.node, text); + } +} + +function toString() { + return this.node.nodeName; +} + +function DOMLazyTree(node) { + return { + node: node, + children: [], + html: null, + text: null, + toString: toString + }; +} + +DOMLazyTree.insertTreeBefore = insertTreeBefore; +DOMLazyTree.replaceChildWithTree = replaceChildWithTree; +DOMLazyTree.queueChild = queueChild; +DOMLazyTree.queueHTML = queueHTML; +DOMLazyTree.queueText = queueText; + +module.exports = DOMLazyTree; +},{"./DOMNamespaces":90,"./createMicrosoftUnsafeLocalFunction":199,"./setInnerHTML":221,"./setTextContent":222}],90:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule DOMNamespaces + */ + +'use strict'; + +var DOMNamespaces = { + html: 'http://www.w3.org/1999/xhtml', + mathml: 'http://www.w3.org/1998/Math/MathML', + svg: 'http://www.w3.org/2000/svg' +}; + +module.exports = DOMNamespaces; +},{}],91:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule DOMProperty + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var invariant = require('fbjs/lib/invariant'); + +function checkMask(value, bitmask) { + return (value & bitmask) === bitmask; +} + +var DOMPropertyInjection = { + /** + * Mapping from normalized, camelcased property names to a configuration that + * specifies how the associated DOM property should be accessed or rendered. + */ + MUST_USE_PROPERTY: 0x1, + HAS_BOOLEAN_VALUE: 0x4, + HAS_NUMERIC_VALUE: 0x8, + HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8, + HAS_OVERLOADED_BOOLEAN_VALUE: 0x20, + + /** + * Inject some specialized knowledge about the DOM. This takes a config object + * with the following properties: + * + * isCustomAttribute: function that given an attribute name will return true + * if it can be inserted into the DOM verbatim. Useful for data-* or aria-* + * attributes where it's impossible to enumerate all of the possible + * attribute names, + * + * Properties: object mapping DOM property name to one of the + * DOMPropertyInjection constants or null. If your attribute isn't in here, + * it won't get written to the DOM. + * + * DOMAttributeNames: object mapping React attribute name to the DOM + * attribute name. Attribute names not specified use the **lowercase** + * normalized name. + * + * DOMAttributeNamespaces: object mapping React attribute name to the DOM + * attribute namespace URL. (Attribute names not specified use no namespace.) + * + * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties. + * Property names not specified use the normalized name. + * + * DOMMutationMethods: Properties that require special mutation methods. If + * `value` is undefined, the mutation method should unset the property. + * + * @param {object} domPropertyConfig the config as described above. + */ + injectDOMPropertyConfig: function (domPropertyConfig) { + var Injection = DOMPropertyInjection; + var Properties = domPropertyConfig.Properties || {}; + var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {}; + var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {}; + var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {}; + var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {}; + + if (domPropertyConfig.isCustomAttribute) { + DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute); + } + + for (var propName in Properties) { + !!DOMProperty.properties.hasOwnProperty(propName) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property \'%s\' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.', propName) : _prodInvariant('48', propName) : void 0; + + var lowerCased = propName.toLowerCase(); + var propConfig = Properties[propName]; + + var propertyInfo = { + attributeName: lowerCased, + attributeNamespace: null, + propertyName: propName, + mutationMethod: null, + + mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY), + hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE), + hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE), + hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE), + hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE) + }; + !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s', propName) : _prodInvariant('50', propName) : void 0; + + if (process.env.NODE_ENV !== 'production') { + DOMProperty.getPossibleStandardName[lowerCased] = propName; + } + + if (DOMAttributeNames.hasOwnProperty(propName)) { + var attributeName = DOMAttributeNames[propName]; + propertyInfo.attributeName = attributeName; + if (process.env.NODE_ENV !== 'production') { + DOMProperty.getPossibleStandardName[attributeName] = propName; + } + } + + if (DOMAttributeNamespaces.hasOwnProperty(propName)) { + propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName]; + } + + if (DOMPropertyNames.hasOwnProperty(propName)) { + propertyInfo.propertyName = DOMPropertyNames[propName]; + } + + if (DOMMutationMethods.hasOwnProperty(propName)) { + propertyInfo.mutationMethod = DOMMutationMethods[propName]; + } + + DOMProperty.properties[propName] = propertyInfo; + } + } +}; + +/* eslint-disable max-len */ +var ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD'; +/* eslint-enable max-len */ + +/** + * DOMProperty exports lookup objects that can be used like functions: + * + * > DOMProperty.isValid['id'] + * true + * > DOMProperty.isValid['foobar'] + * undefined + * + * Although this may be confusing, it performs better in general. + * + * @see http://jsperf.com/key-exists + * @see http://jsperf.com/key-missing + */ +var DOMProperty = { + + ID_ATTRIBUTE_NAME: 'data-reactid', + ROOT_ATTRIBUTE_NAME: 'data-reactroot', + + ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR, + ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040', + + /** + * Map from property "standard name" to an object with info about how to set + * the property in the DOM. Each object contains: + * + * attributeName: + * Used when rendering markup or with `*Attribute()`. + * attributeNamespace + * propertyName: + * Used on DOM node instances. (This includes properties that mutate due to + * external factors.) + * mutationMethod: + * If non-null, used instead of the property or `setAttribute()` after + * initial render. + * mustUseProperty: + * Whether the property must be accessed and mutated as an object property. + * hasBooleanValue: + * Whether the property should be removed when set to a falsey value. + * hasNumericValue: + * Whether the property must be numeric or parse as a numeric and should be + * removed when set to a falsey value. + * hasPositiveNumericValue: + * Whether the property must be positive numeric or parse as a positive + * numeric and should be removed when set to a falsey value. + * hasOverloadedBooleanValue: + * Whether the property can be used as a flag as well as with a value. + * Removed when strictly equal to false; present without a value when + * strictly equal to true; present with a value otherwise. + */ + properties: {}, + + /** + * Mapping from lowercase property names to the properly cased version, used + * to warn in the case of missing properties. Available only in __DEV__. + * @type {Object} + */ + getPossibleStandardName: process.env.NODE_ENV !== 'production' ? {} : null, + + /** + * All of the isCustomAttribute() functions that have been injected. + */ + _isCustomAttributeFunctions: [], + + /** + * Checks whether a property name is a custom attribute. + * @method + */ + isCustomAttribute: function (attributeName) { + for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) { + var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i]; + if (isCustomAttributeFn(attributeName)) { + return true; + } + } + return false; + }, + + injection: DOMPropertyInjection +}; + +module.exports = DOMProperty; +}).call(this,require('_process')) + +},{"./reactProdInvariant":219,"_process":37,"fbjs/lib/invariant":241}],92:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule DOMPropertyOperations + */ + +'use strict'; + +var DOMProperty = require('./DOMProperty'); +var ReactDOMComponentTree = require('./ReactDOMComponentTree'); +var ReactDOMInstrumentation = require('./ReactDOMInstrumentation'); +var ReactInstrumentation = require('./ReactInstrumentation'); + +var quoteAttributeValueForBrowser = require('./quoteAttributeValueForBrowser'); +var warning = require('fbjs/lib/warning'); + +var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$'); +var illegalAttributeNameCache = {}; +var validatedAttributeNameCache = {}; + +function isAttributeNameSafe(attributeName) { + if (validatedAttributeNameCache.hasOwnProperty(attributeName)) { + return true; + } + if (illegalAttributeNameCache.hasOwnProperty(attributeName)) { + return false; + } + if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { + validatedAttributeNameCache[attributeName] = true; + return true; + } + illegalAttributeNameCache[attributeName] = true; + process.env.NODE_ENV !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0; + return false; +} + +function shouldIgnoreValue(propertyInfo, value) { + return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false; +} + +/** + * Operations for dealing with DOM properties. + */ +var DOMPropertyOperations = { + + /** + * Creates markup for the ID property. + * + * @param {string} id Unescaped ID. + * @return {string} Markup string. + */ + createMarkupForID: function (id) { + return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id); + }, + + setAttributeForID: function (node, id) { + node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id); + }, + + createMarkupForRoot: function () { + return DOMProperty.ROOT_ATTRIBUTE_NAME + '=""'; + }, + + setAttributeForRoot: function (node) { + node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, ''); + }, + + /** + * Creates markup for a property. + * + * @param {string} name + * @param {*} value + * @return {?string} Markup string, or null if the property was invalid. + */ + createMarkupForProperty: function (name, value) { + if (process.env.NODE_ENV !== 'production') { + ReactDOMInstrumentation.debugTool.onCreateMarkupForProperty(name, value); + } + var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; + if (propertyInfo) { + if (shouldIgnoreValue(propertyInfo, value)) { + return ''; + } + var attributeName = propertyInfo.attributeName; + if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) { + return attributeName + '=""'; + } + return attributeName + '=' + quoteAttributeValueForBrowser(value); + } else if (DOMProperty.isCustomAttribute(name)) { + if (value == null) { + return ''; + } + return name + '=' + quoteAttributeValueForBrowser(value); + } + return null; + }, + + /** + * Creates markup for a custom property. + * + * @param {string} name + * @param {*} value + * @return {string} Markup string, or empty string if the property was invalid. + */ + createMarkupForCustomAttribute: function (name, value) { + if (!isAttributeNameSafe(name) || value == null) { + return ''; + } + return name + '=' + quoteAttributeValueForBrowser(value); + }, + + /** + * Sets the value for a property on a node. + * + * @param {DOMElement} node + * @param {string} name + * @param {*} value + */ + setValueForProperty: function (node, name, value) { + var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; + if (propertyInfo) { + var mutationMethod = propertyInfo.mutationMethod; + if (mutationMethod) { + mutationMethod(node, value); + } else if (shouldIgnoreValue(propertyInfo, value)) { + this.deleteValueForProperty(node, name); + return; + } else if (propertyInfo.mustUseProperty) { + // Contrary to `setAttribute`, object properties are properly + // `toString`ed by IE8/9. + node[propertyInfo.propertyName] = value; + } else { + var attributeName = propertyInfo.attributeName; + var namespace = propertyInfo.attributeNamespace; + // `setAttribute` with objects becomes only `[object]` in IE8/9, + // ('' + value) makes it output the correct toString()-value. + if (namespace) { + node.setAttributeNS(namespace, attributeName, '' + value); + } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) { + node.setAttribute(attributeName, ''); + } else { + node.setAttribute(attributeName, '' + value); + } + } + } else if (DOMProperty.isCustomAttribute(name)) { + DOMPropertyOperations.setValueForAttribute(node, name, value); + return; + } + + if (process.env.NODE_ENV !== 'production') { + ReactDOMInstrumentation.debugTool.onSetValueForProperty(node, name, value); + var payload = {}; + payload[name] = value; + ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload); + } + }, + + setValueForAttribute: function (node, name, value) { + if (!isAttributeNameSafe(name)) { + return; + } + if (value == null) { + node.removeAttribute(name); + } else { + node.setAttribute(name, '' + value); + } + + if (process.env.NODE_ENV !== 'production') { + var payload = {}; + payload[name] = value; + ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload); + } + }, + + /** + * Deletes an attributes from a node. + * + * @param {DOMElement} node + * @param {string} name + */ + deleteValueForAttribute: function (node, name) { + node.removeAttribute(name); + if (process.env.NODE_ENV !== 'production') { + ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name); + ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name); + } + }, + + /** + * Deletes the value for a property on a node. + * + * @param {DOMElement} node + * @param {string} name + */ + deleteValueForProperty: function (node, name) { + var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null; + if (propertyInfo) { + var mutationMethod = propertyInfo.mutationMethod; + if (mutationMethod) { + mutationMethod(node, undefined); + } else if (propertyInfo.mustUseProperty) { + var propName = propertyInfo.propertyName; + if (propertyInfo.hasBooleanValue) { + node[propName] = false; + } else { + node[propName] = ''; + } + } else { + node.removeAttribute(propertyInfo.attributeName); + } + } else if (DOMProperty.isCustomAttribute(name)) { + node.removeAttribute(name); + } + + if (process.env.NODE_ENV !== 'production') { + ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name); + ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name); + } + } + +}; + +module.exports = DOMPropertyOperations; +}).call(this,require('_process')) + +},{"./DOMProperty":91,"./ReactDOMComponentTree":123,"./ReactDOMInstrumentation":131,"./ReactInstrumentation":155,"./quoteAttributeValueForBrowser":218,"_process":37,"fbjs/lib/warning":251}],93:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule Danger + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var DOMLazyTree = require('./DOMLazyTree'); +var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment'); + +var createNodesFromMarkup = require('fbjs/lib/createNodesFromMarkup'); +var emptyFunction = require('fbjs/lib/emptyFunction'); +var invariant = require('fbjs/lib/invariant'); + +var Danger = { + + /** + * Replaces a node with a string of markup at its current position within its + * parent. The markup must render into a single root node. + * + * @param {DOMElement} oldChild Child node to replace. + * @param {string} markup Markup to render in place of the child node. + * @internal + */ + dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) { + !ExecutionEnvironment.canUseDOM ? process.env.NODE_ENV !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('56') : void 0; + !markup ? process.env.NODE_ENV !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : _prodInvariant('57') : void 0; + !(oldChild.nodeName !== 'HTML') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().') : _prodInvariant('58') : void 0; + + if (typeof markup === 'string') { + var newChild = createNodesFromMarkup(markup, emptyFunction)[0]; + oldChild.parentNode.replaceChild(newChild, oldChild); + } else { + DOMLazyTree.replaceChildWithTree(oldChild, markup); + } + } + +}; + +module.exports = Danger; +}).call(this,require('_process')) + +},{"./DOMLazyTree":89,"./reactProdInvariant":219,"_process":37,"fbjs/lib/ExecutionEnvironment":227,"fbjs/lib/createNodesFromMarkup":232,"fbjs/lib/emptyFunction":233,"fbjs/lib/invariant":241}],94:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule DefaultEventPluginOrder + */ + +'use strict'; + +var keyOf = require('fbjs/lib/keyOf'); + +/** + * Module that is injectable into `EventPluginHub`, that specifies a + * deterministic ordering of `EventPlugin`s. A convenient way to reason about + * plugins, without having to package every one of them. This is better than + * having plugins be ordered in the same order that they are injected because + * that ordering would be influenced by the packaging order. + * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that + * preventing default on events is convenient in `SimpleEventPlugin` handlers. + */ +var DefaultEventPluginOrder = [keyOf({ ResponderEventPlugin: null }), keyOf({ SimpleEventPlugin: null }), keyOf({ TapEventPlugin: null }), keyOf({ EnterLeaveEventPlugin: null }), keyOf({ ChangeEventPlugin: null }), keyOf({ SelectEventPlugin: null }), keyOf({ BeforeInputEventPlugin: null })]; + +module.exports = DefaultEventPluginOrder; +},{"fbjs/lib/keyOf":245}],95:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule DisabledInputUtils + */ + +'use strict'; + +var disableableMouseListenerNames = { + onClick: true, + onDoubleClick: true, + onMouseDown: true, + onMouseMove: true, + onMouseUp: true, + + onClickCapture: true, + onDoubleClickCapture: true, + onMouseDownCapture: true, + onMouseMoveCapture: true, + onMouseUpCapture: true +}; + +/** + * Implements a host component that does not receive mouse events + * when `disabled` is set. + */ +var DisabledInputUtils = { + getHostProps: function (inst, props) { + if (!props.disabled) { + return props; + } + + // Copy the props, except the mouse listeners + var hostProps = {}; + for (var key in props) { + if (!disableableMouseListenerNames[key] && props.hasOwnProperty(key)) { + hostProps[key] = props[key]; + } + } + + return hostProps; + } +}; + +module.exports = DisabledInputUtils; +},{}],96:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule EnterLeaveEventPlugin + */ + +'use strict'; + +var EventConstants = require('./EventConstants'); +var EventPropagators = require('./EventPropagators'); +var ReactDOMComponentTree = require('./ReactDOMComponentTree'); +var SyntheticMouseEvent = require('./SyntheticMouseEvent'); + +var keyOf = require('fbjs/lib/keyOf'); + +var topLevelTypes = EventConstants.topLevelTypes; + +var eventTypes = { + mouseEnter: { + registrationName: keyOf({ onMouseEnter: null }), + dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver] + }, + mouseLeave: { + registrationName: keyOf({ onMouseLeave: null }), + dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver] + } +}; + +var EnterLeaveEventPlugin = { + + eventTypes: eventTypes, + + /** + * For almost every interaction we care about, there will be both a top-level + * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that + * we do not extract duplicate events. However, moving the mouse into the + * browser from outside will not fire a `mouseout` event. In this case, we use + * the `mouseover` top-level event. + */ + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) { + return null; + } + if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) { + // Must not be a mouse in or mouse out - ignoring. + return null; + } + + var win; + if (nativeEventTarget.window === nativeEventTarget) { + // `nativeEventTarget` is probably a window object. + win = nativeEventTarget; + } else { + // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. + var doc = nativeEventTarget.ownerDocument; + if (doc) { + win = doc.defaultView || doc.parentWindow; + } else { + win = window; + } + } + + var from; + var to; + if (topLevelType === topLevelTypes.topMouseOut) { + from = targetInst; + var related = nativeEvent.relatedTarget || nativeEvent.toElement; + to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null; + } else { + // Moving to a node from outside the window. + from = null; + to = targetInst; + } + + if (from === to) { + // Nothing pertains to our managed components. + return null; + } + + var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from); + var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to); + + var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget); + leave.type = 'mouseleave'; + leave.target = fromNode; + leave.relatedTarget = toNode; + + var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget); + enter.type = 'mouseenter'; + enter.target = toNode; + enter.relatedTarget = fromNode; + + EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to); + + return [leave, enter]; + } + +}; + +module.exports = EnterLeaveEventPlugin; +},{"./EventConstants":97,"./EventPropagators":101,"./ReactDOMComponentTree":123,"./SyntheticMouseEvent":188,"fbjs/lib/keyOf":245}],97:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule EventConstants + */ + +'use strict'; + +var keyMirror = require('fbjs/lib/keyMirror'); + +var PropagationPhases = keyMirror({ bubbled: null, captured: null }); + +/** + * Types of raw signals from the browser caught at the top level. + */ +var topLevelTypes = keyMirror({ + topAbort: null, + topAnimationEnd: null, + topAnimationIteration: null, + topAnimationStart: null, + topBlur: null, + topCanPlay: null, + topCanPlayThrough: null, + topChange: null, + topClick: null, + topCompositionEnd: null, + topCompositionStart: null, + topCompositionUpdate: null, + topContextMenu: null, + topCopy: null, + topCut: null, + topDoubleClick: null, + topDrag: null, + topDragEnd: null, + topDragEnter: null, + topDragExit: null, + topDragLeave: null, + topDragOver: null, + topDragStart: null, + topDrop: null, + topDurationChange: null, + topEmptied: null, + topEncrypted: null, + topEnded: null, + topError: null, + topFocus: null, + topInput: null, + topInvalid: null, + topKeyDown: null, + topKeyPress: null, + topKeyUp: null, + topLoad: null, + topLoadedData: null, + topLoadedMetadata: null, + topLoadStart: null, + topMouseDown: null, + topMouseMove: null, + topMouseOut: null, + topMouseOver: null, + topMouseUp: null, + topPaste: null, + topPause: null, + topPlay: null, + topPlaying: null, + topProgress: null, + topRateChange: null, + topReset: null, + topScroll: null, + topSeeked: null, + topSeeking: null, + topSelectionChange: null, + topStalled: null, + topSubmit: null, + topSuspend: null, + topTextInput: null, + topTimeUpdate: null, + topTouchCancel: null, + topTouchEnd: null, + topTouchMove: null, + topTouchStart: null, + topTransitionEnd: null, + topVolumeChange: null, + topWaiting: null, + topWheel: null +}); + +var EventConstants = { + topLevelTypes: topLevelTypes, + PropagationPhases: PropagationPhases +}; + +module.exports = EventConstants; +},{"fbjs/lib/keyMirror":244}],98:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule EventPluginHub + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var EventPluginRegistry = require('./EventPluginRegistry'); +var EventPluginUtils = require('./EventPluginUtils'); +var ReactErrorUtils = require('./ReactErrorUtils'); + +var accumulateInto = require('./accumulateInto'); +var forEachAccumulated = require('./forEachAccumulated'); +var invariant = require('fbjs/lib/invariant'); + +/** + * Internal store for event listeners + */ +var listenerBank = {}; + +/** + * Internal queue of events that have accumulated their dispatches and are + * waiting to have their dispatches executed. + */ +var eventQueue = null; + +/** + * Dispatches an event and releases it back into the pool, unless persistent. + * + * @param {?object} event Synthetic event to be dispatched. + * @param {boolean} simulated If the event is simulated (changes exn behavior) + * @private + */ +var executeDispatchesAndRelease = function (event, simulated) { + if (event) { + EventPluginUtils.executeDispatchesInOrder(event, simulated); + + if (!event.isPersistent()) { + event.constructor.release(event); + } + } +}; +var executeDispatchesAndReleaseSimulated = function (e) { + return executeDispatchesAndRelease(e, true); +}; +var executeDispatchesAndReleaseTopLevel = function (e) { + return executeDispatchesAndRelease(e, false); +}; + +var getDictionaryKey = function (inst) { + return '.' + inst._rootNodeID; +}; + +/** + * This is a unified interface for event plugins to be installed and configured. + * + * Event plugins can implement the following properties: + * + * `extractEvents` {function(string, DOMEventTarget, string, object): *} + * Required. When a top-level event is fired, this method is expected to + * extract synthetic events that will in turn be queued and dispatched. + * + * `eventTypes` {object} + * Optional, plugins that fire events must publish a mapping of registration + * names that are used to register listeners. Values of this mapping must + * be objects that contain `registrationName` or `phasedRegistrationNames`. + * + * `executeDispatch` {function(object, function, string)} + * Optional, allows plugins to override how an event gets dispatched. By + * default, the listener is simply invoked. + * + * Each plugin that is injected into `EventsPluginHub` is immediately operable. + * + * @public + */ +var EventPluginHub = { + + /** + * Methods for injecting dependencies. + */ + injection: { + + /** + * @param {array} InjectedEventPluginOrder + * @public + */ + injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder, + + /** + * @param {object} injectedNamesToPlugins Map from names to plugin modules. + */ + injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName + + }, + + /** + * Stores `listener` at `listenerBank[registrationName][key]`. Is idempotent. + * + * @param {object} inst The instance, which is the source of events. + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @param {function} listener The callback to store. + */ + putListener: function (inst, registrationName, listener) { + !(typeof listener === 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : _prodInvariant('94', registrationName, typeof listener) : void 0; + + var key = getDictionaryKey(inst); + var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {}); + bankForRegistrationName[key] = listener; + + var PluginModule = EventPluginRegistry.registrationNameModules[registrationName]; + if (PluginModule && PluginModule.didPutListener) { + PluginModule.didPutListener(inst, registrationName, listener); + } + }, + + /** + * @param {object} inst The instance, which is the source of events. + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @return {?function} The stored callback. + */ + getListener: function (inst, registrationName) { + var bankForRegistrationName = listenerBank[registrationName]; + var key = getDictionaryKey(inst); + return bankForRegistrationName && bankForRegistrationName[key]; + }, + + /** + * Deletes a listener from the registration bank. + * + * @param {object} inst The instance, which is the source of events. + * @param {string} registrationName Name of listener (e.g. `onClick`). + */ + deleteListener: function (inst, registrationName) { + var PluginModule = EventPluginRegistry.registrationNameModules[registrationName]; + if (PluginModule && PluginModule.willDeleteListener) { + PluginModule.willDeleteListener(inst, registrationName); + } + + var bankForRegistrationName = listenerBank[registrationName]; + // TODO: This should never be null -- when is it? + if (bankForRegistrationName) { + var key = getDictionaryKey(inst); + delete bankForRegistrationName[key]; + } + }, + + /** + * Deletes all listeners for the DOM element with the supplied ID. + * + * @param {object} inst The instance, which is the source of events. + */ + deleteAllListeners: function (inst) { + var key = getDictionaryKey(inst); + for (var registrationName in listenerBank) { + if (!listenerBank.hasOwnProperty(registrationName)) { + continue; + } + + if (!listenerBank[registrationName][key]) { + continue; + } + + var PluginModule = EventPluginRegistry.registrationNameModules[registrationName]; + if (PluginModule && PluginModule.willDeleteListener) { + PluginModule.willDeleteListener(inst, registrationName); + } + + delete listenerBank[registrationName][key]; + } + }, + + /** + * Allows registered plugins an opportunity to extract events from top-level + * native browser events. + * + * @return {*} An accumulation of synthetic events. + * @internal + */ + extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { + var events; + var plugins = EventPluginRegistry.plugins; + for (var i = 0; i < plugins.length; i++) { + // Not every plugin in the ordering may be loaded at runtime. + var possiblePlugin = plugins[i]; + if (possiblePlugin) { + var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget); + if (extractedEvents) { + events = accumulateInto(events, extractedEvents); + } + } + } + return events; + }, + + /** + * Enqueues a synthetic event that should be dispatched when + * `processEventQueue` is invoked. + * + * @param {*} events An accumulation of synthetic events. + * @internal + */ + enqueueEvents: function (events) { + if (events) { + eventQueue = accumulateInto(eventQueue, events); + } + }, + + /** + * Dispatches all synthetic events on the event queue. + * + * @internal + */ + processEventQueue: function (simulated) { + // Set `eventQueue` to null before processing it so that we can tell if more + // events get enqueued while processing. + var processingEventQueue = eventQueue; + eventQueue = null; + if (simulated) { + forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated); + } else { + forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); + } + !!eventQueue ? process.env.NODE_ENV !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : _prodInvariant('95') : void 0; + // This would be a good time to rethrow if any of the event handlers threw. + ReactErrorUtils.rethrowCaughtError(); + }, + + /** + * These are needed for tests only. Do not use! + */ + __purge: function () { + listenerBank = {}; + }, + + __getListenerBank: function () { + return listenerBank; + } + +}; + +module.exports = EventPluginHub; +}).call(this,require('_process')) + +},{"./EventPluginRegistry":99,"./EventPluginUtils":100,"./ReactErrorUtils":146,"./accumulateInto":195,"./forEachAccumulated":204,"./reactProdInvariant":219,"_process":37,"fbjs/lib/invariant":241}],99:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule EventPluginRegistry + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var invariant = require('fbjs/lib/invariant'); + +/** + * Injectable ordering of event plugins. + */ +var EventPluginOrder = null; + +/** + * Injectable mapping from names to event plugin modules. + */ +var namesToPlugins = {}; + +/** + * Recomputes the plugin list using the injected plugins and plugin ordering. + * + * @private + */ +function recomputePluginOrdering() { + if (!EventPluginOrder) { + // Wait until an `EventPluginOrder` is injected. + return; + } + for (var pluginName in namesToPlugins) { + var PluginModule = namesToPlugins[pluginName]; + var pluginIndex = EventPluginOrder.indexOf(pluginName); + !(pluginIndex > -1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : _prodInvariant('96', pluginName) : void 0; + if (EventPluginRegistry.plugins[pluginIndex]) { + continue; + } + !PluginModule.extractEvents ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : _prodInvariant('97', pluginName) : void 0; + EventPluginRegistry.plugins[pluginIndex] = PluginModule; + var publishedEvents = PluginModule.eventTypes; + for (var eventName in publishedEvents) { + !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : _prodInvariant('98', eventName, pluginName) : void 0; + } + } +} + +/** + * Publishes an event so that it can be dispatched by the supplied plugin. + * + * @param {object} dispatchConfig Dispatch configuration for the event. + * @param {object} PluginModule Plugin publishing the event. + * @return {boolean} True if the event was successfully published. + * @private + */ +function publishEventForPlugin(dispatchConfig, PluginModule, eventName) { + !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : _prodInvariant('99', eventName) : void 0; + EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig; + + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + if (phasedRegistrationNames) { + for (var phaseName in phasedRegistrationNames) { + if (phasedRegistrationNames.hasOwnProperty(phaseName)) { + var phasedRegistrationName = phasedRegistrationNames[phaseName]; + publishRegistrationName(phasedRegistrationName, PluginModule, eventName); + } + } + return true; + } else if (dispatchConfig.registrationName) { + publishRegistrationName(dispatchConfig.registrationName, PluginModule, eventName); + return true; + } + return false; +} + +/** + * Publishes a registration name that is used to identify dispatched events and + * can be used with `EventPluginHub.putListener` to register listeners. + * + * @param {string} registrationName Registration name to add. + * @param {object} PluginModule Plugin publishing the event. + * @private + */ +function publishRegistrationName(registrationName, PluginModule, eventName) { + !!EventPluginRegistry.registrationNameModules[registrationName] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : _prodInvariant('100', registrationName) : void 0; + EventPluginRegistry.registrationNameModules[registrationName] = PluginModule; + EventPluginRegistry.registrationNameDependencies[registrationName] = PluginModule.eventTypes[eventName].dependencies; + + if (process.env.NODE_ENV !== 'production') { + var lowerCasedName = registrationName.toLowerCase(); + EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName; + + if (registrationName === 'onDoubleClick') { + EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName; + } + } +} + +/** + * Registers plugins so that they can extract and dispatch events. + * + * @see {EventPluginHub} + */ +var EventPluginRegistry = { + + /** + * Ordered list of injected plugins. + */ + plugins: [], + + /** + * Mapping from event name to dispatch config + */ + eventNameDispatchConfigs: {}, + + /** + * Mapping from registration name to plugin module + */ + registrationNameModules: {}, + + /** + * Mapping from registration name to event name + */ + registrationNameDependencies: {}, + + /** + * Mapping from lowercase registration names to the properly cased version, + * used to warn in the case of missing event handlers. Available + * only in __DEV__. + * @type {Object} + */ + possibleRegistrationNames: process.env.NODE_ENV !== 'production' ? {} : null, + + /** + * Injects an ordering of plugins (by plugin name). This allows the ordering + * to be decoupled from injection of the actual plugins so that ordering is + * always deterministic regardless of packaging, on-the-fly injection, etc. + * + * @param {array} InjectedEventPluginOrder + * @internal + * @see {EventPluginHub.injection.injectEventPluginOrder} + */ + injectEventPluginOrder: function (InjectedEventPluginOrder) { + !!EventPluginOrder ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : _prodInvariant('101') : void 0; + // Clone the ordering so it cannot be dynamically mutated. + EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder); + recomputePluginOrdering(); + }, + + /** + * Injects plugins to be used by `EventPluginHub`. The plugin names must be + * in the ordering injected by `injectEventPluginOrder`. + * + * Plugins can be injected as part of page initialization or on-the-fly. + * + * @param {object} injectedNamesToPlugins Map from names to plugin modules. + * @internal + * @see {EventPluginHub.injection.injectEventPluginsByName} + */ + injectEventPluginsByName: function (injectedNamesToPlugins) { + var isOrderingDirty = false; + for (var pluginName in injectedNamesToPlugins) { + if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { + continue; + } + var PluginModule = injectedNamesToPlugins[pluginName]; + if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== PluginModule) { + !!namesToPlugins[pluginName] ? process.env.NODE_ENV !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : _prodInvariant('102', pluginName) : void 0; + namesToPlugins[pluginName] = PluginModule; + isOrderingDirty = true; + } + } + if (isOrderingDirty) { + recomputePluginOrdering(); + } + }, + + /** + * Looks up the plugin for the supplied event. + * + * @param {object} event A synthetic event. + * @return {?object} The plugin that created the supplied event. + * @internal + */ + getPluginModuleForEvent: function (event) { + var dispatchConfig = event.dispatchConfig; + if (dispatchConfig.registrationName) { + return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null; + } + for (var phase in dispatchConfig.phasedRegistrationNames) { + if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) { + continue; + } + var PluginModule = EventPluginRegistry.registrationNameModules[dispatchConfig.phasedRegistrationNames[phase]]; + if (PluginModule) { + return PluginModule; + } + } + return null; + }, + + /** + * Exposed for unit testing. + * @private + */ + _resetEventPlugins: function () { + EventPluginOrder = null; + for (var pluginName in namesToPlugins) { + if (namesToPlugins.hasOwnProperty(pluginName)) { + delete namesToPlugins[pluginName]; + } + } + EventPluginRegistry.plugins.length = 0; + + var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs; + for (var eventName in eventNameDispatchConfigs) { + if (eventNameDispatchConfigs.hasOwnProperty(eventName)) { + delete eventNameDispatchConfigs[eventName]; + } + } + + var registrationNameModules = EventPluginRegistry.registrationNameModules; + for (var registrationName in registrationNameModules) { + if (registrationNameModules.hasOwnProperty(registrationName)) { + delete registrationNameModules[registrationName]; + } + } + + if (process.env.NODE_ENV !== 'production') { + var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames; + for (var lowerCasedName in possibleRegistrationNames) { + if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) { + delete possibleRegistrationNames[lowerCasedName]; + } + } + } + } + +}; + +module.exports = EventPluginRegistry; +}).call(this,require('_process')) + +},{"./reactProdInvariant":219,"_process":37,"fbjs/lib/invariant":241}],100:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule EventPluginUtils + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var EventConstants = require('./EventConstants'); +var ReactErrorUtils = require('./ReactErrorUtils'); + +var invariant = require('fbjs/lib/invariant'); +var warning = require('fbjs/lib/warning'); + +/** + * Injected dependencies: + */ + +/** + * - `ComponentTree`: [required] Module that can convert between React instances + * and actual node references. + */ +var ComponentTree; +var TreeTraversal; +var injection = { + injectComponentTree: function (Injected) { + ComponentTree = Injected; + if (process.env.NODE_ENV !== 'production') { + process.env.NODE_ENV !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0; + } + }, + injectTreeTraversal: function (Injected) { + TreeTraversal = Injected; + if (process.env.NODE_ENV !== 'production') { + process.env.NODE_ENV !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0; + } + } +}; + +var topLevelTypes = EventConstants.topLevelTypes; + +function isEndish(topLevelType) { + return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel; +} + +function isMoveish(topLevelType) { + return topLevelType === topLevelTypes.topMouseMove || topLevelType === topLevelTypes.topTouchMove; +} +function isStartish(topLevelType) { + return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart; +} + +var validateEventDispatches; +if (process.env.NODE_ENV !== 'production') { + validateEventDispatches = function (event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + + var listenersIsArr = Array.isArray(dispatchListeners); + var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0; + + var instancesIsArr = Array.isArray(dispatchInstances); + var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0; + + process.env.NODE_ENV !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0; + }; +} + +/** + * Dispatch the event to the listener. + * @param {SyntheticEvent} event SyntheticEvent to handle + * @param {boolean} simulated If the event is simulated (changes exn behavior) + * @param {function} listener Application-level callback + * @param {*} inst Internal component instance + */ +function executeDispatch(event, simulated, listener, inst) { + var type = event.type || 'unknown-event'; + event.currentTarget = EventPluginUtils.getNodeFromInstance(inst); + if (simulated) { + ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event); + } else { + ReactErrorUtils.invokeGuardedCallback(type, listener, event); + } + event.currentTarget = null; +} + +/** + * Standard/simple iteration through an event's collected dispatches. + */ +function executeDispatchesInOrder(event, simulated) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + if (process.env.NODE_ENV !== 'production') { + validateEventDispatches(event); + } + if (Array.isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } + // Listeners and Instances are two parallel arrays that are always in sync. + executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]); + } + } else if (dispatchListeners) { + executeDispatch(event, simulated, dispatchListeners, dispatchInstances); + } + event._dispatchListeners = null; + event._dispatchInstances = null; +} + +/** + * Standard/simple iteration through an event's collected dispatches, but stops + * at the first dispatch execution returning true, and returns that id. + * + * @return {?string} id of the first dispatch execution who's listener returns + * true, or null if no listener returned true. + */ +function executeDispatchesInOrderStopAtTrueImpl(event) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + if (process.env.NODE_ENV !== 'production') { + validateEventDispatches(event); + } + if (Array.isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } + // Listeners and Instances are two parallel arrays that are always in sync. + if (dispatchListeners[i](event, dispatchInstances[i])) { + return dispatchInstances[i]; + } + } + } else if (dispatchListeners) { + if (dispatchListeners(event, dispatchInstances)) { + return dispatchInstances; + } + } + return null; +} + +/** + * @see executeDispatchesInOrderStopAtTrueImpl + */ +function executeDispatchesInOrderStopAtTrue(event) { + var ret = executeDispatchesInOrderStopAtTrueImpl(event); + event._dispatchInstances = null; + event._dispatchListeners = null; + return ret; +} + +/** + * Execution of a "direct" dispatch - there must be at most one dispatch + * accumulated on the event or it is considered an error. It doesn't really make + * sense for an event with multiple dispatches (bubbled) to keep track of the + * return values at each dispatch execution, but it does tend to make sense when + * dealing with "direct" dispatches. + * + * @return {*} The return value of executing the single dispatch. + */ +function executeDirectDispatch(event) { + if (process.env.NODE_ENV !== 'production') { + validateEventDispatches(event); + } + var dispatchListener = event._dispatchListeners; + var dispatchInstance = event._dispatchInstances; + !!Array.isArray(dispatchListener) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : _prodInvariant('103') : void 0; + event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null; + var res = dispatchListener ? dispatchListener(event) : null; + event.currentTarget = null; + event._dispatchListeners = null; + event._dispatchInstances = null; + return res; +} + +/** + * @param {SyntheticEvent} event + * @return {boolean} True iff number of dispatches accumulated is greater than 0. + */ +function hasDispatches(event) { + return !!event._dispatchListeners; +} + +/** + * General utilities that are useful in creating custom Event Plugins. + */ +var EventPluginUtils = { + isEndish: isEndish, + isMoveish: isMoveish, + isStartish: isStartish, + + executeDirectDispatch: executeDirectDispatch, + executeDispatchesInOrder: executeDispatchesInOrder, + executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, + hasDispatches: hasDispatches, + + getInstanceFromNode: function (node) { + return ComponentTree.getInstanceFromNode(node); + }, + getNodeFromInstance: function (node) { + return ComponentTree.getNodeFromInstance(node); + }, + isAncestor: function (a, b) { + return TreeTraversal.isAncestor(a, b); + }, + getLowestCommonAncestor: function (a, b) { + return TreeTraversal.getLowestCommonAncestor(a, b); + }, + getParentInstance: function (inst) { + return TreeTraversal.getParentInstance(inst); + }, + traverseTwoPhase: function (target, fn, arg) { + return TreeTraversal.traverseTwoPhase(target, fn, arg); + }, + traverseEnterLeave: function (from, to, fn, argFrom, argTo) { + return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo); + }, + + injection: injection +}; + +module.exports = EventPluginUtils; +}).call(this,require('_process')) + +},{"./EventConstants":97,"./ReactErrorUtils":146,"./reactProdInvariant":219,"_process":37,"fbjs/lib/invariant":241,"fbjs/lib/warning":251}],101:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule EventPropagators + */ + +'use strict'; + +var EventConstants = require('./EventConstants'); +var EventPluginHub = require('./EventPluginHub'); +var EventPluginUtils = require('./EventPluginUtils'); + +var accumulateInto = require('./accumulateInto'); +var forEachAccumulated = require('./forEachAccumulated'); +var warning = require('fbjs/lib/warning'); + +var PropagationPhases = EventConstants.PropagationPhases; +var getListener = EventPluginHub.getListener; + +/** + * Some event types have a notion of different registration names for different + * "phases" of propagation. This finds listeners by a given phase. + */ +function listenerAtPhase(inst, event, propagationPhase) { + var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase]; + return getListener(inst, registrationName); +} + +/** + * Tags a `SyntheticEvent` with dispatched listeners. Creating this function + * here, allows us to not have to bind or create functions for each event. + * Mutating the event's members allows us to not have to create a wrapping + * "dispatch" object that pairs the event with the listener. + */ +function accumulateDirectionalDispatches(inst, upwards, event) { + if (process.env.NODE_ENV !== 'production') { + process.env.NODE_ENV !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0; + } + var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured; + var listener = listenerAtPhase(inst, event, phase); + if (listener) { + event._dispatchListeners = accumulateInto(event._dispatchListeners, listener); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } +} + +/** + * Collect dispatches (must be entirely collected before dispatching - see unit + * tests). Lazily allocate the array to conserve memory. We must loop through + * each event and perform the traversal for each one. We cannot perform a + * single traversal for the entire collection of events because each event may + * have a different target. + */ +function accumulateTwoPhaseDispatchesSingle(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); + } +} + +/** + * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID. + */ +function accumulateTwoPhaseDispatchesSingleSkipTarget(event) { + if (event && event.dispatchConfig.phasedRegistrationNames) { + var targetInst = event._targetInst; + var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null; + EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event); + } +} + +/** + * Accumulates without regard to direction, does not look for phased + * registration names. Same as `accumulateDirectDispatchesSingle` but without + * requiring that the `dispatchMarker` be the same as the dispatched ID. + */ +function accumulateDispatches(inst, ignoredDirection, event) { + if (event && event.dispatchConfig.registrationName) { + var registrationName = event.dispatchConfig.registrationName; + var listener = getListener(inst, registrationName); + if (listener) { + event._dispatchListeners = accumulateInto(event._dispatchListeners, listener); + event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + } + } +} + +/** + * Accumulates dispatches on an `SyntheticEvent`, but only for the + * `dispatchMarker`. + * @param {SyntheticEvent} event + */ +function accumulateDirectDispatchesSingle(event) { + if (event && event.dispatchConfig.registrationName) { + accumulateDispatches(event._targetInst, null, event); + } +} + +function accumulateTwoPhaseDispatches(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); +} + +function accumulateTwoPhaseDispatchesSkipTarget(events) { + forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget); +} + +function accumulateEnterLeaveDispatches(leave, enter, from, to) { + EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter); +} + +function accumulateDirectDispatches(events) { + forEachAccumulated(events, accumulateDirectDispatchesSingle); +} + +/** + * A small set of propagation patterns, each of which will accept a small amount + * of information, and generate a set of "dispatch ready event objects" - which + * are sets of events that have already been annotated with a set of dispatched + * listener functions/ids. The API is designed this way to discourage these + * propagation strategies from actually executing the dispatches, since we + * always want to collect the entire set of dispatches before executing event a + * single one. + * + * @constructor EventPropagators + */ +var EventPropagators = { + accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches, + accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget, + accumulateDirectDispatches: accumulateDirectDispatches, + accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches +}; + +module.exports = EventPropagators; +}).call(this,require('_process')) + +},{"./EventConstants":97,"./EventPluginHub":98,"./EventPluginUtils":100,"./accumulateInto":195,"./forEachAccumulated":204,"_process":37,"fbjs/lib/warning":251}],102:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule FallbackCompositionState + */ + +'use strict'; + +var _assign = require('object-assign'); + +var PooledClass = require('./PooledClass'); + +var getTextContentAccessor = require('./getTextContentAccessor'); + +/** + * This helper class stores information about text content of a target node, + * allowing comparison of content before and after a given event. + * + * Identify the node where selection currently begins, then observe + * both its text content and its current position in the DOM. Since the + * browser may natively replace the target node during composition, we can + * use its position to find its replacement. + * + * @param {DOMEventTarget} root + */ +function FallbackCompositionState(root) { + this._root = root; + this._startText = this.getText(); + this._fallbackText = null; +} + +_assign(FallbackCompositionState.prototype, { + destructor: function () { + this._root = null; + this._startText = null; + this._fallbackText = null; + }, + + /** + * Get current text of input. + * + * @return {string} + */ + getText: function () { + if ('value' in this._root) { + return this._root.value; + } + return this._root[getTextContentAccessor()]; + }, + + /** + * Determine the differing substring between the initially stored + * text content and the current content. + * + * @return {string} + */ + getData: function () { + if (this._fallbackText) { + return this._fallbackText; + } + + var start; + var startValue = this._startText; + var startLength = startValue.length; + var end; + var endValue = this.getText(); + var endLength = endValue.length; + + for (start = 0; start < startLength; start++) { + if (startValue[start] !== endValue[start]) { + break; + } + } + + var minEnd = startLength - start; + for (end = 1; end <= minEnd; end++) { + if (startValue[startLength - end] !== endValue[endLength - end]) { + break; + } + } + + var sliceTail = end > 1 ? 1 - end : undefined; + this._fallbackText = endValue.slice(start, sliceTail); + return this._fallbackText; + } +}); + +PooledClass.addPoolingTo(FallbackCompositionState); + +module.exports = FallbackCompositionState; +},{"./PooledClass":106,"./getTextContentAccessor":212,"object-assign":36}],103:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule HTMLDOMPropertyConfig + */ + +'use strict'; + +var DOMProperty = require('./DOMProperty'); + +var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY; +var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE; +var HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE; +var HAS_POSITIVE_NUMERIC_VALUE = DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE; +var HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE; + +var HTMLDOMPropertyConfig = { + isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')), + Properties: { + /** + * Standard Properties + */ + accept: 0, + acceptCharset: 0, + accessKey: 0, + action: 0, + allowFullScreen: HAS_BOOLEAN_VALUE, + allowTransparency: 0, + alt: 0, + async: HAS_BOOLEAN_VALUE, + autoComplete: 0, + // autoFocus is polyfilled/normalized by AutoFocusUtils + // autoFocus: HAS_BOOLEAN_VALUE, + autoPlay: HAS_BOOLEAN_VALUE, + capture: HAS_BOOLEAN_VALUE, + cellPadding: 0, + cellSpacing: 0, + charSet: 0, + challenge: 0, + checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + cite: 0, + classID: 0, + className: 0, + cols: HAS_POSITIVE_NUMERIC_VALUE, + colSpan: 0, + content: 0, + contentEditable: 0, + contextMenu: 0, + controls: HAS_BOOLEAN_VALUE, + coords: 0, + crossOrigin: 0, + data: 0, // For `` acts as `src`. + dateTime: 0, + 'default': HAS_BOOLEAN_VALUE, + defer: HAS_BOOLEAN_VALUE, + dir: 0, + disabled: HAS_BOOLEAN_VALUE, + download: HAS_OVERLOADED_BOOLEAN_VALUE, + draggable: 0, + encType: 0, + form: 0, + formAction: 0, + formEncType: 0, + formMethod: 0, + formNoValidate: HAS_BOOLEAN_VALUE, + formTarget: 0, + frameBorder: 0, + headers: 0, + height: 0, + hidden: HAS_BOOLEAN_VALUE, + high: 0, + href: 0, + hrefLang: 0, + htmlFor: 0, + httpEquiv: 0, + icon: 0, + id: 0, + inputMode: 0, + integrity: 0, + is: 0, + keyParams: 0, + keyType: 0, + kind: 0, + label: 0, + lang: 0, + list: 0, + loop: HAS_BOOLEAN_VALUE, + low: 0, + manifest: 0, + marginHeight: 0, + marginWidth: 0, + max: 0, + maxLength: 0, + media: 0, + mediaGroup: 0, + method: 0, + min: 0, + minLength: 0, + // Caution; `option.selected` is not updated if `select.multiple` is + // disabled with `removeAttribute`. + multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + name: 0, + nonce: 0, + noValidate: HAS_BOOLEAN_VALUE, + open: HAS_BOOLEAN_VALUE, + optimum: 0, + pattern: 0, + placeholder: 0, + poster: 0, + preload: 0, + profile: 0, + radioGroup: 0, + readOnly: HAS_BOOLEAN_VALUE, + referrerPolicy: 0, + rel: 0, + required: HAS_BOOLEAN_VALUE, + reversed: HAS_BOOLEAN_VALUE, + role: 0, + rows: HAS_POSITIVE_NUMERIC_VALUE, + rowSpan: HAS_NUMERIC_VALUE, + sandbox: 0, + scope: 0, + scoped: HAS_BOOLEAN_VALUE, + scrolling: 0, + seamless: HAS_BOOLEAN_VALUE, + selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + shape: 0, + size: HAS_POSITIVE_NUMERIC_VALUE, + sizes: 0, + span: HAS_POSITIVE_NUMERIC_VALUE, + spellCheck: 0, + src: 0, + srcDoc: 0, + srcLang: 0, + srcSet: 0, + start: HAS_NUMERIC_VALUE, + step: 0, + style: 0, + summary: 0, + tabIndex: 0, + target: 0, + title: 0, + // Setting .type throws on non- tags + type: 0, + useMap: 0, + value: 0, + width: 0, + wmode: 0, + wrap: 0, + + /** + * RDFa Properties + */ + about: 0, + datatype: 0, + inlist: 0, + prefix: 0, + // property is also supported for OpenGraph in meta tags. + property: 0, + resource: 0, + 'typeof': 0, + vocab: 0, + + /** + * Non-standard Properties + */ + // autoCapitalize and autoCorrect are supported in Mobile Safari for + // keyboard hints. + autoCapitalize: 0, + autoCorrect: 0, + // autoSave allows WebKit/Blink to persist values of input fields on page reloads + autoSave: 0, + // color is for Safari mask-icon link + color: 0, + // itemProp, itemScope, itemType are for + // Microdata support. See http://schema.org/docs/gs.html + itemProp: 0, + itemScope: HAS_BOOLEAN_VALUE, + itemType: 0, + // itemID and itemRef are for Microdata support as well but + // only specified in the WHATWG spec document. See + // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api + itemID: 0, + itemRef: 0, + // results show looking glass icon and recent searches on input + // search fields in WebKit/Blink + results: 0, + // IE-only attribute that specifies security restrictions on an iframe + // as an alternative to the sandbox attribute on IE<10 + security: 0, + // IE-only attribute that controls focus behavior + unselectable: 0 + }, + DOMAttributeNames: { + acceptCharset: 'accept-charset', + className: 'class', + htmlFor: 'for', + httpEquiv: 'http-equiv' + }, + DOMPropertyNames: {} +}; + +module.exports = HTMLDOMPropertyConfig; +},{"./DOMProperty":91}],104:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule KeyEscapeUtils + * + */ + +'use strict'; + +/** + * Escape and wrap key so it is safe to use as a reactid + * + * @param {string} key to be escaped. + * @return {string} the escaped key. + */ + +function escape(key) { + var escapeRegex = /[=:]/g; + var escaperLookup = { + '=': '=0', + ':': '=2' + }; + var escapedString = ('' + key).replace(escapeRegex, function (match) { + return escaperLookup[match]; + }); + + return '$' + escapedString; +} + +/** + * Unescape and unwrap key for human-readable display + * + * @param {string} key to unescape. + * @return {string} the unescaped key. + */ +function unescape(key) { + var unescapeRegex = /(=0|=2)/g; + var unescaperLookup = { + '=0': '=', + '=2': ':' + }; + var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1); + + return ('' + keySubstring).replace(unescapeRegex, function (match) { + return unescaperLookup[match]; + }); +} + +var KeyEscapeUtils = { + escape: escape, + unescape: unescape +}; + +module.exports = KeyEscapeUtils; +},{}],105:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule LinkedValueUtils + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var ReactPropTypes = require('./ReactPropTypes'); +var ReactPropTypeLocations = require('./ReactPropTypeLocations'); +var ReactPropTypesSecret = require('./ReactPropTypesSecret'); + +var invariant = require('fbjs/lib/invariant'); +var warning = require('fbjs/lib/warning'); + +var hasReadOnlyValue = { + 'button': true, + 'checkbox': true, + 'image': true, + 'hidden': true, + 'radio': true, + 'reset': true, + 'submit': true +}; + +function _assertSingleLink(inputProps) { + !(inputProps.checkedLink == null || inputProps.valueLink == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don\'t want to use valueLink and vice versa.') : _prodInvariant('87') : void 0; +} +function _assertValueLink(inputProps) { + _assertSingleLink(inputProps); + !(inputProps.value == null && inputProps.onChange == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don\'t want to use valueLink.') : _prodInvariant('88') : void 0; +} + +function _assertCheckedLink(inputProps) { + _assertSingleLink(inputProps); + !(inputProps.checked == null && inputProps.onChange == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don\'t want to use checkedLink') : _prodInvariant('89') : void 0; +} + +var propTypes = { + value: function (props, propName, componentName) { + if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) { + return null; + } + return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); + }, + checked: function (props, propName, componentName) { + if (!props[propName] || props.onChange || props.readOnly || props.disabled) { + return null; + } + return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); + }, + onChange: ReactPropTypes.func +}; + +var loggedTypeFailures = {}; +function getDeclarationErrorAddendum(owner) { + if (owner) { + var name = owner.getName(); + if (name) { + return ' Check the render method of `' + name + '`.'; + } + } + return ''; +} + +/** + * Provide a linked `value` attribute for controlled forms. You should not use + * this outside of the ReactDOM controlled form components. + */ +var LinkedValueUtils = { + checkPropTypes: function (tagName, props, owner) { + for (var propName in propTypes) { + if (propTypes.hasOwnProperty(propName)) { + var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop, null, ReactPropTypesSecret); + } + if (error instanceof Error && !(error.message in loggedTypeFailures)) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error.message] = true; + + var addendum = getDeclarationErrorAddendum(owner); + process.env.NODE_ENV !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0; + } + } + }, + + /** + * @param {object} inputProps Props for form component + * @return {*} current value of the input either from value prop or link. + */ + getValue: function (inputProps) { + if (inputProps.valueLink) { + _assertValueLink(inputProps); + return inputProps.valueLink.value; + } + return inputProps.value; + }, + + /** + * @param {object} inputProps Props for form component + * @return {*} current checked status of the input either from checked prop + * or link. + */ + getChecked: function (inputProps) { + if (inputProps.checkedLink) { + _assertCheckedLink(inputProps); + return inputProps.checkedLink.value; + } + return inputProps.checked; + }, + + /** + * @param {object} inputProps Props for form component + * @param {SyntheticEvent} event change event to handle + */ + executeOnChange: function (inputProps, event) { + if (inputProps.valueLink) { + _assertValueLink(inputProps); + return inputProps.valueLink.requestChange(event.target.value); + } else if (inputProps.checkedLink) { + _assertCheckedLink(inputProps); + return inputProps.checkedLink.requestChange(event.target.checked); + } else if (inputProps.onChange) { + return inputProps.onChange.call(undefined, event); + } + } +}; + +module.exports = LinkedValueUtils; +}).call(this,require('_process')) + +},{"./ReactPropTypeLocations":165,"./ReactPropTypes":166,"./ReactPropTypesSecret":167,"./reactProdInvariant":219,"_process":37,"fbjs/lib/invariant":241,"fbjs/lib/warning":251}],106:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule PooledClass + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var invariant = require('fbjs/lib/invariant'); + +/** + * Static poolers. Several custom versions for each potential number of + * arguments. A completely generic pooler is easy to implement, but would + * require accessing the `arguments` object. In each of these, `this` refers to + * the Class itself, not an instance. If any others are needed, simply add them + * here, or in their own files. + */ +var oneArgumentPooler = function (copyFieldsFrom) { + var Klass = this; + if (Klass.instancePool.length) { + var instance = Klass.instancePool.pop(); + Klass.call(instance, copyFieldsFrom); + return instance; + } else { + return new Klass(copyFieldsFrom); + } +}; + +var twoArgumentPooler = function (a1, a2) { + var Klass = this; + if (Klass.instancePool.length) { + var instance = Klass.instancePool.pop(); + Klass.call(instance, a1, a2); + return instance; + } else { + return new Klass(a1, a2); + } +}; + +var threeArgumentPooler = function (a1, a2, a3) { + var Klass = this; + if (Klass.instancePool.length) { + var instance = Klass.instancePool.pop(); + Klass.call(instance, a1, a2, a3); + return instance; + } else { + return new Klass(a1, a2, a3); + } +}; + +var fourArgumentPooler = function (a1, a2, a3, a4) { + var Klass = this; + if (Klass.instancePool.length) { + var instance = Klass.instancePool.pop(); + Klass.call(instance, a1, a2, a3, a4); + return instance; + } else { + return new Klass(a1, a2, a3, a4); + } +}; + +var fiveArgumentPooler = function (a1, a2, a3, a4, a5) { + var Klass = this; + if (Klass.instancePool.length) { + var instance = Klass.instancePool.pop(); + Klass.call(instance, a1, a2, a3, a4, a5); + return instance; + } else { + return new Klass(a1, a2, a3, a4, a5); + } +}; + +var standardReleaser = function (instance) { + var Klass = this; + !(instance instanceof Klass) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : _prodInvariant('25') : void 0; + instance.destructor(); + if (Klass.instancePool.length < Klass.poolSize) { + Klass.instancePool.push(instance); + } +}; + +var DEFAULT_POOL_SIZE = 10; +var DEFAULT_POOLER = oneArgumentPooler; + +/** + * Augments `CopyConstructor` to be a poolable class, augmenting only the class + * itself (statically) not adding any prototypical fields. Any CopyConstructor + * you give this may have a `poolSize` property, and will look for a + * prototypical `destructor` on instances. + * + * @param {Function} CopyConstructor Constructor that can be used to reset. + * @param {Function} pooler Customizable pooler. + */ +var addPoolingTo = function (CopyConstructor, pooler) { + var NewKlass = CopyConstructor; + NewKlass.instancePool = []; + NewKlass.getPooled = pooler || DEFAULT_POOLER; + if (!NewKlass.poolSize) { + NewKlass.poolSize = DEFAULT_POOL_SIZE; + } + NewKlass.release = standardReleaser; + return NewKlass; +}; + +var PooledClass = { + addPoolingTo: addPoolingTo, + oneArgumentPooler: oneArgumentPooler, + twoArgumentPooler: twoArgumentPooler, + threeArgumentPooler: threeArgumentPooler, + fourArgumentPooler: fourArgumentPooler, + fiveArgumentPooler: fiveArgumentPooler +}; + +module.exports = PooledClass; +}).call(this,require('_process')) + +},{"./reactProdInvariant":219,"_process":37,"fbjs/lib/invariant":241}],107:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule React + */ + +'use strict'; + +var _assign = require('object-assign'); + +var ReactChildren = require('./ReactChildren'); +var ReactComponent = require('./ReactComponent'); +var ReactPureComponent = require('./ReactPureComponent'); +var ReactClass = require('./ReactClass'); +var ReactDOMFactories = require('./ReactDOMFactories'); +var ReactElement = require('./ReactElement'); +var ReactPropTypes = require('./ReactPropTypes'); +var ReactVersion = require('./ReactVersion'); + +var onlyChild = require('./onlyChild'); +var warning = require('fbjs/lib/warning'); + +var createElement = ReactElement.createElement; +var createFactory = ReactElement.createFactory; +var cloneElement = ReactElement.cloneElement; + +if (process.env.NODE_ENV !== 'production') { + var ReactElementValidator = require('./ReactElementValidator'); + createElement = ReactElementValidator.createElement; + createFactory = ReactElementValidator.createFactory; + cloneElement = ReactElementValidator.cloneElement; +} + +var __spread = _assign; + +if (process.env.NODE_ENV !== 'production') { + var warned = false; + __spread = function () { + process.env.NODE_ENV !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0; + warned = true; + return _assign.apply(null, arguments); + }; +} + +var React = { + + // Modern + + Children: { + map: ReactChildren.map, + forEach: ReactChildren.forEach, + count: ReactChildren.count, + toArray: ReactChildren.toArray, + only: onlyChild + }, + + Component: ReactComponent, + PureComponent: ReactPureComponent, + + createElement: createElement, + cloneElement: cloneElement, + isValidElement: ReactElement.isValidElement, + + // Classic + + PropTypes: ReactPropTypes, + createClass: ReactClass.createClass, + createFactory: createFactory, + createMixin: function (mixin) { + // Currently a noop. Will be used to validate and trace mixins. + return mixin; + }, + + // This looks DOM specific but these are actually isomorphic helpers + // since they are just generating DOM strings. + DOM: ReactDOMFactories, + + version: ReactVersion, + + // Deprecated hook for JSX spread, don't use this for anything. + __spread: __spread +}; + +module.exports = React; +}).call(this,require('_process')) + +},{"./ReactChildren":110,"./ReactClass":112,"./ReactComponent":113,"./ReactDOMFactories":127,"./ReactElement":143,"./ReactElementValidator":144,"./ReactPropTypes":166,"./ReactPureComponent":168,"./ReactVersion":176,"./onlyChild":217,"_process":37,"fbjs/lib/warning":251,"object-assign":36}],108:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactBrowserEventEmitter + */ + +'use strict'; + +var _assign = require('object-assign'); + +var EventConstants = require('./EventConstants'); +var EventPluginRegistry = require('./EventPluginRegistry'); +var ReactEventEmitterMixin = require('./ReactEventEmitterMixin'); +var ViewportMetrics = require('./ViewportMetrics'); + +var getVendorPrefixedEventName = require('./getVendorPrefixedEventName'); +var isEventSupported = require('./isEventSupported'); + +/** + * Summary of `ReactBrowserEventEmitter` event handling: + * + * - Top-level delegation is used to trap most native browser events. This + * may only occur in the main thread and is the responsibility of + * ReactEventListener, which is injected and can therefore support pluggable + * event sources. This is the only work that occurs in the main thread. + * + * - We normalize and de-duplicate events to account for browser quirks. This + * may be done in the worker thread. + * + * - Forward these native events (with the associated top-level type used to + * trap it) to `EventPluginHub`, which in turn will ask plugins if they want + * to extract any synthetic events. + * + * - The `EventPluginHub` will then process each event by annotating them with + * "dispatches", a sequence of listeners and IDs that care about that event. + * + * - The `EventPluginHub` then dispatches the events. + * + * Overview of React and the event system: + * + * +------------+ . + * | DOM | . + * +------------+ . + * | . + * v . + * +------------+ . + * | ReactEvent | . + * | Listener | . + * +------------+ . +-----------+ + * | . +--------+|SimpleEvent| + * | . | |Plugin | + * +-----|------+ . v +-----------+ + * | | | . +--------------+ +------------+ + * | +-----------.--->|EventPluginHub| | Event | + * | | . | | +-----------+ | Propagators| + * | ReactEvent | . | | |TapEvent | |------------| + * | Emitter | . | |<---+|Plugin | |other plugin| + * | | . | | +-----------+ | utilities | + * | +-----------.--->| | +------------+ + * | | | . +--------------+ + * +-----|------+ . ^ +-----------+ + * | . | |Enter/Leave| + * + . +-------+|Plugin | + * +-------------+ . +-----------+ + * | application | . + * |-------------| . + * | | . + * | | . + * +-------------+ . + * . + * React Core . General Purpose Event Plugin System + */ + +var hasEventPageXY; +var alreadyListeningTo = {}; +var isMonitoringScrollValue = false; +var reactTopListenersCounter = 0; + +// For events like 'submit' which don't consistently bubble (which we trap at a +// lower node than `document`), binding at `document` would cause duplicate +// events so we don't include them here +var topEventMapping = { + topAbort: 'abort', + topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend', + topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration', + topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart', + topBlur: 'blur', + topCanPlay: 'canplay', + topCanPlayThrough: 'canplaythrough', + topChange: 'change', + topClick: 'click', + topCompositionEnd: 'compositionend', + topCompositionStart: 'compositionstart', + topCompositionUpdate: 'compositionupdate', + topContextMenu: 'contextmenu', + topCopy: 'copy', + topCut: 'cut', + topDoubleClick: 'dblclick', + topDrag: 'drag', + topDragEnd: 'dragend', + topDragEnter: 'dragenter', + topDragExit: 'dragexit', + topDragLeave: 'dragleave', + topDragOver: 'dragover', + topDragStart: 'dragstart', + topDrop: 'drop', + topDurationChange: 'durationchange', + topEmptied: 'emptied', + topEncrypted: 'encrypted', + topEnded: 'ended', + topError: 'error', + topFocus: 'focus', + topInput: 'input', + topKeyDown: 'keydown', + topKeyPress: 'keypress', + topKeyUp: 'keyup', + topLoadedData: 'loadeddata', + topLoadedMetadata: 'loadedmetadata', + topLoadStart: 'loadstart', + topMouseDown: 'mousedown', + topMouseMove: 'mousemove', + topMouseOut: 'mouseout', + topMouseOver: 'mouseover', + topMouseUp: 'mouseup', + topPaste: 'paste', + topPause: 'pause', + topPlay: 'play', + topPlaying: 'playing', + topProgress: 'progress', + topRateChange: 'ratechange', + topScroll: 'scroll', + topSeeked: 'seeked', + topSeeking: 'seeking', + topSelectionChange: 'selectionchange', + topStalled: 'stalled', + topSuspend: 'suspend', + topTextInput: 'textInput', + topTimeUpdate: 'timeupdate', + topTouchCancel: 'touchcancel', + topTouchEnd: 'touchend', + topTouchMove: 'touchmove', + topTouchStart: 'touchstart', + topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend', + topVolumeChange: 'volumechange', + topWaiting: 'waiting', + topWheel: 'wheel' +}; + +/** + * To ensure no conflicts with other potential React instances on the page + */ +var topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2); + +function getListeningForDocument(mountAt) { + // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty` + // directly. + if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) { + mountAt[topListenersIDKey] = reactTopListenersCounter++; + alreadyListeningTo[mountAt[topListenersIDKey]] = {}; + } + return alreadyListeningTo[mountAt[topListenersIDKey]]; +} + +/** + * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For + * example: + * + * EventPluginHub.putListener('myID', 'onClick', myFunction); + * + * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'. + * + * @internal + */ +var ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, { + + /** + * Injectable event backend + */ + ReactEventListener: null, + + injection: { + /** + * @param {object} ReactEventListener + */ + injectReactEventListener: function (ReactEventListener) { + ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel); + ReactBrowserEventEmitter.ReactEventListener = ReactEventListener; + } + }, + + /** + * Sets whether or not any created callbacks should be enabled. + * + * @param {boolean} enabled True if callbacks should be enabled. + */ + setEnabled: function (enabled) { + if (ReactBrowserEventEmitter.ReactEventListener) { + ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled); + } + }, + + /** + * @return {boolean} True if callbacks are enabled. + */ + isEnabled: function () { + return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled()); + }, + + /** + * We listen for bubbled touch events on the document object. + * + * Firefox v8.01 (and possibly others) exhibited strange behavior when + * mounting `onmousemove` events at some node that was not the document + * element. The symptoms were that if your mouse is not moving over something + * contained within that mount point (for example on the background) the + * top-level listeners for `onmousemove` won't be called. However, if you + * register the `mousemove` on the document object, then it will of course + * catch all `mousemove`s. This along with iOS quirks, justifies restricting + * top-level listeners to the document object only, at least for these + * movement types of events and possibly all events. + * + * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html + * + * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but + * they bubble to document. + * + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @param {object} contentDocumentHandle Document which owns the container + */ + listenTo: function (registrationName, contentDocumentHandle) { + var mountAt = contentDocumentHandle; + var isListening = getListeningForDocument(mountAt); + var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName]; + + var topLevelTypes = EventConstants.topLevelTypes; + for (var i = 0; i < dependencies.length; i++) { + var dependency = dependencies[i]; + if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { + if (dependency === topLevelTypes.topWheel) { + if (isEventSupported('wheel')) { + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt); + } else if (isEventSupported('mousewheel')) { + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt); + } else { + // Firefox needs to capture a different mouse scroll event. + // @see http://www.quirksmode.org/dom/events/tests/scroll.html + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt); + } + } else if (dependency === topLevelTypes.topScroll) { + + if (isEventSupported('scroll', true)) { + ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt); + } else { + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topScroll, 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE); + } + } else if (dependency === topLevelTypes.topFocus || dependency === topLevelTypes.topBlur) { + + if (isEventSupported('focus', true)) { + ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt); + ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt); + } else if (isEventSupported('focusin')) { + // IE has `focusin` and `focusout` events which bubble. + // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt); + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt); + } + + // to make sure blur and focus event listeners are only attached once + isListening[topLevelTypes.topBlur] = true; + isListening[topLevelTypes.topFocus] = true; + } else if (topEventMapping.hasOwnProperty(dependency)) { + ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt); + } + + isListening[dependency] = true; + } + } + }, + + trapBubbledEvent: function (topLevelType, handlerBaseName, handle) { + return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle); + }, + + trapCapturedEvent: function (topLevelType, handlerBaseName, handle) { + return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle); + }, + + /** + * Listens to window scroll and resize events. We cache scroll values so that + * application code can access them without triggering reflows. + * + * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when + * pageX/pageY isn't supported (legacy browsers). + * + * NOTE: Scroll events do not bubble. + * + * @see http://www.quirksmode.org/dom/events/scroll.html + */ + ensureScrollValueMonitoring: function () { + if (hasEventPageXY === undefined) { + hasEventPageXY = document.createEvent && 'pageX' in document.createEvent('MouseEvent'); + } + if (!hasEventPageXY && !isMonitoringScrollValue) { + var refresh = ViewportMetrics.refreshScrollValues; + ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh); + isMonitoringScrollValue = true; + } + } + +}); + +module.exports = ReactBrowserEventEmitter; +},{"./EventConstants":97,"./EventPluginRegistry":99,"./ReactEventEmitterMixin":147,"./ViewportMetrics":194,"./getVendorPrefixedEventName":213,"./isEventSupported":215,"object-assign":36}],109:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactChildReconciler + */ + +'use strict'; + +var ReactReconciler = require('./ReactReconciler'); + +var instantiateReactComponent = require('./instantiateReactComponent'); +var KeyEscapeUtils = require('./KeyEscapeUtils'); +var shouldUpdateReactComponent = require('./shouldUpdateReactComponent'); +var traverseAllChildren = require('./traverseAllChildren'); +var warning = require('fbjs/lib/warning'); + +var ReactComponentTreeDevtool; + +if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'test') { + // Temporary hack. + // Inline requires don't work well with Jest: + // https://github.com/facebook/react/issues/7240 + // Remove the inline requires when we don't need them anymore: + // https://github.com/facebook/react/pull/7178 + ReactComponentTreeDevtool = require('./ReactComponentTreeDevtool'); +} + +function instantiateChild(childInstances, child, name, selfDebugID) { + // We found a component instance. + var keyUnique = childInstances[name] === undefined; + if (process.env.NODE_ENV !== 'production') { + if (!ReactComponentTreeDevtool) { + ReactComponentTreeDevtool = require('./ReactComponentTreeDevtool'); + } + process.env.NODE_ENV !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0; + } + if (child != null && keyUnique) { + childInstances[name] = instantiateReactComponent(child, true); + } +} + +/** + * ReactChildReconciler provides helpers for initializing or updating a set of + * children. Its output is suitable for passing it onto ReactMultiChild which + * does diffed reordering and insertion. + */ +var ReactChildReconciler = { + /** + * Generates a "mount image" for each of the supplied children. In the case + * of `ReactDOMComponent`, a mount image is a string of markup. + * + * @param {?object} nestedChildNodes Nested child maps. + * @return {?object} A set of child instances. + * @internal + */ + instantiateChildren: function (nestedChildNodes, transaction, context, selfDebugID // __DEV__ only + ) { + if (nestedChildNodes == null) { + return null; + } + var childInstances = {}; + + if (process.env.NODE_ENV !== 'production') { + traverseAllChildren(nestedChildNodes, function (childInsts, child, name) { + return instantiateChild(childInsts, child, name, selfDebugID); + }, childInstances); + } else { + traverseAllChildren(nestedChildNodes, instantiateChild, childInstances); + } + return childInstances; + }, + + /** + * Updates the rendered children and returns a new set of children. + * + * @param {?object} prevChildren Previously initialized set of children. + * @param {?object} nextChildren Flat child element maps. + * @param {ReactReconcileTransaction} transaction + * @param {object} context + * @return {?object} A new set of child instances. + * @internal + */ + updateChildren: function (prevChildren, nextChildren, mountImages, removedNodes, transaction, hostParent, hostContainerInfo, context) { + // We currently don't have a way to track moves here but if we use iterators + // instead of for..in we can zip the iterators and check if an item has + // moved. + // TODO: If nothing has changed, return the prevChildren object so that we + // can quickly bailout if nothing has changed. + if (!nextChildren && !prevChildren) { + return; + } + var name; + var prevChild; + for (name in nextChildren) { + if (!nextChildren.hasOwnProperty(name)) { + continue; + } + prevChild = prevChildren && prevChildren[name]; + var prevElement = prevChild && prevChild._currentElement; + var nextElement = nextChildren[name]; + if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) { + ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context); + nextChildren[name] = prevChild; + } else { + if (prevChild) { + removedNodes[name] = ReactReconciler.getHostNode(prevChild); + ReactReconciler.unmountComponent(prevChild, false); + } + // The child must be instantiated before it's mounted. + var nextChildInstance = instantiateReactComponent(nextElement, true); + nextChildren[name] = nextChildInstance; + // Creating mount image now ensures refs are resolved in right order + // (see https://github.com/facebook/react/pull/7101 for explanation). + var nextChildMountImage = ReactReconciler.mountComponent(nextChildInstance, transaction, hostParent, hostContainerInfo, context); + mountImages.push(nextChildMountImage); + } + } + // Unmount children that are no longer present. + for (name in prevChildren) { + if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) { + prevChild = prevChildren[name]; + removedNodes[name] = ReactReconciler.getHostNode(prevChild); + ReactReconciler.unmountComponent(prevChild, false); + } + } + }, + + /** + * Unmounts all rendered children. This should be used to clean up children + * when this component is unmounted. + * + * @param {?object} renderedChildren Previously initialized set of children. + * @internal + */ + unmountChildren: function (renderedChildren, safely) { + for (var name in renderedChildren) { + if (renderedChildren.hasOwnProperty(name)) { + var renderedChild = renderedChildren[name]; + ReactReconciler.unmountComponent(renderedChild, safely); + } + } + } + +}; + +module.exports = ReactChildReconciler; +}).call(this,require('_process')) + +},{"./KeyEscapeUtils":104,"./ReactComponentTreeDevtool":116,"./ReactReconciler":170,"./instantiateReactComponent":214,"./shouldUpdateReactComponent":223,"./traverseAllChildren":224,"_process":37,"fbjs/lib/warning":251}],110:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactChildren + */ + +'use strict'; + +var PooledClass = require('./PooledClass'); +var ReactElement = require('./ReactElement'); + +var emptyFunction = require('fbjs/lib/emptyFunction'); +var traverseAllChildren = require('./traverseAllChildren'); + +var twoArgumentPooler = PooledClass.twoArgumentPooler; +var fourArgumentPooler = PooledClass.fourArgumentPooler; + +var userProvidedKeyEscapeRegex = /\/+/g; +function escapeUserProvidedKey(text) { + return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/'); +} + +/** + * PooledClass representing the bookkeeping associated with performing a child + * traversal. Allows avoiding binding callbacks. + * + * @constructor ForEachBookKeeping + * @param {!function} forEachFunction Function to perform traversal with. + * @param {?*} forEachContext Context to perform context with. + */ +function ForEachBookKeeping(forEachFunction, forEachContext) { + this.func = forEachFunction; + this.context = forEachContext; + this.count = 0; +} +ForEachBookKeeping.prototype.destructor = function () { + this.func = null; + this.context = null; + this.count = 0; +}; +PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler); + +function forEachSingleChild(bookKeeping, child, name) { + var func = bookKeeping.func; + var context = bookKeeping.context; + + func.call(context, child, bookKeeping.count++); +} + +/** + * Iterates through children that are typically specified as `props.children`. + * + * See https://facebook.github.io/react/docs/top-level-api.html#react.children.foreach + * + * The provided forEachFunc(child, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} forEachFunc + * @param {*} forEachContext Context for forEachContext. + */ +function forEachChildren(children, forEachFunc, forEachContext) { + if (children == null) { + return children; + } + var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext); + traverseAllChildren(children, forEachSingleChild, traverseContext); + ForEachBookKeeping.release(traverseContext); +} + +/** + * PooledClass representing the bookkeeping associated with performing a child + * mapping. Allows avoiding binding callbacks. + * + * @constructor MapBookKeeping + * @param {!*} mapResult Object containing the ordered map of results. + * @param {!function} mapFunction Function to perform mapping with. + * @param {?*} mapContext Context to perform mapping with. + */ +function MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) { + this.result = mapResult; + this.keyPrefix = keyPrefix; + this.func = mapFunction; + this.context = mapContext; + this.count = 0; +} +MapBookKeeping.prototype.destructor = function () { + this.result = null; + this.keyPrefix = null; + this.func = null; + this.context = null; + this.count = 0; +}; +PooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler); + +function mapSingleChildIntoContext(bookKeeping, child, childKey) { + var result = bookKeeping.result; + var keyPrefix = bookKeeping.keyPrefix; + var func = bookKeeping.func; + var context = bookKeeping.context; + + + var mappedChild = func.call(context, child, bookKeeping.count++); + if (Array.isArray(mappedChild)) { + mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument); + } else if (mappedChild != null) { + if (ReactElement.isValidElement(mappedChild)) { + mappedChild = ReactElement.cloneAndReplaceKey(mappedChild, + // Keep both the (mapped) and old keys if they differ, just as + // traverseAllChildren used to do for objects as children + keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey); + } + result.push(mappedChild); + } +} + +function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) { + var escapedPrefix = ''; + if (prefix != null) { + escapedPrefix = escapeUserProvidedKey(prefix) + '/'; + } + var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context); + traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); + MapBookKeeping.release(traverseContext); +} + +/** + * Maps children that are typically specified as `props.children`. + * + * See https://facebook.github.io/react/docs/top-level-api.html#react.children.map + * + * The provided mapFunction(child, key, index) will be called for each + * leaf child. + * + * @param {?*} children Children tree container. + * @param {function(*, int)} func The map function. + * @param {*} context Context for mapFunction. + * @return {object} Object containing the ordered map of results. + */ +function mapChildren(children, func, context) { + if (children == null) { + return children; + } + var result = []; + mapIntoWithKeyPrefixInternal(children, result, null, func, context); + return result; +} + +function forEachSingleChildDummy(traverseContext, child, name) { + return null; +} + +/** + * Count the number of children that are typically specified as + * `props.children`. + * + * See https://facebook.github.io/react/docs/top-level-api.html#react.children.count + * + * @param {?*} children Children tree container. + * @return {number} The number of children. + */ +function countChildren(children, context) { + return traverseAllChildren(children, forEachSingleChildDummy, null); +} + +/** + * Flatten a children object (typically specified as `props.children`) and + * return an array with appropriately re-keyed children. + * + * See https://facebook.github.io/react/docs/top-level-api.html#react.children.toarray + */ +function toArray(children) { + var result = []; + mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument); + return result; +} + +var ReactChildren = { + forEach: forEachChildren, + map: mapChildren, + mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal, + count: countChildren, + toArray: toArray +}; + +module.exports = ReactChildren; +},{"./PooledClass":106,"./ReactElement":143,"./traverseAllChildren":224,"fbjs/lib/emptyFunction":233}],111:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactChildrenMutationWarningDevtool + */ + +'use strict'; + +var ReactComponentTreeDevtool = require('./ReactComponentTreeDevtool'); + +var warning = require('fbjs/lib/warning'); + +var elements = {}; + +function handleElement(debugID, element) { + if (element == null) { + return; + } + if (element._shadowChildren === undefined) { + return; + } + if (element._shadowChildren === element.props.children) { + return; + } + var isMutated = false; + if (Array.isArray(element._shadowChildren)) { + if (element._shadowChildren.length === element.props.children.length) { + for (var i = 0; i < element._shadowChildren.length; i++) { + if (element._shadowChildren[i] !== element.props.children[i]) { + isMutated = true; + } + } + } else { + isMutated = true; + } + } + process.env.NODE_ENV !== 'production' ? warning(Array.isArray(element._shadowChildren) && !isMutated, 'Component\'s children should not be mutated.%s', ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0; +} + +var ReactDOMUnknownPropertyDevtool = { + onBeforeMountComponent: function (debugID, element) { + elements[debugID] = element; + }, + onBeforeUpdateComponent: function (debugID, element) { + elements[debugID] = element; + }, + onComponentHasMounted: function (debugID) { + handleElement(debugID, elements[debugID]); + delete elements[debugID]; + }, + onComponentHasUpdated: function (debugID) { + handleElement(debugID, elements[debugID]); + delete elements[debugID]; + } +}; + +module.exports = ReactDOMUnknownPropertyDevtool; +}).call(this,require('_process')) + +},{"./ReactComponentTreeDevtool":116,"_process":37,"fbjs/lib/warning":251}],112:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactClass + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'), + _assign = require('object-assign'); + +var ReactComponent = require('./ReactComponent'); +var ReactElement = require('./ReactElement'); +var ReactPropTypeLocations = require('./ReactPropTypeLocations'); +var ReactPropTypeLocationNames = require('./ReactPropTypeLocationNames'); +var ReactNoopUpdateQueue = require('./ReactNoopUpdateQueue'); + +var emptyObject = require('fbjs/lib/emptyObject'); +var invariant = require('fbjs/lib/invariant'); +var keyMirror = require('fbjs/lib/keyMirror'); +var keyOf = require('fbjs/lib/keyOf'); +var warning = require('fbjs/lib/warning'); + +var MIXINS_KEY = keyOf({ mixins: null }); + +/** + * Policies that describe methods in `ReactClassInterface`. + */ +var SpecPolicy = keyMirror({ + /** + * These methods may be defined only once by the class specification or mixin. + */ + DEFINE_ONCE: null, + /** + * These methods may be defined by both the class specification and mixins. + * Subsequent definitions will be chained. These methods must return void. + */ + DEFINE_MANY: null, + /** + * These methods are overriding the base class. + */ + OVERRIDE_BASE: null, + /** + * These methods are similar to DEFINE_MANY, except we assume they return + * objects. We try to merge the keys of the return values of all the mixed in + * functions. If there is a key conflict we throw. + */ + DEFINE_MANY_MERGED: null +}); + +var injectedMixins = []; + +/** + * Composite components are higher-level components that compose other composite + * or host components. + * + * To create a new type of `ReactClass`, pass a specification of + * your new class to `React.createClass`. The only requirement of your class + * specification is that you implement a `render` method. + * + * var MyComponent = React.createClass({ + * render: function() { + * return
Hello World
; + * } + * }); + * + * The class specification supports a specific protocol of methods that have + * special meaning (e.g. `render`). See `ReactClassInterface` for + * more the comprehensive protocol. Any other properties and methods in the + * class specification will be available on the prototype. + * + * @interface ReactClassInterface + * @internal + */ +var ReactClassInterface = { + + /** + * An array of Mixin objects to include when defining your component. + * + * @type {array} + * @optional + */ + mixins: SpecPolicy.DEFINE_MANY, + + /** + * An object containing properties and methods that should be defined on + * the component's constructor instead of its prototype (static methods). + * + * @type {object} + * @optional + */ + statics: SpecPolicy.DEFINE_MANY, + + /** + * Definition of prop types for this component. + * + * @type {object} + * @optional + */ + propTypes: SpecPolicy.DEFINE_MANY, + + /** + * Definition of context types for this component. + * + * @type {object} + * @optional + */ + contextTypes: SpecPolicy.DEFINE_MANY, + + /** + * Definition of context types this component sets for its children. + * + * @type {object} + * @optional + */ + childContextTypes: SpecPolicy.DEFINE_MANY, + + // ==== Definition methods ==== + + /** + * Invoked when the component is mounted. Values in the mapping will be set on + * `this.props` if that prop is not specified (i.e. using an `in` check). + * + * This method is invoked before `getInitialState` and therefore cannot rely + * on `this.state` or use `this.setState`. + * + * @return {object} + * @optional + */ + getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED, + + /** + * Invoked once before the component is mounted. The return value will be used + * as the initial value of `this.state`. + * + * getInitialState: function() { + * return { + * isOn: false, + * fooBaz: new BazFoo() + * } + * } + * + * @return {object} + * @optional + */ + getInitialState: SpecPolicy.DEFINE_MANY_MERGED, + + /** + * @return {object} + * @optional + */ + getChildContext: SpecPolicy.DEFINE_MANY_MERGED, + + /** + * Uses props from `this.props` and state from `this.state` to render the + * structure of the component. + * + * No guarantees are made about when or how often this method is invoked, so + * it must not have side effects. + * + * render: function() { + * var name = this.props.name; + * return
Hello, {name}!
; + * } + * + * @return {ReactComponent} + * @nosideeffects + * @required + */ + render: SpecPolicy.DEFINE_ONCE, + + // ==== Delegate methods ==== + + /** + * Invoked when the component is initially created and about to be mounted. + * This may have side effects, but any external subscriptions or data created + * by this method must be cleaned up in `componentWillUnmount`. + * + * @optional + */ + componentWillMount: SpecPolicy.DEFINE_MANY, + + /** + * Invoked when the component has been mounted and has a DOM representation. + * However, there is no guarantee that the DOM node is in the document. + * + * Use this as an opportunity to operate on the DOM when the component has + * been mounted (initialized and rendered) for the first time. + * + * @param {DOMElement} rootNode DOM element representing the component. + * @optional + */ + componentDidMount: SpecPolicy.DEFINE_MANY, + + /** + * Invoked before the component receives new props. + * + * Use this as an opportunity to react to a prop transition by updating the + * state using `this.setState`. Current props are accessed via `this.props`. + * + * componentWillReceiveProps: function(nextProps, nextContext) { + * this.setState({ + * likesIncreasing: nextProps.likeCount > this.props.likeCount + * }); + * } + * + * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop + * transition may cause a state change, but the opposite is not true. If you + * need it, you are probably looking for `componentWillUpdate`. + * + * @param {object} nextProps + * @optional + */ + componentWillReceiveProps: SpecPolicy.DEFINE_MANY, + + /** + * Invoked while deciding if the component should be updated as a result of + * receiving new props, state and/or context. + * + * Use this as an opportunity to `return false` when you're certain that the + * transition to the new props/state/context will not require a component + * update. + * + * shouldComponentUpdate: function(nextProps, nextState, nextContext) { + * return !equal(nextProps, this.props) || + * !equal(nextState, this.state) || + * !equal(nextContext, this.context); + * } + * + * @param {object} nextProps + * @param {?object} nextState + * @param {?object} nextContext + * @return {boolean} True if the component should update. + * @optional + */ + shouldComponentUpdate: SpecPolicy.DEFINE_ONCE, + + /** + * Invoked when the component is about to update due to a transition from + * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState` + * and `nextContext`. + * + * Use this as an opportunity to perform preparation before an update occurs. + * + * NOTE: You **cannot** use `this.setState()` in this method. + * + * @param {object} nextProps + * @param {?object} nextState + * @param {?object} nextContext + * @param {ReactReconcileTransaction} transaction + * @optional + */ + componentWillUpdate: SpecPolicy.DEFINE_MANY, + + /** + * Invoked when the component's DOM representation has been updated. + * + * Use this as an opportunity to operate on the DOM when the component has + * been updated. + * + * @param {object} prevProps + * @param {?object} prevState + * @param {?object} prevContext + * @param {DOMElement} rootNode DOM element representing the component. + * @optional + */ + componentDidUpdate: SpecPolicy.DEFINE_MANY, + + /** + * Invoked when the component is about to be removed from its parent and have + * its DOM representation destroyed. + * + * Use this as an opportunity to deallocate any external resources. + * + * NOTE: There is no `componentDidUnmount` since your component will have been + * destroyed by that point. + * + * @optional + */ + componentWillUnmount: SpecPolicy.DEFINE_MANY, + + // ==== Advanced methods ==== + + /** + * Updates the component's currently mounted DOM representation. + * + * By default, this implements React's rendering and reconciliation algorithm. + * Sophisticated clients may wish to override this. + * + * @param {ReactReconcileTransaction} transaction + * @internal + * @overridable + */ + updateComponent: SpecPolicy.OVERRIDE_BASE + +}; + +/** + * Mapping from class specification keys to special processing functions. + * + * Although these are declared like instance properties in the specification + * when defining classes using `React.createClass`, they are actually static + * and are accessible on the constructor instead of the prototype. Despite + * being static, they must be defined outside of the "statics" key under + * which all other static methods are defined. + */ +var RESERVED_SPEC_KEYS = { + displayName: function (Constructor, displayName) { + Constructor.displayName = displayName; + }, + mixins: function (Constructor, mixins) { + if (mixins) { + for (var i = 0; i < mixins.length; i++) { + mixSpecIntoComponent(Constructor, mixins[i]); + } + } + }, + childContextTypes: function (Constructor, childContextTypes) { + if (process.env.NODE_ENV !== 'production') { + validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext); + } + Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes); + }, + contextTypes: function (Constructor, contextTypes) { + if (process.env.NODE_ENV !== 'production') { + validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context); + } + Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes); + }, + /** + * Special case getDefaultProps which should move into statics but requires + * automatic merging. + */ + getDefaultProps: function (Constructor, getDefaultProps) { + if (Constructor.getDefaultProps) { + Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps); + } else { + Constructor.getDefaultProps = getDefaultProps; + } + }, + propTypes: function (Constructor, propTypes) { + if (process.env.NODE_ENV !== 'production') { + validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop); + } + Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes); + }, + statics: function (Constructor, statics) { + mixStaticSpecIntoComponent(Constructor, statics); + }, + autobind: function () {} }; + +// noop +function validateTypeDef(Constructor, typeDef, location) { + for (var propName in typeDef) { + if (typeDef.hasOwnProperty(propName)) { + // use a warning instead of an invariant so components + // don't show up in prod but only in __DEV__ + process.env.NODE_ENV !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0; + } + } +} + +function validateMethodOverride(isAlreadyDefined, name) { + var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null; + + // Disallow overriding of base class methods unless explicitly allowed. + if (ReactClassMixin.hasOwnProperty(name)) { + !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.', name) : _prodInvariant('73', name) : void 0; + } + + // Disallow defining methods more than once unless explicitly allowed. + if (isAlreadyDefined) { + !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('74', name) : void 0; + } +} + +/** + * Mixin helper which handles policy validation and reserved + * specification keys when building React classes. + */ +function mixSpecIntoComponent(Constructor, spec) { + if (!spec) { + if (process.env.NODE_ENV !== 'production') { + var typeofSpec = typeof spec; + var isMixinValid = typeofSpec === 'object' && spec !== null; + + process.env.NODE_ENV !== 'production' ? warning(isMixinValid, '%s: You\'re attempting to include a mixin that is either null ' + 'or not an object. Check the mixins included by the component, ' + 'as well as any mixins they include themselves. ' + 'Expected object but got %s.', Constructor.displayName || 'ReactClass', spec === null ? null : typeofSpec) : void 0; + } + + return; + } + + !(typeof spec !== 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to use a component class or function as a mixin. Instead, just use a regular object.') : _prodInvariant('75') : void 0; + !!ReactElement.isValidElement(spec) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to use a component as a mixin. Instead, just use a regular object.') : _prodInvariant('76') : void 0; + + var proto = Constructor.prototype; + var autoBindPairs = proto.__reactAutoBindPairs; + + // By handling mixins before any other properties, we ensure the same + // chaining order is applied to methods with DEFINE_MANY policy, whether + // mixins are listed before or after these methods in the spec. + if (spec.hasOwnProperty(MIXINS_KEY)) { + RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins); + } + + for (var name in spec) { + if (!spec.hasOwnProperty(name)) { + continue; + } + + if (name === MIXINS_KEY) { + // We have already handled mixins in a special case above. + continue; + } + + var property = spec[name]; + var isAlreadyDefined = proto.hasOwnProperty(name); + validateMethodOverride(isAlreadyDefined, name); + + if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { + RESERVED_SPEC_KEYS[name](Constructor, property); + } else { + // Setup methods on prototype: + // The following member methods should not be automatically bound: + // 1. Expected ReactClass methods (in the "interface"). + // 2. Overridden methods (that were mixed in). + var isReactClassMethod = ReactClassInterface.hasOwnProperty(name); + var isFunction = typeof property === 'function'; + var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false; + + if (shouldAutoBind) { + autoBindPairs.push(name, property); + proto[name] = property; + } else { + if (isAlreadyDefined) { + var specPolicy = ReactClassInterface[name]; + + // These cases should already be caught by validateMethodOverride. + !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.', specPolicy, name) : _prodInvariant('77', specPolicy, name) : void 0; + + // For methods which are defined more than once, call the existing + // methods before calling the new property, merging if appropriate. + if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) { + proto[name] = createMergedResultFunction(proto[name], property); + } else if (specPolicy === SpecPolicy.DEFINE_MANY) { + proto[name] = createChainedFunction(proto[name], property); + } + } else { + proto[name] = property; + if (process.env.NODE_ENV !== 'production') { + // Add verbose displayName to the function, which helps when looking + // at profiling tools. + if (typeof property === 'function' && spec.displayName) { + proto[name].displayName = spec.displayName + '_' + name; + } + } + } + } + } + } +} + +function mixStaticSpecIntoComponent(Constructor, statics) { + if (!statics) { + return; + } + for (var name in statics) { + var property = statics[name]; + if (!statics.hasOwnProperty(name)) { + continue; + } + + var isReserved = name in RESERVED_SPEC_KEYS; + !!isReserved ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved property, `%s`, that shouldn\'t be on the "statics" key. Define it as an instance property instead; it will still be accessible on the constructor.', name) : _prodInvariant('78', name) : void 0; + + var isInherited = name in Constructor; + !!isInherited ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('79', name) : void 0; + Constructor[name] = property; + } +} + +/** + * Merge two objects, but throw if both contain the same key. + * + * @param {object} one The first object, which is mutated. + * @param {object} two The second object + * @return {object} one after it has been mutated to contain everything in two. + */ +function mergeIntoWithNoDuplicateKeys(one, two) { + !(one && two && typeof one === 'object' && typeof two === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : _prodInvariant('80') : void 0; + + for (var key in two) { + if (two.hasOwnProperty(key)) { + !(one[key] === undefined) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.', key) : _prodInvariant('81', key) : void 0; + one[key] = two[key]; + } + } + return one; +} + +/** + * Creates a function that invokes two functions and merges their return values. + * + * @param {function} one Function to invoke first. + * @param {function} two Function to invoke second. + * @return {function} Function that invokes the two argument functions. + * @private + */ +function createMergedResultFunction(one, two) { + return function mergedResult() { + var a = one.apply(this, arguments); + var b = two.apply(this, arguments); + if (a == null) { + return b; + } else if (b == null) { + return a; + } + var c = {}; + mergeIntoWithNoDuplicateKeys(c, a); + mergeIntoWithNoDuplicateKeys(c, b); + return c; + }; +} + +/** + * Creates a function that invokes two functions and ignores their return vales. + * + * @param {function} one Function to invoke first. + * @param {function} two Function to invoke second. + * @return {function} Function that invokes the two argument functions. + * @private + */ +function createChainedFunction(one, two) { + return function chainedFunction() { + one.apply(this, arguments); + two.apply(this, arguments); + }; +} + +/** + * Binds a method to the component. + * + * @param {object} component Component whose method is going to be bound. + * @param {function} method Method to be bound. + * @return {function} The bound method. + */ +function bindAutoBindMethod(component, method) { + var boundMethod = method.bind(component); + if (process.env.NODE_ENV !== 'production') { + boundMethod.__reactBoundContext = component; + boundMethod.__reactBoundMethod = method; + boundMethod.__reactBoundArguments = null; + var componentName = component.constructor.displayName; + var _bind = boundMethod.bind; + boundMethod.bind = function (newThis) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + // User is trying to bind() an autobound method; we effectively will + // ignore the value of "this" that the user is trying to use, so + // let's warn. + if (newThis !== component && newThis !== null) { + process.env.NODE_ENV !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0; + } else if (!args.length) { + process.env.NODE_ENV !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0; + return boundMethod; + } + var reboundMethod = _bind.apply(boundMethod, arguments); + reboundMethod.__reactBoundContext = component; + reboundMethod.__reactBoundMethod = method; + reboundMethod.__reactBoundArguments = args; + return reboundMethod; + }; + } + return boundMethod; +} + +/** + * Binds all auto-bound methods in a component. + * + * @param {object} component Component whose method is going to be bound. + */ +function bindAutoBindMethods(component) { + var pairs = component.__reactAutoBindPairs; + for (var i = 0; i < pairs.length; i += 2) { + var autoBindKey = pairs[i]; + var method = pairs[i + 1]; + component[autoBindKey] = bindAutoBindMethod(component, method); + } +} + +/** + * Add more to the ReactClass base class. These are all legacy features and + * therefore not already part of the modern ReactComponent. + */ +var ReactClassMixin = { + + /** + * TODO: This will be deprecated because state should always keep a consistent + * type signature and the only use case for this, is to avoid that. + */ + replaceState: function (newState, callback) { + this.updater.enqueueReplaceState(this, newState); + if (callback) { + this.updater.enqueueCallback(this, callback, 'replaceState'); + } + }, + + /** + * Checks whether or not this composite component is mounted. + * @return {boolean} True if mounted, false otherwise. + * @protected + * @final + */ + isMounted: function () { + return this.updater.isMounted(this); + } +}; + +var ReactClassComponent = function () {}; +_assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin); + +/** + * Module for creating composite components. + * + * @class ReactClass + */ +var ReactClass = { + + /** + * Creates a composite component class given a class specification. + * See https://facebook.github.io/react/docs/top-level-api.html#react.createclass + * + * @param {object} spec Class specification (which must define `render`). + * @return {function} Component constructor function. + * @public + */ + createClass: function (spec) { + var Constructor = function (props, context, updater) { + // This constructor gets overridden by mocks. The argument is used + // by mocks to assert on what gets mounted. + + if (process.env.NODE_ENV !== 'production') { + process.env.NODE_ENV !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0; + } + + // Wire up auto-binding + if (this.__reactAutoBindPairs.length) { + bindAutoBindMethods(this); + } + + this.props = props; + this.context = context; + this.refs = emptyObject; + this.updater = updater || ReactNoopUpdateQueue; + + this.state = null; + + // ReactClasses doesn't have constructors. Instead, they use the + // getInitialState and componentWillMount methods for initialization. + + var initialState = this.getInitialState ? this.getInitialState() : null; + if (process.env.NODE_ENV !== 'production') { + // We allow auto-mocks to proceed as if they're returning null. + if (initialState === undefined && this.getInitialState._isMockFunction) { + // This is probably bad practice. Consider warning here and + // deprecating this convenience. + initialState = null; + } + } + !(typeof initialState === 'object' && !Array.isArray(initialState)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : _prodInvariant('82', Constructor.displayName || 'ReactCompositeComponent') : void 0; + + this.state = initialState; + }; + Constructor.prototype = new ReactClassComponent(); + Constructor.prototype.constructor = Constructor; + Constructor.prototype.__reactAutoBindPairs = []; + + injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor)); + + mixSpecIntoComponent(Constructor, spec); + + // Initialize the defaultProps property after all mixins have been merged. + if (Constructor.getDefaultProps) { + Constructor.defaultProps = Constructor.getDefaultProps(); + } + + if (process.env.NODE_ENV !== 'production') { + // This is a tag to indicate that the use of these method names is ok, + // since it's used with createClass. If it's not, then it's likely a + // mistake so we'll warn you to use the static property, property + // initializer or constructor respectively. + if (Constructor.getDefaultProps) { + Constructor.getDefaultProps.isReactClassApproved = {}; + } + if (Constructor.prototype.getInitialState) { + Constructor.prototype.getInitialState.isReactClassApproved = {}; + } + } + + !Constructor.prototype.render ? process.env.NODE_ENV !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : _prodInvariant('83') : void 0; + + if (process.env.NODE_ENV !== 'production') { + process.env.NODE_ENV !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0; + process.env.NODE_ENV !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0; + } + + // Reduce time spent doing lookups by setting these on the prototype. + for (var methodName in ReactClassInterface) { + if (!Constructor.prototype[methodName]) { + Constructor.prototype[methodName] = null; + } + } + + return Constructor; + }, + + injection: { + injectMixin: function (mixin) { + injectedMixins.push(mixin); + } + } + +}; + +module.exports = ReactClass; +}).call(this,require('_process')) + +},{"./ReactComponent":113,"./ReactElement":143,"./ReactNoopUpdateQueue":162,"./ReactPropTypeLocationNames":164,"./ReactPropTypeLocations":165,"./reactProdInvariant":219,"_process":37,"fbjs/lib/emptyObject":234,"fbjs/lib/invariant":241,"fbjs/lib/keyMirror":244,"fbjs/lib/keyOf":245,"fbjs/lib/warning":251,"object-assign":36}],113:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponent + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var ReactNoopUpdateQueue = require('./ReactNoopUpdateQueue'); + +var canDefineProperty = require('./canDefineProperty'); +var emptyObject = require('fbjs/lib/emptyObject'); +var invariant = require('fbjs/lib/invariant'); +var warning = require('fbjs/lib/warning'); + +/** + * Base class helpers for the updating state of a component. + */ +function ReactComponent(props, context, updater) { + this.props = props; + this.context = context; + this.refs = emptyObject; + // We initialize the default updater but the real one gets injected by the + // renderer. + this.updater = updater || ReactNoopUpdateQueue; +} + +ReactComponent.prototype.isReactComponent = {}; + +/** + * Sets a subset of the state. Always use this to mutate + * state. You should treat `this.state` as immutable. + * + * There is no guarantee that `this.state` will be immediately updated, so + * accessing `this.state` after calling this method may return the old value. + * + * There is no guarantee that calls to `setState` will run synchronously, + * as they may eventually be batched together. You can provide an optional + * callback that will be executed when the call to setState is actually + * completed. + * + * When a function is provided to setState, it will be called at some point in + * the future (not synchronously). It will be called with the up to date + * component arguments (state, props, context). These values can be different + * from this.* because your function may be called after receiveProps but before + * shouldComponentUpdate, and this new state, props, and context will not yet be + * assigned to this. + * + * @param {object|function} partialState Next partial state or function to + * produce next partial state to be merged with current state. + * @param {?function} callback Called after state is updated. + * @final + * @protected + */ +ReactComponent.prototype.setState = function (partialState, callback) { + !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0; + this.updater.enqueueSetState(this, partialState); + if (callback) { + this.updater.enqueueCallback(this, callback, 'setState'); + } +}; + +/** + * Forces an update. This should only be invoked when it is known with + * certainty that we are **not** in a DOM transaction. + * + * You may want to call this when you know that some deeper aspect of the + * component's state has changed but `setState` was not called. + * + * This will not invoke `shouldComponentUpdate`, but it will invoke + * `componentWillUpdate` and `componentDidUpdate`. + * + * @param {?function} callback Called after update is complete. + * @final + * @protected + */ +ReactComponent.prototype.forceUpdate = function (callback) { + this.updater.enqueueForceUpdate(this); + if (callback) { + this.updater.enqueueCallback(this, callback, 'forceUpdate'); + } +}; + +/** + * Deprecated APIs. These APIs used to exist on classic React classes but since + * we would like to deprecate them, we're not going to move them over to this + * modern base class. Instead, we define a getter that warns if it's accessed. + */ +if (process.env.NODE_ENV !== 'production') { + var deprecatedAPIs = { + isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'], + replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).'] + }; + var defineDeprecationWarning = function (methodName, info) { + if (canDefineProperty) { + Object.defineProperty(ReactComponent.prototype, methodName, { + get: function () { + process.env.NODE_ENV !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : void 0; + return undefined; + } + }); + } + }; + for (var fnName in deprecatedAPIs) { + if (deprecatedAPIs.hasOwnProperty(fnName)) { + defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); + } + } +} + +module.exports = ReactComponent; +}).call(this,require('_process')) + +},{"./ReactNoopUpdateQueue":162,"./canDefineProperty":197,"./reactProdInvariant":219,"_process":37,"fbjs/lib/emptyObject":234,"fbjs/lib/invariant":241,"fbjs/lib/warning":251}],114:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponentBrowserEnvironment + */ + +'use strict'; + +var DOMChildrenOperations = require('./DOMChildrenOperations'); +var ReactDOMIDOperations = require('./ReactDOMIDOperations'); + +/** + * Abstracts away all functionality of the reconciler that requires knowledge of + * the browser context. TODO: These callers should be refactored to avoid the + * need for this injection. + */ +var ReactComponentBrowserEnvironment = { + + processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates, + + replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup, + + /** + * If a particular environment requires that some resources be cleaned up, + * specify this in the injected Mixin. In the DOM, we would likely want to + * purge any cached node ID lookups. + * + * @private + */ + unmountIDFromEnvironment: function (rootNodeID) {} + +}; + +module.exports = ReactComponentBrowserEnvironment; +},{"./DOMChildrenOperations":88,"./ReactDOMIDOperations":129}],115:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2014-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponentEnvironment + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var invariant = require('fbjs/lib/invariant'); + +var injected = false; + +var ReactComponentEnvironment = { + + /** + * Optionally injectable environment dependent cleanup hook. (server vs. + * browser etc). Example: A browser system caches DOM nodes based on component + * ID and must remove that cache entry when this instance is unmounted. + */ + unmountIDFromEnvironment: null, + + /** + * Optionally injectable hook for swapping out mount images in the middle of + * the tree. + */ + replaceNodeWithMarkup: null, + + /** + * Optionally injectable hook for processing a queue of child updates. Will + * later move into MultiChildComponents. + */ + processChildrenUpdates: null, + + injection: { + injectEnvironment: function (environment) { + !!injected ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : _prodInvariant('104') : void 0; + ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment; + ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup; + ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates; + injected = true; + } + } + +}; + +module.exports = ReactComponentEnvironment; +}).call(this,require('_process')) + +},{"./reactProdInvariant":219,"_process":37,"fbjs/lib/invariant":241}],116:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactComponentTreeDevtool + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'); + +var ReactCurrentOwner = require('./ReactCurrentOwner'); + +var invariant = require('fbjs/lib/invariant'); +var warning = require('fbjs/lib/warning'); + +var tree = {}; +var unmountedIDs = {}; +var rootIDs = {}; + +function updateTree(id, update) { + if (!tree[id]) { + tree[id] = { + element: null, + parentID: null, + ownerID: null, + text: null, + childIDs: [], + displayName: 'Unknown', + isMounted: false, + updateCount: 0 + }; + } + update(tree[id]); +} + +function purgeDeep(id) { + var item = tree[id]; + if (item) { + var childIDs = item.childIDs; + + delete tree[id]; + childIDs.forEach(purgeDeep); + } +} + +function describeComponentFrame(name, source, ownerName) { + return '\n in ' + name + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : ''); +} + +function describeID(id) { + var name = ReactComponentTreeDevtool.getDisplayName(id); + var element = ReactComponentTreeDevtool.getElement(id); + var ownerID = ReactComponentTreeDevtool.getOwnerID(id); + var ownerName; + if (ownerID) { + ownerName = ReactComponentTreeDevtool.getDisplayName(ownerID); + } + process.env.NODE_ENV !== 'production' ? warning(element, 'ReactComponentTreeDevtool: Missing React element for debugID %s when ' + 'building stack', id) : void 0; + return describeComponentFrame(name, element && element._source, ownerName); +} + +var ReactComponentTreeDevtool = { + onSetDisplayName: function (id, displayName) { + updateTree(id, function (item) { + return item.displayName = displayName; + }); + }, + onSetChildren: function (id, nextChildIDs) { + updateTree(id, function (item) { + item.childIDs = nextChildIDs; + + nextChildIDs.forEach(function (nextChildID) { + var nextChild = tree[nextChildID]; + !nextChild ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected devtool events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('68') : void 0; + !(nextChild.displayName != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onSetDisplayName() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('69') : void 0; + !(nextChild.childIDs != null || nextChild.text != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onSetChildren() or onSetText() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('70') : void 0; + !nextChild.isMounted ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0; + if (nextChild.parentID == null) { + nextChild.parentID = id; + // TODO: This shouldn't be necessary but mounting a new root during in + // componentWillMount currently causes not-yet-mounted components to + // be purged from our tree data so their parent ID is missing. + } + !(nextChild.parentID === id) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Expected onSetParent() and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('72', nextChildID, nextChild.parentID, id) : void 0; + }); + }); + }, + onSetOwner: function (id, ownerID) { + updateTree(id, function (item) { + return item.ownerID = ownerID; + }); + }, + onSetParent: function (id, parentID) { + updateTree(id, function (item) { + return item.parentID = parentID; + }); + }, + onSetText: function (id, text) { + updateTree(id, function (item) { + return item.text = text; + }); + }, + onBeforeMountComponent: function (id, element) { + updateTree(id, function (item) { + return item.element = element; + }); + }, + onBeforeUpdateComponent: function (id, element) { + updateTree(id, function (item) { + return item.element = element; + }); + }, + onMountComponent: function (id) { + updateTree(id, function (item) { + return item.isMounted = true; + }); + }, + onMountRootComponent: function (id) { + rootIDs[id] = true; + }, + onUpdateComponent: function (id) { + updateTree(id, function (item) { + return item.updateCount++; + }); + }, + onUnmountComponent: function (id) { + updateTree(id, function (item) { + return item.isMounted = false; + }); + unmountedIDs[id] = true; + delete rootIDs[id]; + }, + purgeUnmountedComponents: function () { + if (ReactComponentTreeDevtool._preventPurging) { + // Should only be used for testing. + return; + } + + for (var id in unmountedIDs) { + purgeDeep(id); + } + unmountedIDs = {}; + }, + isMounted: function (id) { + var item = tree[id]; + return item ? item.isMounted : false; + }, + getCurrentStackAddendum: function (topElement) { + var info = ''; + if (topElement) { + var type = topElement.type; + var name = typeof type === 'function' ? type.displayName || type.name : type; + var owner = topElement._owner; + info += describeComponentFrame(name || 'Unknown', topElement._source, owner && owner.getName()); + } + + var currentOwner = ReactCurrentOwner.current; + var id = currentOwner && currentOwner._debugID; + + info += ReactComponentTreeDevtool.getStackAddendumByID(id); + return info; + }, + getStackAddendumByID: function (id) { + var info = ''; + while (id) { + info += describeID(id); + id = ReactComponentTreeDevtool.getParentID(id); + } + return info; + }, + getChildIDs: function (id) { + var item = tree[id]; + return item ? item.childIDs : []; + }, + getDisplayName: function (id) { + var item = tree[id]; + return item ? item.displayName : 'Unknown'; + }, + getElement: function (id) { + var item = tree[id]; + return item ? item.element : null; + }, + getOwnerID: function (id) { + var item = tree[id]; + return item ? item.ownerID : null; + }, + getParentID: function (id) { + var item = tree[id]; + return item ? item.parentID : null; + }, + getSource: function (id) { + var item = tree[id]; + var element = item ? item.element : null; + var source = element != null ? element._source : null; + return source; + }, + getText: function (id) { + var item = tree[id]; + return item ? item.text : null; + }, + getUpdateCount: function (id) { + var item = tree[id]; + return item ? item.updateCount : 0; + }, + getRootIDs: function () { + return Object.keys(rootIDs); + }, + getRegisteredIDs: function () { + return Object.keys(tree); + } +}; + +module.exports = ReactComponentTreeDevtool; +}).call(this,require('_process')) + +},{"./ReactCurrentOwner":118,"./reactProdInvariant":219,"_process":37,"fbjs/lib/invariant":241,"fbjs/lib/warning":251}],117:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactCompositeComponent + */ + +'use strict'; + +var _prodInvariant = require('./reactProdInvariant'), + _assign = require('object-assign'); + +var ReactComponentEnvironment = require('./ReactComponentEnvironment'); +var ReactCurrentOwner = require('./ReactCurrentOwner'); +var ReactElement = require('./ReactElement'); +var ReactErrorUtils = require('./ReactErrorUtils'); +var ReactInstanceMap = require('./ReactInstanceMap'); +var ReactInstrumentation = require('./ReactInstrumentation'); +var ReactNodeTypes = require('./ReactNodeTypes'); +var ReactPropTypeLocations = require('./ReactPropTypeLocations'); +var ReactReconciler = require('./ReactReconciler'); + +var checkReactTypeSpec = require('./checkReactTypeSpec'); +var emptyObject = require('fbjs/lib/emptyObject'); +var invariant = require('fbjs/lib/invariant'); +var shallowEqual = require('fbjs/lib/shallowEqual'); +var shouldUpdateReactComponent = require('./shouldUpdateReactComponent'); +var warning = require('fbjs/lib/warning'); + +var CompositeTypes = { + ImpureClass: 0, + PureClass: 1, + StatelessFunctional: 2 +}; + +function StatelessComponent(Component) {} +StatelessComponent.prototype.render = function () { + var Component = ReactInstanceMap.get(this)._currentElement.type; + var element = Component(this.props, this.context, this.updater); + warnIfInvalidElement(Component, element); + return element; +}; + +function warnIfInvalidElement(Component, element) { + if (process.env.NODE_ENV !== 'production') { + process.env.NODE_ENV !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0; + process.env.NODE_ENV !== 'production' ? warning(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component') : void 0; + } +} + +function invokeComponentDidMountWithTimer() { + var publicInstance = this._instance; + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidMount'); + } + publicInstance.componentDidMount(); + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidMount'); + } +} + +function invokeComponentDidUpdateWithTimer(prevProps, prevState, prevContext) { + var publicInstance = this._instance; + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidUpdate'); + } + publicInstance.componentDidUpdate(prevProps, prevState, prevContext); + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidUpdate'); + } +} + +function shouldConstruct(Component) { + return !!(Component.prototype && Component.prototype.isReactComponent); +} + +function isPureComponent(Component) { + return !!(Component.prototype && Component.prototype.isPureReactComponent); +} + +/** + * ------------------ The Life-Cycle of a Composite Component ------------------ + * + * - constructor: Initialization of state. The instance is now retained. + * - componentWillMount + * - render + * - [children's constructors] + * - [children's componentWillMount and render] + * - [children's componentDidMount] + * - componentDidMount + * + * Update Phases: + * - componentWillReceiveProps (only called if parent updated) + * - shouldComponentUpdate + * - componentWillUpdate + * - render + * - [children's constructors or receive props phases] + * - componentDidUpdate + * + * - componentWillUnmount + * - [children's componentWillUnmount] + * - [children destroyed] + * - (destroyed): The instance is now blank, released by React and ready for GC. + * + * ----------------------------------------------------------------------------- + */ + +/** + * An incrementing ID assigned to each component when it is mounted. This is + * used to enforce the order in which `ReactUpdates` updates dirty components. + * + * @private + */ +var nextMountID = 1; + +/** + * @lends {ReactCompositeComponent.prototype} + */ +var ReactCompositeComponentMixin = { + + /** + * Base constructor for all composite component. + * + * @param {ReactElement} element + * @final + * @internal + */ + construct: function (element) { + this._currentElement = element; + this._rootNodeID = null; + this._compositeType = null; + this._instance = null; + this._hostParent = null; + this._hostContainerInfo = null; + + // See ReactUpdateQueue + this._updateBatchNumber = null; + this._pendingElement = null; + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + + this._renderedNodeType = null; + this._renderedComponent = null; + this._context = null; + this._mountOrder = 0; + this._topLevelWrapper = null; + + // See ReactUpdates and ReactUpdateQueue. + this._pendingCallbacks = null; + + // ComponentWillUnmount shall only be called once + this._calledComponentWillUnmount = false; + + if (process.env.NODE_ENV !== 'production') { + this._warnedAboutRefsInRender = false; + } + }, + + /** + * Initializes the component, renders markup, and registers event listeners. + * + * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction + * @param {?object} hostParent + * @param {?object} hostContainerInfo + * @param {?object} context + * @return {?string} Rendered markup to be inserted into the DOM. + * @final + * @internal + */ + mountComponent: function (transaction, hostParent, hostContainerInfo, context) { + var _this = this; + + this._context = context; + this._mountOrder = nextMountID++; + this._hostParent = hostParent; + this._hostContainerInfo = hostContainerInfo; + + var publicProps = this._currentElement.props; + var publicContext = this._processContext(context); + + var Component = this._currentElement.type; + + var updateQueue = transaction.getUpdateQueue(); + + // Initialize the public class + var doConstruct = shouldConstruct(Component); + var inst = this._constructComponent(doConstruct, publicProps, publicContext, updateQueue); + var renderedElement; + + // Support functional components + if (!doConstruct && (inst == null || inst.render == null)) { + renderedElement = inst; + warnIfInvalidElement(Component, renderedElement); + !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : _prodInvariant('105', Component.displayName || Component.name || 'Component') : void 0; + inst = new StatelessComponent(Component); + this._compositeType = CompositeTypes.StatelessFunctional; + } else { + if (isPureComponent(Component)) { + this._compositeType = CompositeTypes.PureClass; + } else { + this._compositeType = CompositeTypes.ImpureClass; + } + } + + if (process.env.NODE_ENV !== 'production') { + // This will throw later in _renderValidatedComponent, but add an early + // warning now to help debugging + if (inst.render == null) { + process.env.NODE_ENV !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0; + } + + var propsMutated = inst.props !== publicProps; + var componentName = Component.displayName || Component.name || 'Component'; + + process.env.NODE_ENV !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + 'up the same props that your component\'s constructor was passed.', componentName, componentName) : void 0; + } + + // These should be set up in the constructor, but as a convenience for + // simpler class abstractions, we set them up after the fact. + inst.props = publicProps; + inst.context = publicContext; + inst.refs = emptyObject; + inst.updater = updateQueue; + + this._instance = inst; + + // Store a reference from the instance back to the internal representation + ReactInstanceMap.set(inst, this); + + if (process.env.NODE_ENV !== 'production') { + // Since plain JS classes are defined without any special initialization + // logic, we can not catch common errors early. Therefore, we have to + // catch them here, at initialization time, instead. + process.env.NODE_ENV !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0; + process.env.NODE_ENV !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0; + process.env.NODE_ENV !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0; + process.env.NODE_ENV !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0; + process.env.NODE_ENV !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : void 0; + process.env.NODE_ENV !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0; + process.env.NODE_ENV !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0; + } + + var initialState = inst.state; + if (initialState === undefined) { + inst.state = initialState = null; + } + !(typeof initialState === 'object' && !Array.isArray(initialState)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0; + + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + + var markup; + if (inst.unstable_handleError) { + markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context); + } else { + markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context); + } + + if (inst.componentDidMount) { + if (process.env.NODE_ENV !== 'production') { + transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this); + } else { + transaction.getReactMountReady().enqueue(inst.componentDidMount, inst); + } + } + + if (process.env.NODE_ENV !== 'production') { + if (this._debugID) { + var callback = function (component) { + return ReactInstrumentation.debugTool.onComponentHasMounted(_this._debugID); + }; + transaction.getReactMountReady().enqueue(callback, this); + } + } + + return markup; + }, + + _constructComponent: function (doConstruct, publicProps, publicContext, updateQueue) { + if (process.env.NODE_ENV !== 'production') { + ReactCurrentOwner.current = this; + try { + return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue); + } finally { + ReactCurrentOwner.current = null; + } + } else { + return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue); + } + }, + + _constructComponentWithoutOwner: function (doConstruct, publicProps, publicContext, updateQueue) { + var Component = this._currentElement.type; + var instanceOrElement; + if (doConstruct) { + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'ctor'); + } + } + instanceOrElement = new Component(publicProps, publicContext, updateQueue); + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'ctor'); + } + } + } else { + // This can still be an instance in case of factory components + // but we'll count this as time spent rendering as the more common case. + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render'); + } + } + instanceOrElement = Component(publicProps, publicContext, updateQueue); + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render'); + } + } + } + return instanceOrElement; + }, + + performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) { + var markup; + var checkpoint = transaction.checkpoint(); + try { + markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context); + } catch (e) { + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onError(); + } + } + // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint + transaction.rollback(checkpoint); + this._instance.unstable_handleError(e); + if (this._pendingStateQueue) { + this._instance.state = this._processPendingState(this._instance.props, this._instance.context); + } + checkpoint = transaction.checkpoint(); + + this._renderedComponent.unmountComponent(true); + transaction.rollback(checkpoint); + + // Try again - we've informed the component about the error, so they can render an error message this time. + // If this throws again, the error will bubble up (and can be caught by a higher error boundary). + markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context); + } + return markup; + }, + + performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) { + var inst = this._instance; + if (inst.componentWillMount) { + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillMount'); + } + } + inst.componentWillMount(); + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillMount'); + } + } + // When mounting, calls to `setState` by `componentWillMount` will set + // `this._pendingStateQueue` without triggering a re-render. + if (this._pendingStateQueue) { + inst.state = this._processPendingState(inst.props, inst.context); + } + } + + // If not a stateless component, we now render + if (renderedElement === undefined) { + renderedElement = this._renderValidatedComponent(); + } + + var nodeType = ReactNodeTypes.getType(renderedElement); + this._renderedNodeType = nodeType; + var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */ + ); + this._renderedComponent = child; + if (process.env.NODE_ENV !== 'production') { + if (child._debugID !== 0 && this._debugID !== 0) { + ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID); + } + } + + var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context)); + + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []); + } + } + + return markup; + }, + + getHostNode: function () { + return ReactReconciler.getHostNode(this._renderedComponent); + }, + + /** + * Releases any resources allocated by `mountComponent`. + * + * @final + * @internal + */ + unmountComponent: function (safely) { + if (!this._renderedComponent) { + return; + } + var inst = this._instance; + + if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) { + inst._calledComponentWillUnmount = true; + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUnmount'); + } + } + if (safely) { + var name = this.getName() + '.componentWillUnmount()'; + ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst)); + } else { + inst.componentWillUnmount(); + } + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUnmount'); + } + } + } + + if (this._renderedComponent) { + ReactReconciler.unmountComponent(this._renderedComponent, safely); + this._renderedNodeType = null; + this._renderedComponent = null; + this._instance = null; + } + + // Reset pending fields + // Even if this component is scheduled for another update in ReactUpdates, + // it would still be ignored because these fields are reset. + this._pendingStateQueue = null; + this._pendingReplaceState = false; + this._pendingForceUpdate = false; + this._pendingCallbacks = null; + this._pendingElement = null; + + // These fields do not really need to be reset since this object is no + // longer accessible. + this._context = null; + this._rootNodeID = null; + this._topLevelWrapper = null; + + // Delete the reference from the instance to this internal representation + // which allow the internals to be properly cleaned up even if the user + // leaks a reference to the public instance. + ReactInstanceMap.remove(inst); + + // Some existing components rely on inst.props even after they've been + // destroyed (in event handlers). + // TODO: inst.props = null; + // TODO: inst.state = null; + // TODO: inst.context = null; + }, + + /** + * Filters the context object to only contain keys specified in + * `contextTypes` + * + * @param {object} context + * @return {?object} + * @private + */ + _maskContext: function (context) { + var Component = this._currentElement.type; + var contextTypes = Component.contextTypes; + if (!contextTypes) { + return emptyObject; + } + var maskedContext = {}; + for (var contextName in contextTypes) { + maskedContext[contextName] = context[contextName]; + } + return maskedContext; + }, + + /** + * Filters the context object to only contain keys specified in + * `contextTypes`, and asserts that they are valid. + * + * @param {object} context + * @return {?object} + * @private + */ + _processContext: function (context) { + var maskedContext = this._maskContext(context); + if (process.env.NODE_ENV !== 'production') { + var Component = this._currentElement.type; + if (Component.contextTypes) { + this._checkContextTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context); + } + } + return maskedContext; + }, + + /** + * @param {object} currentContext + * @return {object} + * @private + */ + _processChildContext: function (currentContext) { + var Component = this._currentElement.type; + var inst = this._instance; + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onBeginProcessingChildContext(); + } + var childContext = inst.getChildContext && inst.getChildContext(); + if (process.env.NODE_ENV !== 'production') { + ReactInstrumentation.debugTool.onEndProcessingChildContext(); + } + if (childContext) { + !(typeof Component.childContextTypes === 'object') ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0; + if (process.env.NODE_ENV !== 'production') { + this._checkContextTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext); + } + for (var name in childContext) { + !(name in Component.childContextTypes) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name) : void 0; + } + return _assign({}, currentContext, childContext); + } + return currentContext; + }, + + /** + * Assert that the context types are valid + * + * @param {object} typeSpecs Map of context field to a ReactPropType + * @param {object} values Runtime values that need to be type-checked + * @param {string} location e.g. "prop", "context", "child context" + * @private + */ + _checkContextTypes: function (typeSpecs, values, location) { + checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID); + }, + + receiveComponent: function (nextElement, transaction, nextContext) { + var prevElement = this._currentElement; + var prevContext = this._context; + + this._pendingElement = null; + + this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext); + }, + + /** + * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate` + * is set, update the component. + * + * @param {ReactReconcileTransaction} transaction + * @internal + */ + performUpdateIfNecessary: function (transaction) { + if (this._pendingElement != null) { + ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context); + } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) { + this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context); + } else { + this._updateBatchNumber = null; + } + }, + + /** + * Perform an update to a mounted component. The componentWillReceiveProps and + * shouldComponentUpdate methods are called, then (assuming the update isn't + * skipped) the remaining update lifecycle methods are called and the DOM + * representation is updated. + * + * By default, this implements React's rendering and reconciliation algorithm. + * Sophisticated clients may wish to override this. + * + * @param {ReactReconcileTransaction} transaction + * @param {ReactElement} prevParentElement + * @param {ReactElement} nextParentElement + * @internal + * @overridable + */ + updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) { + var inst = this._instance; + !(inst != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Attempted to update component `%s` that has already been unmounted (or failed to mount).', this.getName() || 'ReactCompositeComponent') : _prodInvariant('136', this.getName() || 'ReactCompositeComponent') : void 0; + + var willReceive = false; + var nextContext; + + // Determine if the context has changed or not + if (this._context === nextUnmaskedContext) { + nextContext = inst.context; + } else { + nextContext = this._processContext(nextUnmaskedContext); + willReceive = true; + } + + var prevProps = prevParentElement.props; + var nextProps = nextParentElement.props; + + // Not a simple state update but a props update + if (prevParentElement !== nextParentElement) { + willReceive = true; + } + + // An update here will schedule an update but immediately set + // _pendingStateQueue which will ensure that any state updates gets + // immediately reconciled instead of waiting for the next batch. + if (willReceive && inst.componentWillReceiveProps) { + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillReceiveProps'); + } + } + inst.componentWillReceiveProps(nextProps, nextContext); + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillReceiveProps'); + } + } + } + + var nextState = this._processPendingState(nextProps, nextContext); + var shouldUpdate = true; + + if (!this._pendingForceUpdate) { + if (inst.shouldComponentUpdate) { + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'shouldComponentUpdate'); + } + } + shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext); + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'shouldComponentUpdate'); + } + } + } else { + if (this._compositeType === CompositeTypes.PureClass) { + shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState); + } + } + } + + if (process.env.NODE_ENV !== 'production') { + process.env.NODE_ENV !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0; + } + + this._updateBatchNumber = null; + if (shouldUpdate) { + this._pendingForceUpdate = false; + // Will set `this.props`, `this.state` and `this.context`. + this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext); + } else { + // If it's determined that a component should not update, we still want + // to set props and state but we shortcut the rest of the update. + this._currentElement = nextParentElement; + this._context = nextUnmaskedContext; + inst.props = nextProps; + inst.state = nextState; + inst.context = nextContext; + } + }, + + _processPendingState: function (props, context) { + var inst = this._instance; + var queue = this._pendingStateQueue; + var replace = this._pendingReplaceState; + this._pendingReplaceState = false; + this._pendingStateQueue = null; + + if (!queue) { + return inst.state; + } + + if (replace && queue.length === 1) { + return queue[0]; + } + + var nextState = _assign({}, replace ? queue[0] : inst.state); + for (var i = replace ? 1 : 0; i < queue.length; i++) { + var partial = queue[i]; + _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial); + } + + return nextState; + }, + + /** + * Merges new props and state, notifies delegate methods of update and + * performs update. + * + * @param {ReactElement} nextElement Next element + * @param {object} nextProps Next public object to set as properties. + * @param {?object} nextState Next object to set as state. + * @param {?object} nextContext Next public object to set as context. + * @param {ReactReconcileTransaction} transaction + * @param {?object} unmaskedContext + * @private + */ + _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) { + var _this2 = this; + + var inst = this._instance; + + var hasComponentDidUpdate = Boolean(inst.componentDidUpdate); + var prevProps; + var prevState; + var prevContext; + if (hasComponentDidUpdate) { + prevProps = inst.props; + prevState = inst.state; + prevContext = inst.context; + } + + if (inst.componentWillUpdate) { + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUpdate'); + } + } + inst.componentWillUpdate(nextProps, nextState, nextContext); + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUpdate'); + } + } + } + + this._currentElement = nextElement; + this._context = unmaskedContext; + inst.props = nextProps; + inst.state = nextState; + inst.context = nextContext; + + this._updateRenderedComponent(transaction, unmaskedContext); + + if (hasComponentDidUpdate) { + if (process.env.NODE_ENV !== 'production') { + transaction.getReactMountReady().enqueue(invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext), this); + } else { + transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst); + } + } + + if (process.env.NODE_ENV !== 'production') { + if (this._debugID) { + var callback = function () { + return ReactInstrumentation.debugTool.onComponentHasUpdated(_this2._debugID); + }; + transaction.getReactMountReady().enqueue(callback, this); + } + } + }, + + /** + * Call the component's `render` method and update the DOM accordingly. + * + * @param {ReactReconcileTransaction} transaction + * @internal + */ + _updateRenderedComponent: function (transaction, context) { + var prevComponentInstance = this._renderedComponent; + var prevRenderedElement = prevComponentInstance._currentElement; + var nextRenderedElement = this._renderValidatedComponent(); + if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) { + ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context)); + } else { + var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance); + ReactReconciler.unmountComponent(prevComponentInstance, false); + + var nodeType = ReactNodeTypes.getType(nextRenderedElement); + this._renderedNodeType = nodeType; + var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */ + ); + this._renderedComponent = child; + if (process.env.NODE_ENV !== 'production') { + if (child._debugID !== 0 && this._debugID !== 0) { + ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID); + } + } + + var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context)); + + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []); + } + } + + this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance); + } + }, + + /** + * Overridden in shallow rendering. + * + * @protected + */ + _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) { + ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance); + }, + + /** + * @protected + */ + _renderValidatedComponentWithoutOwnerOrContext: function () { + var inst = this._instance; + + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render'); + } + } + var renderedComponent = inst.render(); + if (process.env.NODE_ENV !== 'production') { + if (this._debugID !== 0) { + ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render'); + } + } + + if (process.env.NODE_ENV !== 'production') { + // We allow auto-mocks to proceed as if they're returning null. + if (renderedComponent === undefined && inst.render._isMockFunction) { + // This is probably bad practice. Consider warning here and + // deprecating this convenience. + renderedComponent = null; + } + } + + return renderedComponent; + }, + + /** + * @private + */ + _renderValidatedComponent: function () { + var renderedComponent; + if (process.env.NODE_ENV !== 'production' || this._compositeType !== CompositeTypes.StatelessFunctional) { + ReactCurrentOwner.current = this; + try { + renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext(); + } finally { + ReactCurrentOwner.current = null; + } + } else { + renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext(); + } + !( + // TODO: An `isValidNode` function would probably be more appropriate + renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? process.env.NODE_ENV !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : _prodInvariant('109', this.getName() || 'ReactCompositeComponent') : void 0; + + return renderedComponent; + }, + + /** + * Lazily allocates the refs object and stores `component` as `ref`. + * + * @param {string} ref Reference name. + * @param {component} component Component to store as `ref`. + * @final + * @private + */ + attachRef: function (ref, component) { + var inst = this.getPublicInstance(); + !(inst != null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : _prodInvariant('110') : void 0; + var publicComponentInstance = component.getPublicInstance(); + if (process.env.NODE_ENV !== 'production') { + var componentName = component && component.getName ? component.getName() : 'a component'; + process.env.NODE_ENV !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0; + } + var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs; + refs[ref] = publicComponentInstance; + }, + + /** + * Detaches a reference name. + * + * @param {string} ref Name to dereference. + * @final + * @private + */ + detachRef: function (ref) { + var refs = this.getPublicInstance().refs; + delete refs[ref]; + }, + + /** + * Get a text description of the component that can be used to identify it + * in error messages. + * @return {string} The name or null. + * @internal + */ + getName: function () { + var type = this._currentElement.type; + var constructor = this._instance && this._instance.constructor; + return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null; + }, + + /** + * Get the publicly accessible representation of this component - i.e. what + * is exposed by refs and returned by render. Can be null for stateless + * components. + * + * @return {ReactComponent} the public component instance. + * @internal + */ + getPublicInstance: function () { + var inst = this._instance; + if (this._compositeType === CompositeTypes.StatelessFunctional) { + return null; + } + return inst; + }, + + // Stub + _instantiateReactComponent: null + +}; + +var ReactCompositeComponent = { + + Mixin: ReactCompositeComponentMixin + +}; + +module.exports = ReactCompositeComponent; +}).call(this,require('_process')) + +},{"./ReactComponentEnvironment":115,"./ReactCurrentOwner":118,"./ReactElement":143,"./ReactErrorUtils":146,"./ReactInstanceMap":154,"./ReactInstrumentation":155,"./ReactNodeTypes":161,"./ReactPropTypeLocations":165,"./ReactReconciler":170,"./checkReactTypeSpec":198,"./reactProdInvariant":219,"./shouldUpdateReactComponent":223,"_process":37,"fbjs/lib/emptyObject":234,"fbjs/lib/invariant":241,"fbjs/lib/shallowEqual":250,"fbjs/lib/warning":251,"object-assign":36}],118:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactCurrentOwner + */ + +'use strict'; + +/** + * Keeps track of the current owner. + * + * The current owner is the component who should own any components that are + * currently being constructed. + */ + +var ReactCurrentOwner = { + + /** + * @internal + * @type {ReactComponent} + */ + current: null + +}; + +module.exports = ReactCurrentOwner; +},{}],119:[function(require,module,exports){ +(function (process){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactDOM + */ + +/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/ + +'use strict'; + +var ReactDOMComponentTree = require('./ReactDOMComponentTree'); +var ReactDefaultInjection = require('./ReactDefaultInjection'); +var ReactMount = require('./ReactMount'); +var ReactReconciler = require('./ReactReconciler'); +var ReactUpdates = require('./ReactUpdates'); +var ReactVersion = require('./ReactVersion'); + +var findDOMNode = require('./findDOMNode'); +var getHostComponentFromComposite = require('./getHostComponentFromComposite'); +var renderSubtreeIntoContainer = require('./renderSubtreeIntoContainer'); +var warning = require('fbjs/lib/warning'); + +ReactDefaultInjection.inject(); + +var ReactDOM = { + findDOMNode: findDOMNode, + render: ReactMount.render, + unmountComponentAtNode: ReactMount.unmountComponentAtNode, + version: ReactVersion, + + /* eslint-disable camelcase */ + unstable_batchedUpdates: ReactUpdates.batchedUpdates, + unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer +}; + +// Inject the runtime into a devtools global hook regardless of browser. +// Allows for debugging when the hook is injected on the page. +/* eslint-enable camelcase */ +if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') { + __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({ + ComponentTree: { + getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode, + getNodeFromInstance: function (inst) { + // inst is an internal instance (but could be a composite) + if (inst._renderedComponent) { + inst = getHostComponentFromComposite(inst); + } + if (inst) { + return ReactDOMComponentTree.getNodeFromInstance(inst); + } else { + return null; + } + } + }, + Mount: ReactMount, + Reconciler: ReactReconciler + }); +} + +if (process.env.NODE_ENV !== 'production') { + var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment'); + if (ExecutionEnvironment.canUseDOM && window.top === window.self) { + + // First check if devtools is not installed + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { + // If we're in Chrome or Firefox, provide a download link if not installed. + if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) { + // Firefox does not have the issue with devtools loaded over file:// + var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1; + console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools'); + } + } + + var testFunc = function testFn() {}; + process.env.NODE_ENV !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0; + + // If we're in IE8, check to see if we are in compatibility mode and provide + // information on preventing compatibility mode + var ieCompatibilityMode = document.documentMode && document.documentMode < 8; + + process.env.NODE_ENV !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '') : void 0; + + var expectedFeatures = [ + // shims + Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim]; + + for (var i = 0; i < expectedFeatures.length; i++) { + if (!expectedFeatures[i]) { + process.env.NODE_ENV !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0; + break; + } + } + } +} + +module.exports = ReactDOM; +}).call(this,require('_process')) + +},{"./ReactDOMComponentTree":123,"./ReactDefaultInjection":142,"./ReactMount":158,"./ReactReconciler":170,"./ReactUpdates":175,"./ReactVersion":176,"./findDOMNode":202,"./getHostComponentFromComposite":209,"./renderSubtreeIntoContainer":220,"_process":37,"fbjs/lib/ExecutionEnvironment":227,"fbjs/lib/warning":251}],120:[function(require,module,exports){ +/** + * Copyright 2013-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule ReactDOMButton + */ + +'use strict'; + +var DisabledInputUtils = require('./DisabledInputUtils'); + +/** + * Implements a