[
  {
    "path": ".gitignore",
    "content": "node_modules\n/nbproject/\n.idea/\n"
  },
  {
    "path": "LICENSE",
    "content": "This Source Code Form is subject to the terms of the Mozilla Public\nLicense, v. 2.0. If a copy of the MPL was not distributed with this\nfile, You can obtain one at http://mozilla.org/MPL/2.0/.\n"
  },
  {
    "path": "README.md",
    "content": "**Development of ScanJS has stopped.**\n=======================================\n\nWe are using [ESLint](http://eslint.org) instead.\nYour options:\n* XSS-prevention rule during CI with [eslint-plugin-no-unsanitized](https://github.com/mozilla/eslint-plugin-no-unsanitized). This assumes that you prevent/disallow obfuscation and that your code is subject to code review before it is being scanned (e.g., to catch intentional malicious/obfuscated code)\n* If you want something that warn for \"all the things\" that scanjs pointed out, you will need to use and build upon [eslint-config-scanjs](https://github.com/mozfreddyb/eslint-config-scanjs). \n\nThank you.\n\n--------------------------------\n\nScanJS was was a Static analysis tool for javascript code. ScanJS was created as an aid for security review, to help identify security issues in client-side web applications.\n\nScanJS used Acorn to convert sources to AST, then walks AST looking for source patterns. You could use the rules file supplied, or load your own rules. \n\nScanJS Rules\n------------------------\nRules are specified in JSON format - for an example see ```/common/template_rules.json```\n\nAt a minimum, each must have rule is made up of 2 attributes:\n- name: the name of the rule\n- source: javascript source which matches one of the patterns below (see Rule Syntax below)\n\nOptionally a rule may have the following attirbutes:\n- testhit: one more JavaScript statements (seperate by semi-colons) that the rule will match\n- testmiss: the rule should not match any of these statements\n- desc: description of the rule\n- threat: for catgorizing rules by threat\n\n\nRule Syntax\n------------------------\n\nFor the `source` attribute, the following basic statements are supported:\n- identifier `foo`: matches any identifier ,  \"foo\"\n- property `$_any.foo`: $_any is wildcard, matches anything.foo\n- objectproperty `foo.bar`: matches object and property, i.e. foo.bar\n\nYou can also matches function calls based on the same syntax:\n- call `foo()`: matches function calls with this name\n- propertycall `$_any.foo`: matches anything.foo() but not foo()\n- objectpropertycall: `foo.bar()`: matches foo.bar() only\n\nYou can also search for functions with matching literal arguments:\n\n- callargs `foo('test',ignored,42)`: matches a function called foo, with 'test' as the first argument, anything as the second argument, and the number 42 as the third argument (i.e. matches ONLY literal arguments).\n- propertycallargs `$_any.foo('test',ignored,42)`: same as above, but function has to be a property.\n- objectpropertycallargs `foo.bar('test',ignored,42)`: same as above, but matches both object and property\n\nYou can also search for assignment to a specifically named identifier:\n\n- assignment `foo=$_any`: matches when foo is assigned to something\n- propertyassignment `$_any.foo=$_any`: matches when anything.foo is assigned to something\n- objectpropertyassignment `foo.bar=$_any`: matches when foo.bar is assigned to something\n\nIf you specify `$_unsafe` on the right hand side (e.g. foo.innerHTML=$_unsafe), it will only match if the RHS contains at least one identifier.\n\nTips:\n- Javascript is very dynamic, and this is navie approach: write conservative rules and review for false positives\n- One simple statement per rule, not complex statements (yet)! \n- 'foo' does NOT match 'this.foo', if you are looking for something in global (e.g. 'alert()' ), you need to add two rules: 'alert.()' and '$_any.alert()'\n- Try the rule out in the experiment tab to test what it matches\n\n\nExamples:\nSee /common/template_rules.json and /common/rules.json\n\nRunning ScanJS\n======================\n\nRun ScanJS in the browser\n------------------------\n- Install [node.js](http://nodejs.org/)\n- ```nodejs server.js```\n- Navigate to http://127.0.0.1:4000/client/ or see our [example page](http://mozilla.github.io/scanjs/client/)\n\nRun ScanJS from the command line\n------------------------\n- Install [node.js](http://nodejs.org/)\n- ```scanner.js -t DIRECTORY_PATH```\n\nTesting instructions\n------------------------\nTests use the mocha testing framework.\n\n- `npm test` \n- or in the browser:```http://127.0.0.1:4000/tests/```\n\nTests are included in the rules declaration (see common/rules.json) by specifying the following two attributes, which are specified in the form of a series of javascript statements:\n\n- _testhit_: The rule should match each of these statements individualy. \n- _testmiss_: The rule should not match all of these statements.\n\n\n"
  },
  {
    "path": "client/css/angular-csp.css",
    "content": "/* Include this file in your html if you are using the CSP mode. */\n\n@charset \"UTF-8\";\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\n.ng-cloak, .x-ng-cloak,\n.ng-hide {\n  display: none !important;\n}\n\nng\\:form {\n  display: block;\n}\n\n.ng-animate-block-transitions {\n  transition:0s all!important;\n  -webkit-transition:0s all!important;\n}\n"
  },
  {
    "path": "client/css/app.css",
    "content": "@import url(\"bootstrap.css\");\n@import url(\"dashboard.css\");\n@import url(\"codemirror.css\");\n@import url(\"codemirror-mdn.css\");\n@import url(\"prettify.css\");\n@import url(\"font-awesome.css\");\n\nhtml, body {\n  height: 100%;\n  width: 100%;\n}\n\npre.prettyprint{\n    width: auto;\n    max-width: 600px;\n    overflow: auto;\n    font-size: x-small;\n}\n\n.navbar {\n  background: #4D4E53;\n}\n\n.nav > li > a:hover,\n.nav > li > a:focus {\n  background-color: #0095DD;\n}\n\na {\n  cursor:pointer;\n}\n\n.sidebar {\n  background-color: #EAEFF2;\n}\n\n.jumbotron {\n  background: #D4DDE4;\n}\n\n.table {\n  border: 1px solid #EAEFF2;\n}\n\n.table-striped > tbody > tr:nth-child(odd) > td,\n.table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #EAEFF2;\n}\n\n.sidebar-inputfiles{\n  font-size: x-small;\n}\n\n.CodeMirror {\n  border: 1px solid #EAEFF2;\n  height:500px;\n}\n\n.badge {\n  margin: 3px 3px 3px 3px;\n}\n\n@-webkit-keyframes rotating {\n    0% {\n      -webkit-transform: rotate(0deg); \n      color: #333;\n    }\n    25% {\n      -webkit-transform: rotate(90deg);\n      color: #70706F;\n    }\n    50% {\n      -webkit-transform: rotate(180deg);\n      color: #ADADAB;\n    }\n    75% {\n      -webkit-transform: rotate(270deg);\n      color: #EAEAE7;\n    }\n    100% {\n      -webkit-transform: rotate(360deg);\n      color: #333;\n    }\n}\n\n@keyframes rotating {\n    0% {\n      transform: rotate(0deg); \n      color: #333;\n    }\n    25% {\n      transform: rotate(90deg);\n      color: #70706F;\n    }\n    50% {\n      transform: rotate(180deg);\n      color: #ADADAB;\n    }\n    75% {\n      transform: rotate(270deg);\n      color: #EAEAE7;\n    }\n    100% {\n      transform: rotate(360deg);\n      color: #333;\n    }\n}\n\n.rotating {\n  margin: 5px 3px 0 3px;\n  -webkit-animation: rotating 1s linear infinite;\n  animation: rotating 1s linear infinite;\n}\n.fixed {\n    position: fixed;\n    min-width: 45%;\n}"
  },
  {
    "path": "client/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.1.1 (http://getbootstrap.com)\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n/*! normalize.css v3.0.0 | MIT License | git.io/normalize */\nhtml {\n  font-family: sans-serif;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\nbody {\n  margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block;\n  vertical-align: baseline;\n}\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n[hidden],\ntemplate {\n  display: none;\n}\na {\n  background: transparent;\n}\na:active,\na:hover {\n  outline: 0;\n}\nabbr[title] {\n  border-bottom: 1px dotted;\n}\nb,\nstrong {\n  font-weight: bold;\n}\ndfn {\n  font-style: italic;\n}\nh1 {\n  margin: .67em 0;\n  font-size: 2em;\n}\nmark {\n  color: #000;\n  background: #ff0;\n}\nsmall {\n  font-size: 80%;\n}\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\nsup {\n  top: -.5em;\n}\nsub {\n  bottom: -.25em;\n}\nimg {\n  border: 0;\n}\nsvg:not(:root) {\n  overflow: hidden;\n}\nfigure {\n  margin: 1em 40px;\n}\nhr {\n  height: 0;\n  -moz-box-sizing: content-box;\n       box-sizing: content-box;\n}\npre {\n  overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  margin: 0;\n  font: inherit;\n  color: inherit;\n}\nbutton {\n  overflow: visible;\n}\nbutton,\nselect {\n  text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\ninput {\n  line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\nfieldset {\n  padding: .35em .625em .75em;\n  margin: 0 2px;\n  border: 1px solid #c0c0c0;\n}\nlegend {\n  padding: 0;\n  border: 0;\n}\ntextarea {\n  overflow: auto;\n}\noptgroup {\n  font-weight: bold;\n}\ntable {\n  border-spacing: 0;\n  border-collapse: collapse;\n}\ntd,\nth {\n  padding: 0;\n}\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n  select {\n    background: #fff !important;\n  }\n  .navbar {\n    display: none;\n  }\n  .table td,\n  .table th {\n    background-color: #fff !important;\n  }\n  .btn > .caret,\n  .dropup > .btn > .caret {\n    border-top-color: #000 !important;\n  }\n  .label {\n    border: 1px solid #000;\n  }\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table-bordered th,\n  .table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n* {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\nhtml {\n  font-size: 62.5%;\n\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #333;\n  background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\na {\n  color: #428bca;\n  text-decoration: none;\n}\na:hover,\na:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\na:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\nfigure {\n  margin: 0;\n}\nimg {\n  vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n.img-rounded {\n  border-radius: 6px;\n}\n.img-thumbnail {\n  display: inline-block;\n  max-width: 100%;\n  height: auto;\n  padding: 4px;\n  line-height: 1.42857143;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 4px;\n  -webkit-transition: all .2s ease-in-out;\n          transition: all .2s ease-in-out;\n}\n.img-circle {\n  border-radius: 50%;\n}\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eee;\n}\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: inherit;\n  font-weight: 500;\n  line-height: 1.1;\n  color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n  font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n  font-size: 75%;\n}\nh1,\n.h1 {\n  font-size: 36px;\n}\nh2,\n.h2 {\n  font-size: 30px;\n}\nh3,\n.h3 {\n  font-size: 24px;\n}\nh4,\n.h4 {\n  font-size: 18px;\n}\nh5,\n.h5 {\n  font-size: 14px;\n}\nh6,\n.h6 {\n  font-size: 12px;\n}\np {\n  margin: 0 0 10px;\n}\n.lead {\n  margin-bottom: 20px;\n  font-size: 16px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\nsmall,\n.small {\n  font-size: 85%;\n}\ncite {\n  font-style: normal;\n}\n.text-left {\n  text-align: left;\n}\n.text-right {\n  text-align: right;\n}\n.text-center {\n  text-align: center;\n}\n.text-justify {\n  text-align: justify;\n}\n.text-muted {\n  color: #999;\n}\n.text-primary {\n  color: #428bca;\n}\na.text-primary:hover {\n  color: #3071a9;\n}\n.text-success {\n  color: #3c763d;\n}\na.text-success:hover {\n  color: #2b542c;\n}\n.text-info {\n  color: #31708f;\n}\na.text-info:hover {\n  color: #245269;\n}\n.text-warning {\n  color: #8a6d3b;\n}\na.text-warning:hover {\n  color: #66512c;\n}\n.text-danger {\n  color: #a94442;\n}\na.text-danger:hover {\n  color: #843534;\n}\n.bg-primary {\n  color: #fff;\n  background-color: #428bca;\n}\na.bg-primary:hover {\n  background-color: #3071a9;\n}\n.bg-success {\n  background-color: #dff0d8;\n}\na.bg-success:hover {\n  background-color: #c1e2b3;\n}\n.bg-info {\n  background-color: #d9edf7;\n}\na.bg-info:hover {\n  background-color: #afd9ee;\n}\n.bg-warning {\n  background-color: #fcf8e3;\n}\na.bg-warning:hover {\n  background-color: #f7ecb5;\n}\n.bg-danger {\n  background-color: #f2dede;\n}\na.bg-danger:hover {\n  background-color: #e4b9b9;\n}\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eee;\n}\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n.list-inline {\n  padding-left: 0;\n  margin-left: -5px;\n  list-style: none;\n}\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\ndl {\n  margin-top: 0;\n  margin-bottom: 20px;\n}\ndt,\ndd {\n  line-height: 1.42857143;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: 0;\n}\n@media (min-width: 768px) {\n  .dl-horizontal dt {\n    float: left;\n    width: 160px;\n    overflow: hidden;\n    clear: left;\n    text-align: right;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n  .dl-horizontal dd {\n    margin-left: 180px;\n  }\n}\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999;\n}\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  font-size: 17.5px;\n  border-left: 5px solid #eee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n  margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n  display: block;\n  font-size: 80%;\n  line-height: 1.42857143;\n  color: #999;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n  content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  text-align: right;\n  border-right: 5px solid #eee;\n  border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n  content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n  content: '\\00A0 \\2014';\n}\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\naddress {\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n  font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #c7254e;\n  white-space: nowrap;\n  background-color: #f9f2f4;\n  border-radius: 4px;\n}\nkbd {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #fff;\n  background-color: #333;\n  border-radius: 3px;\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n}\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.42857143;\n  color: #333;\n  word-break: break-all;\n  word-wrap: break-word;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n}\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border-radius: 0;\n}\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n.container {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n@media (min-width: 768px) {\n  .container {\n    width: 750px;\n  }\n}\n@media (min-width: 992px) {\n  .container {\n    width: 970px;\n  }\n}\n@media (min-width: 1200px) {\n  .container {\n    width: 1170px;\n  }\n}\n.container-fluid {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n.row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n  float: left;\n}\n.col-xs-12 {\n  width: 100%;\n}\n.col-xs-11 {\n  width: 91.66666667%;\n}\n.col-xs-10 {\n  width: 83.33333333%;\n}\n.col-xs-9 {\n  width: 75%;\n}\n.col-xs-8 {\n  width: 66.66666667%;\n}\n.col-xs-7 {\n  width: 58.33333333%;\n}\n.col-xs-6 {\n  width: 50%;\n}\n.col-xs-5 {\n  width: 41.66666667%;\n}\n.col-xs-4 {\n  width: 33.33333333%;\n}\n.col-xs-3 {\n  width: 25%;\n}\n.col-xs-2 {\n  width: 16.66666667%;\n}\n.col-xs-1 {\n  width: 8.33333333%;\n}\n.col-xs-pull-12 {\n  right: 100%;\n}\n.col-xs-pull-11 {\n  right: 91.66666667%;\n}\n.col-xs-pull-10 {\n  right: 83.33333333%;\n}\n.col-xs-pull-9 {\n  right: 75%;\n}\n.col-xs-pull-8 {\n  right: 66.66666667%;\n}\n.col-xs-pull-7 {\n  right: 58.33333333%;\n}\n.col-xs-pull-6 {\n  right: 50%;\n}\n.col-xs-pull-5 {\n  right: 41.66666667%;\n}\n.col-xs-pull-4 {\n  right: 33.33333333%;\n}\n.col-xs-pull-3 {\n  right: 25%;\n}\n.col-xs-pull-2 {\n  right: 16.66666667%;\n}\n.col-xs-pull-1 {\n  right: 8.33333333%;\n}\n.col-xs-pull-0 {\n  right: 0;\n}\n.col-xs-push-12 {\n  left: 100%;\n}\n.col-xs-push-11 {\n  left: 91.66666667%;\n}\n.col-xs-push-10 {\n  left: 83.33333333%;\n}\n.col-xs-push-9 {\n  left: 75%;\n}\n.col-xs-push-8 {\n  left: 66.66666667%;\n}\n.col-xs-push-7 {\n  left: 58.33333333%;\n}\n.col-xs-push-6 {\n  left: 50%;\n}\n.col-xs-push-5 {\n  left: 41.66666667%;\n}\n.col-xs-push-4 {\n  left: 33.33333333%;\n}\n.col-xs-push-3 {\n  left: 25%;\n}\n.col-xs-push-2 {\n  left: 16.66666667%;\n}\n.col-xs-push-1 {\n  left: 8.33333333%;\n}\n.col-xs-push-0 {\n  left: 0;\n}\n.col-xs-offset-12 {\n  margin-left: 100%;\n}\n.col-xs-offset-11 {\n  margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n  margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n  margin-left: 75%;\n}\n.col-xs-offset-8 {\n  margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n  margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n  margin-left: 50%;\n}\n.col-xs-offset-5 {\n  margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n  margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n  margin-left: 25%;\n}\n.col-xs-offset-2 {\n  margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n  margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n  margin-left: 0;\n}\n@media (min-width: 768px) {\n  .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n    float: left;\n  }\n  .col-sm-12 {\n    width: 100%;\n  }\n  .col-sm-11 {\n    width: 91.66666667%;\n  }\n  .col-sm-10 {\n    width: 83.33333333%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-8 {\n    width: 66.66666667%;\n  }\n  .col-sm-7 {\n    width: 58.33333333%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-5 {\n    width: 41.66666667%;\n  }\n  .col-sm-4 {\n    width: 33.33333333%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-2 {\n    width: 16.66666667%;\n  }\n  .col-sm-1 {\n    width: 8.33333333%;\n  }\n  .col-sm-pull-12 {\n    right: 100%;\n  }\n  .col-sm-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-sm-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-sm-pull-9 {\n    right: 75%;\n  }\n  .col-sm-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-sm-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-sm-pull-6 {\n    right: 50%;\n  }\n  .col-sm-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-sm-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-sm-pull-3 {\n    right: 25%;\n  }\n  .col-sm-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-sm-pull-1 {\n    right: 8.33333333%;\n  }\n  .col-sm-pull-0 {\n    right: 0;\n  }\n  .col-sm-push-12 {\n    left: 100%;\n  }\n  .col-sm-push-11 {\n    left: 91.66666667%;\n  }\n  .col-sm-push-10 {\n    left: 83.33333333%;\n  }\n  .col-sm-push-9 {\n    left: 75%;\n  }\n  .col-sm-push-8 {\n    left: 66.66666667%;\n  }\n  .col-sm-push-7 {\n    left: 58.33333333%;\n  }\n  .col-sm-push-6 {\n    left: 50%;\n  }\n  .col-sm-push-5 {\n    left: 41.66666667%;\n  }\n  .col-sm-push-4 {\n    left: 33.33333333%;\n  }\n  .col-sm-push-3 {\n    left: 25%;\n  }\n  .col-sm-push-2 {\n    left: 16.66666667%;\n  }\n  .col-sm-push-1 {\n    left: 8.33333333%;\n  }\n  .col-sm-push-0 {\n    left: 0;\n  }\n  .col-sm-offset-12 {\n    margin-left: 100%;\n  }\n  .col-sm-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .col-sm-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .col-sm-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-sm-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .col-sm-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-sm-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .col-sm-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-sm-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-sm-offset-0 {\n    margin-left: 0;\n  }\n}\n@media (min-width: 992px) {\n  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n    float: left;\n  }\n  .col-md-12 {\n    width: 100%;\n  }\n  .col-md-11 {\n    width: 91.66666667%;\n  }\n  .col-md-10 {\n    width: 83.33333333%;\n  }\n  .col-md-9 {\n    width: 75%;\n  }\n  .col-md-8 {\n    width: 66.66666667%;\n  }\n  .col-md-7 {\n    width: 58.33333333%;\n  }\n  .col-md-6 {\n    width: 50%;\n  }\n  .col-md-5 {\n    width: 41.66666667%;\n  }\n  .col-md-4 {\n    width: 33.33333333%;\n  }\n  .col-md-3 {\n    width: 25%;\n  }\n  .col-md-2 {\n    width: 16.66666667%;\n  }\n  .col-md-1 {\n    width: 8.33333333%;\n  }\n  .col-md-pull-12 {\n    right: 100%;\n  }\n  .col-md-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-md-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-md-pull-9 {\n    right: 75%;\n  }\n  .col-md-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-md-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-md-pull-6 {\n    right: 50%;\n  }\n  .col-md-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-md-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-md-pull-3 {\n    right: 25%;\n  }\n  .col-md-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-md-pull-1 {\n    right: 8.33333333%;\n  }\n  .col-md-pull-0 {\n    right: 0;\n  }\n  .col-md-push-12 {\n    left: 100%;\n  }\n  .col-md-push-11 {\n    left: 91.66666667%;\n  }\n  .col-md-push-10 {\n    left: 83.33333333%;\n  }\n  .col-md-push-9 {\n    left: 75%;\n  }\n  .col-md-push-8 {\n    left: 66.66666667%;\n  }\n  .col-md-push-7 {\n    left: 58.33333333%;\n  }\n  .col-md-push-6 {\n    left: 50%;\n  }\n  .col-md-push-5 {\n    left: 41.66666667%;\n  }\n  .col-md-push-4 {\n    left: 33.33333333%;\n  }\n  .col-md-push-3 {\n    left: 25%;\n  }\n  .col-md-push-2 {\n    left: 16.66666667%;\n  }\n  .col-md-push-1 {\n    left: 8.33333333%;\n  }\n  .col-md-push-0 {\n    left: 0;\n  }\n  .col-md-offset-12 {\n    margin-left: 100%;\n  }\n  .col-md-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .col-md-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-md-offset-9 {\n    margin-left: 75%;\n  }\n  .col-md-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-md-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-md-offset-6 {\n    margin-left: 50%;\n  }\n  .col-md-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-md-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-md-offset-3 {\n    margin-left: 25%;\n  }\n  .col-md-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-md-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-md-offset-0 {\n    margin-left: 0;\n  }\n}\n@media (min-width: 1200px) {\n  .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n    float: left;\n  }\n  .col-lg-12 {\n    width: 100%;\n  }\n  .col-lg-11 {\n    width: 91.66666667%;\n  }\n  .col-lg-10 {\n    width: 83.33333333%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-8 {\n    width: 66.66666667%;\n  }\n  .col-lg-7 {\n    width: 58.33333333%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-5 {\n    width: 41.66666667%;\n  }\n  .col-lg-4 {\n    width: 33.33333333%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-2 {\n    width: 16.66666667%;\n  }\n  .col-lg-1 {\n    width: 8.33333333%;\n  }\n  .col-lg-pull-12 {\n    right: 100%;\n  }\n  .col-lg-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-lg-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-lg-pull-9 {\n    right: 75%;\n  }\n  .col-lg-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-lg-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-lg-pull-6 {\n    right: 50%;\n  }\n  .col-lg-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-lg-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-lg-pull-3 {\n    right: 25%;\n  }\n  .col-lg-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-lg-pull-1 {\n    right: 8.33333333%;\n  }\n  .col-lg-pull-0 {\n    right: 0;\n  }\n  .col-lg-push-12 {\n    left: 100%;\n  }\n  .col-lg-push-11 {\n    left: 91.66666667%;\n  }\n  .col-lg-push-10 {\n    left: 83.33333333%;\n  }\n  .col-lg-push-9 {\n    left: 75%;\n  }\n  .col-lg-push-8 {\n    left: 66.66666667%;\n  }\n  .col-lg-push-7 {\n    left: 58.33333333%;\n  }\n  .col-lg-push-6 {\n    left: 50%;\n  }\n  .col-lg-push-5 {\n    left: 41.66666667%;\n  }\n  .col-lg-push-4 {\n    left: 33.33333333%;\n  }\n  .col-lg-push-3 {\n    left: 25%;\n  }\n  .col-lg-push-2 {\n    left: 16.66666667%;\n  }\n  .col-lg-push-1 {\n    left: 8.33333333%;\n  }\n  .col-lg-push-0 {\n    left: 0;\n  }\n  .col-lg-offset-12 {\n    margin-left: 100%;\n  }\n  .col-lg-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .col-lg-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .col-lg-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-lg-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .col-lg-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-lg-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .col-lg-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-lg-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-lg-offset-0 {\n    margin-left: 0;\n  }\n}\ntable {\n  max-width: 100%;\n  background-color: transparent;\n}\nth {\n  text-align: left;\n}\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n  padding: 8px;\n  line-height: 1.42857143;\n  vertical-align: top;\n  border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n.table > tbody + tbody {\n  border-top: 2px solid #ddd;\n}\n.table .table {\n  background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n  padding: 5px;\n}\n.table-bordered {\n  border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n  border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n  border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-child(odd) > td,\n.table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n  background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n  position: static;\n  display: table-column;\n  float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n  position: static;\n  display: table-cell;\n  float: none;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n  background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr.active:hover > th {\n  background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n  background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr.success:hover > th {\n  background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n  background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr.info:hover > th {\n  background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n  background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr.warning:hover > th {\n  background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n  background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr.danger:hover > th {\n  background-color: #ebcccc;\n}\n@media (max-width: 767px) {\n  .table-responsive {\n    width: 100%;\n    margin-bottom: 15px;\n    overflow-x: scroll;\n    overflow-y: hidden;\n    -webkit-overflow-scrolling: touch;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    border: 1px solid #ddd;\n  }\n  .table-responsive > .table {\n    margin-bottom: 0;\n  }\n  .table-responsive > .table > thead > tr > th,\n  .table-responsive > .table > tbody > tr > th,\n  .table-responsive > .table > tfoot > tr > th,\n  .table-responsive > .table > thead > tr > td,\n  .table-responsive > .table > tbody > tr > td,\n  .table-responsive > .table > tfoot > tr > td {\n    white-space: nowrap;\n  }\n  .table-responsive > .table-bordered {\n    border: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr > th:first-child,\n  .table-responsive > .table-bordered > tbody > tr > th:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n  .table-responsive > .table-bordered > thead > tr > td:first-child,\n  .table-responsive > .table-bordered > tbody > tr > td:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n    border-left: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr > th:last-child,\n  .table-responsive > .table-bordered > tbody > tr > th:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n  .table-responsive > .table-bordered > thead > tr > td:last-child,\n  .table-responsive > .table-bordered > tbody > tr > td:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n    border-right: 0;\n  }\n  .table-responsive > .table-bordered > tbody > tr:last-child > th,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n  .table-responsive > .table-bordered > tbody > tr:last-child > td,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n    border-bottom: 0;\n  }\n}\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: inherit;\n  color: #333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n  line-height: normal;\n}\ninput[type=\"file\"] {\n  display: block;\n}\ninput[type=\"range\"] {\n  display: block;\n  width: 100%;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\noutput {\n  display: block;\n  padding-top: 7px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555;\n}\n.form-control {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555;\n  background-color: #fff;\n  background-image: none;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n  -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n          transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n  border-color: #66afe9;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n}\n.form-control::-moz-placeholder {\n  color: #999;\n  opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n  color: #999;\n}\n.form-control::-webkit-input-placeholder {\n  color: #999;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eee;\n  opacity: 1;\n}\ntextarea.form-control {\n  height: auto;\n}\ninput[type=\"search\"] {\n  -webkit-appearance: none;\n}\ninput[type=\"date\"] {\n  line-height: 34px;\n}\n.form-group {\n  margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n  display: block;\n  min-height: 20px;\n  padding-left: 20px;\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n  display: inline;\n  font-weight: normal;\n  cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  font-weight: normal;\n  vertical-align: middle;\n  cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\n.radio[disabled],\n.radio-inline[disabled],\n.checkbox[disabled],\n.checkbox-inline[disabled],\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"],\nfieldset[disabled] .radio,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox,\nfieldset[disabled] .checkbox-inline {\n  cursor: not-allowed;\n}\n.input-sm {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\nselect.input-sm {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n  height: auto;\n}\n.input-lg {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\nselect.input-lg {\n  height: 46px;\n  line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n  height: auto;\n}\n.has-feedback {\n  position: relative;\n}\n.has-feedback .form-control {\n  padding-right: 42.5px;\n}\n.has-feedback .form-control-feedback {\n  position: absolute;\n  top: 25px;\n  right: 0;\n  display: block;\n  width: 34px;\n  height: 34px;\n  line-height: 34px;\n  text-align: center;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline {\n  color: #3c763d;\n}\n.has-success .form-control {\n  border-color: #3c763d;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-success .form-control:focus {\n  border-color: #2b542c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n  color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline {\n  color: #8a6d3b;\n}\n.has-warning .form-control {\n  border-color: #8a6d3b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-warning .form-control:focus {\n  border-color: #66512c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n  color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline {\n  color: #a94442;\n}\n.has-error .form-control {\n  border-color: #a94442;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-error .form-control:focus {\n  border-color: #843534;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #a94442;\n}\n.has-error .form-control-feedback {\n  color: #a94442;\n}\n.form-control-static {\n  margin-bottom: 0;\n}\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n@media (min-width: 768px) {\n  .form-inline .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .form-control {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .form-inline .input-group > .form-control {\n    width: 100%;\n  }\n  .form-inline .control-label {\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .radio,\n  .form-inline .checkbox {\n    display: inline-block;\n    padding-left: 0;\n    margin-top: 0;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n  .form-inline .has-feedback .form-control-feedback {\n    top: 0;\n  }\n}\n.form-horizontal .control-label,\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n  padding-top: 7px;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n  min-height: 27px;\n}\n.form-horizontal .form-group {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n.form-horizontal .form-control-static {\n  padding-top: 7px;\n}\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n  top: 0;\n  right: 15px;\n}\n.btn {\n  display: inline-block;\n  padding: 6px 12px;\n  margin-bottom: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1.42857143;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  cursor: pointer;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus {\n  color: #333;\n  text-decoration: none;\n}\n.btn:active,\n.btn.active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  pointer-events: none;\n  cursor: not-allowed;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n          box-shadow: none;\n  opacity: .65;\n}\n.btn-default {\n  color: #333;\n  background-color: #fff;\n  border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus,\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  color: #333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  background-image: none;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n  background-color: #fff;\n  border-color: #ccc;\n}\n.btn-default .badge {\n  color: #fff;\n  background-color: #333;\n}\n.btn-primary {\n  color: #fff;\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  color: #fff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  background-image: none;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.btn-primary .badge {\n  color: #428bca;\n  background-color: #fff;\n}\n.btn-success {\n  color: #fff;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  color: #fff;\n  background-color: #47a447;\n  border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  background-image: none;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.btn-success .badge {\n  color: #5cb85c;\n  background-color: #fff;\n}\n.btn-info {\n  color: #fff;\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.btn-info:hover,\n.btn-info:focus,\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  color: #fff;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  background-image: none;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.btn-info .badge {\n  color: #5bc0de;\n  background-color: #fff;\n}\n.btn-warning {\n  color: #fff;\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  color: #fff;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  background-image: none;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.btn-warning .badge {\n  color: #f0ad4e;\n  background-color: #fff;\n}\n.btn-danger {\n  color: #fff;\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  color: #fff;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  background-image: none;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.btn-danger .badge {\n  color: #d9534f;\n  background-color: #fff;\n}\n.btn-link {\n  font-weight: normal;\n  color: #428bca;\n  cursor: pointer;\n  border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #999;\n  text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n}\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity .15s linear;\n          transition: opacity .15s linear;\n}\n.fade.in {\n  opacity: 1;\n}\n.collapse {\n  display: none;\n}\n.collapse.in {\n  display: block;\n}\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height .35s ease;\n          transition: height .35s ease;\n}\n@font-face {\n  font-family: 'Glyphicons Halflings';\n\n  src: url('../fonts/glyphicons-halflings-regular.eot');\n  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n  content: \"\\2a\";\n}\n.glyphicon-plus:before {\n  content: \"\\2b\";\n}\n.glyphicon-euro:before {\n  content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n  content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n  content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n  content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n  content: \"\\270f\";\n}\n.glyphicon-glass:before {\n  content: \"\\e001\";\n}\n.glyphicon-music:before {\n  content: \"\\e002\";\n}\n.glyphicon-search:before {\n  content: \"\\e003\";\n}\n.glyphicon-heart:before {\n  content: \"\\e005\";\n}\n.glyphicon-star:before {\n  content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n  content: \"\\e007\";\n}\n.glyphicon-user:before {\n  content: \"\\e008\";\n}\n.glyphicon-film:before {\n  content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n  content: \"\\e010\";\n}\n.glyphicon-th:before {\n  content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n  content: \"\\e012\";\n}\n.glyphicon-ok:before {\n  content: \"\\e013\";\n}\n.glyphicon-remove:before {\n  content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n  content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n  content: \"\\e016\";\n}\n.glyphicon-off:before {\n  content: \"\\e017\";\n}\n.glyphicon-signal:before {\n  content: \"\\e018\";\n}\n.glyphicon-cog:before {\n  content: \"\\e019\";\n}\n.glyphicon-trash:before {\n  content: \"\\e020\";\n}\n.glyphicon-home:before {\n  content: \"\\e021\";\n}\n.glyphicon-file:before {\n  content: \"\\e022\";\n}\n.glyphicon-time:before {\n  content: \"\\e023\";\n}\n.glyphicon-road:before {\n  content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n  content: \"\\e025\";\n}\n.glyphicon-download:before {\n  content: \"\\e026\";\n}\n.glyphicon-upload:before {\n  content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n  content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n  content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n  content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n  content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n  content: \"\\e032\";\n}\n.glyphicon-lock:before {\n  content: \"\\e033\";\n}\n.glyphicon-flag:before {\n  content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n  content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n  content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n  content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n  content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n  content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n  content: \"\\e040\";\n}\n.glyphicon-tag:before {\n  content: \"\\e041\";\n}\n.glyphicon-tags:before {\n  content: \"\\e042\";\n}\n.glyphicon-book:before {\n  content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n  content: \"\\e044\";\n}\n.glyphicon-print:before {\n  content: \"\\e045\";\n}\n.glyphicon-camera:before {\n  content: \"\\e046\";\n}\n.glyphicon-font:before {\n  content: \"\\e047\";\n}\n.glyphicon-bold:before {\n  content: \"\\e048\";\n}\n.glyphicon-italic:before {\n  content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n  content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n  content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n  content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n  content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n  content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n  content: \"\\e055\";\n}\n.glyphicon-list:before {\n  content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n  content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n  content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n  content: \"\\e059\";\n}\n.glyphicon-picture:before {\n  content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n  content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n  content: \"\\e063\";\n}\n.glyphicon-tint:before {\n  content: \"\\e064\";\n}\n.glyphicon-edit:before {\n  content: \"\\e065\";\n}\n.glyphicon-share:before {\n  content: \"\\e066\";\n}\n.glyphicon-check:before {\n  content: \"\\e067\";\n}\n.glyphicon-move:before {\n  content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n  content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n  content: \"\\e070\";\n}\n.glyphicon-backward:before {\n  content: \"\\e071\";\n}\n.glyphicon-play:before {\n  content: \"\\e072\";\n}\n.glyphicon-pause:before {\n  content: \"\\e073\";\n}\n.glyphicon-stop:before {\n  content: \"\\e074\";\n}\n.glyphicon-forward:before {\n  content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n  content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n  content: \"\\e077\";\n}\n.glyphicon-eject:before {\n  content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n  content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n  content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n  content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n  content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n  content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n  content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n  content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n  content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n  content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n  content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n  content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n  content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n  content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n  content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n  content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n  content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n  content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n  content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n  content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n  content: \"\\e101\";\n}\n.glyphicon-gift:before {\n  content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n  content: \"\\e103\";\n}\n.glyphicon-fire:before {\n  content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n  content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n  content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n  content: \"\\e107\";\n}\n.glyphicon-plane:before {\n  content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n  content: \"\\e109\";\n}\n.glyphicon-random:before {\n  content: \"\\e110\";\n}\n.glyphicon-comment:before {\n  content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n  content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n  content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n  content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n  content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n  content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n  content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n  content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n  content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n  content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n  content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n  content: \"\\e122\";\n}\n.glyphicon-bell:before {\n  content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n  content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n  content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n  content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n  content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n  content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n  content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n  content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n  content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n  content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n  content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n  content: \"\\e134\";\n}\n.glyphicon-globe:before {\n  content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n  content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n  content: \"\\e137\";\n}\n.glyphicon-filter:before {\n  content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n  content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n  content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n  content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n  content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n  content: \"\\e143\";\n}\n.glyphicon-link:before {\n  content: \"\\e144\";\n}\n.glyphicon-phone:before {\n  content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n  content: \"\\e146\";\n}\n.glyphicon-usd:before {\n  content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n  content: \"\\e149\";\n}\n.glyphicon-sort:before {\n  content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n  content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n  content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n  content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n  content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n  content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n  content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n  content: \"\\e157\";\n}\n.glyphicon-expand:before {\n  content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n  content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n  content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n  content: \"\\e161\";\n}\n.glyphicon-flash:before {\n  content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n  content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n  content: \"\\e164\";\n}\n.glyphicon-record:before {\n  content: \"\\e165\";\n}\n.glyphicon-save:before {\n  content: \"\\e166\";\n}\n.glyphicon-open:before {\n  content: \"\\e167\";\n}\n.glyphicon-saved:before {\n  content: \"\\e168\";\n}\n.glyphicon-import:before {\n  content: \"\\e169\";\n}\n.glyphicon-export:before {\n  content: \"\\e170\";\n}\n.glyphicon-send:before {\n  content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n  content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n  content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n  content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n  content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n  content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n  content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n  content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n  content: \"\\e179\";\n}\n.glyphicon-header:before {\n  content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n  content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n  content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n  content: \"\\e183\";\n}\n.glyphicon-tower:before {\n  content: \"\\e184\";\n}\n.glyphicon-stats:before {\n  content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n  content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n  content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n  content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n  content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n  content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n  content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n  content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n  content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n  content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n  content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n  content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n  content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n  content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n  content: \"\\e200\";\n}\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top: 4px solid;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n}\n.dropdown {\n  position: relative;\n}\n.dropdown-toggle:focus {\n  outline: 0;\n}\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  font-size: 14px;\n  list-style: none;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, .15);\n  border-radius: 4px;\n  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n          box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n}\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 1.42857143;\n  color: #333;\n  white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  color: #262626;\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #fff;\n  text-decoration: none;\n  background-color: #428bca;\n  outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #999;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n  display: block;\n}\n.open > a {\n  outline: 0;\n}\n.dropdown-menu-right {\n  right: 0;\n  left: auto;\n}\n.dropdown-menu-left {\n  right: auto;\n  left: 0;\n}\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.42857143;\n  color: #999;\n}\n.dropdown-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 990;\n}\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  content: \"\";\n  border-top: 0;\n  border-bottom: 4px solid;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n@media (min-width: 768px) {\n  .navbar-right .dropdown-menu {\n    right: 0;\n    left: auto;\n  }\n  .navbar-right .dropdown-menu-left {\n    right: auto;\n    left: 0;\n  }\n}\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n  z-index: 2;\n}\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus {\n  outline: none;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n  margin-left: -1px;\n}\n.btn-toolbar {\n  margin-left: -5px;\n}\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n  float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n  margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n.btn-group > .btn:first-child {\n  margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n  float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group > .btn-group:first-child > .btn:last-child,\n.btn-group > .btn-group:first-child > .dropdown-toggle {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n  padding-right: 8px;\n  padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-right: 12px;\n  padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n.btn .caret {\n  margin-left: 0;\n}\n.btn-lg .caret {\n  border-width: 5px 5px 0;\n  border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n  border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n  float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n  border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n  width: 100%;\n}\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n.input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n  float: none;\n  padding-right: 0;\n  padding-left: 0;\n}\n.input-group .form-control {\n  position: relative;\n  z-index: 2;\n  float: left;\n  width: 100%;\n  margin-bottom: 0;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n  height: 46px;\n  line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n  height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n  height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n.input-group-addon {\n  padding: 6px 12px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1;\n  color: #555;\n  text-align: center;\n  background-color: #eee;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n}\n.input-group-addon.input-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n.input-group-addon.input-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n  border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n  border-left: 0;\n}\n.input-group-btn {\n  position: relative;\n  font-size: 0;\n  white-space: nowrap;\n}\n.input-group-btn > .btn {\n  position: relative;\n}\n.input-group-btn > .btn + .btn {\n  margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n  z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n  margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n  margin-left: -1px;\n}\n.nav {\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n.nav > li {\n  position: relative;\n  display: block;\n}\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eee;\n}\n.nav > li.disabled > a {\n  color: #999;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #999;\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n  background-color: #eee;\n  border-color: #428bca;\n}\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.nav > li > a > img {\n  max-width: none;\n}\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.42857143;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n  border-color: #eee #eee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555;\n  cursor: default;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n  float: none;\n}\n.nav-tabs.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-tabs.nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n  border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li > a {\n    border-bottom: 1px solid #ddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs.nav-justified > .active > a,\n  .nav-tabs.nav-justified > .active > a:hover,\n  .nav-tabs.nav-justified > .active > a:focus {\n    border-bottom-color: #fff;\n  }\n}\n.nav-pills > li {\n  float: left;\n}\n.nav-pills > li > a {\n  border-radius: 4px;\n}\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #fff;\n  background-color: #428bca;\n}\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n.nav-justified {\n  width: 100%;\n}\n.nav-justified > li {\n  float: none;\n}\n.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n@media (min-width: 768px) {\n  .nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n.nav-tabs-justified {\n  border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n  border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n  .nav-tabs-justified > li > a {\n    border-bottom: 1px solid #ddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs-justified > .active > a,\n  .nav-tabs-justified > .active > a:hover,\n  .nav-tabs-justified > .active > a:focus {\n    border-bottom-color: #fff;\n  }\n}\n.tab-content > .tab-pane {\n  display: none;\n}\n.tab-content > .active {\n  display: block;\n}\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.navbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n  .navbar {\n    border-radius: 4px;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-header {\n    float: left;\n  }\n}\n.navbar-collapse {\n  max-height: 340px;\n  padding-right: 15px;\n  padding-left: 15px;\n  overflow-x: visible;\n  -webkit-overflow-scrolling: touch;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n}\n.navbar-collapse.in {\n  overflow-y: auto;\n}\n@media (min-width: 768px) {\n  .navbar-collapse {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n  }\n  .navbar-collapse.collapse {\n    display: block !important;\n    height: auto !important;\n    padding-bottom: 0;\n    overflow: visible !important;\n  }\n  .navbar-collapse.in {\n    overflow-y: visible;\n  }\n  .navbar-fixed-top .navbar-collapse,\n  .navbar-static-top .navbar-collapse,\n  .navbar-fixed-bottom .navbar-collapse {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n@media (min-width: 768px) {\n  .container > .navbar-header,\n  .container-fluid > .navbar-header,\n  .container > .navbar-collapse,\n  .container-fluid > .navbar-collapse {\n    margin-right: 0;\n    margin-left: 0;\n  }\n}\n.navbar-static-top {\n  z-index: 1000;\n  border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n  .navbar-static-top {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n}\n@media (min-width: 768px) {\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n.navbar-brand {\n  float: left;\n  height: 50px;\n  padding: 15px 15px;\n  font-size: 18px;\n  line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n  text-decoration: none;\n}\n@media (min-width: 768px) {\n  .navbar > .container .navbar-brand,\n  .navbar > .container-fluid .navbar-brand {\n    margin-left: -15px;\n  }\n}\n.navbar-toggle {\n  position: relative;\n  float: right;\n  padding: 9px 10px;\n  margin-top: 8px;\n  margin-right: 15px;\n  margin-bottom: 8px;\n  background-color: transparent;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.navbar-toggle:focus {\n  outline: none;\n}\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n@media (min-width: 768px) {\n  .navbar-toggle {\n    display: none;\n  }\n}\n.navbar-nav {\n  margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  line-height: 20px;\n}\n@media (max-width: 767px) {\n  .navbar-nav .open .dropdown-menu {\n    position: static;\n    float: none;\n    width: auto;\n    margin-top: 0;\n    background-color: transparent;\n    border: 0;\n    box-shadow: none;\n  }\n  .navbar-nav .open .dropdown-menu > li > a,\n  .navbar-nav .open .dropdown-menu .dropdown-header {\n    padding: 5px 15px 5px 25px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a {\n    line-height: 20px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-nav .open .dropdown-menu > li > a:focus {\n    background-image: none;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-nav {\n    float: left;\n    margin: 0;\n  }\n  .navbar-nav > li {\n    float: left;\n  }\n  .navbar-nav > li > a {\n    padding-top: 15px;\n    padding-bottom: 15px;\n  }\n  .navbar-nav.navbar-right:last-child {\n    margin-right: -15px;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-left {\n    float: left !important;\n  }\n  .navbar-right {\n    float: right !important;\n  }\n}\n.navbar-form {\n  padding: 10px 15px;\n  margin-top: 8px;\n  margin-right: -15px;\n  margin-bottom: 8px;\n  margin-left: -15px;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n}\n@media (min-width: 768px) {\n  .navbar-form .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .form-control {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .navbar-form .input-group > .form-control {\n    width: 100%;\n  }\n  .navbar-form .control-label {\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .radio,\n  .navbar-form .checkbox {\n    display: inline-block;\n    padding-left: 0;\n    margin-top: 0;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .radio input[type=\"radio\"],\n  .navbar-form .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n  .navbar-form .has-feedback .form-control-feedback {\n    top: 0;\n  }\n}\n@media (max-width: 767px) {\n  .navbar-form .form-group {\n    margin-bottom: 5px;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-form {\n    width: auto;\n    padding-top: 0;\n    padding-bottom: 0;\n    margin-right: 0;\n    margin-left: 0;\n    border: 0;\n    -webkit-box-shadow: none;\n            box-shadow: none;\n  }\n  .navbar-form.navbar-right:last-child {\n    margin-right: -15px;\n  }\n}\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n  margin-top: 14px;\n  margin-bottom: 14px;\n}\n.navbar-text {\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n  .navbar-text {\n    float: left;\n    margin-right: 15px;\n    margin-left: 15px;\n  }\n  .navbar-text.navbar-right:last-child {\n    margin-right: 0;\n  }\n}\n.navbar-default {\n  background-color: #f8f8f8;\n  border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n  color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n  color: #5e5e5e;\n  background-color: transparent;\n}\n.navbar-default .navbar-text {\n  color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n  color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n  color: #333;\n  background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n  color: #555;\n  background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n  color: #ccc;\n  background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n  border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n  background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n  background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n  border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n  color: #555;\n  background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n    color: #777;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #333;\n    background-color: transparent;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #555;\n    background-color: #e7e7e7;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #ccc;\n    background-color: transparent;\n  }\n}\n.navbar-default .navbar-link {\n  color: #777;\n}\n.navbar-default .navbar-link:hover {\n  color: #333;\n}\n.navbar-inverse {\n  background-color: #222;\n  border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n  color: #999;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n  color: #999;\n}\n.navbar-inverse .navbar-nav > li > a {\n  color: #999;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n  color: #fff;\n  background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n  color: #444;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n  border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n  border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n  color: #fff;\n  background-color: #080808;\n}\n@media (max-width: 767px) {\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n    border-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #999;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #fff;\n    background-color: transparent;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #fff;\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #444;\n    background-color: transparent;\n  }\n}\n.navbar-inverse .navbar-link {\n  color: #999;\n}\n.navbar-inverse .navbar-link:hover {\n  color: #fff;\n}\n.breadcrumb {\n  padding: 8px 15px;\n  margin-bottom: 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n}\n.breadcrumb > li {\n  display: inline-block;\n}\n.breadcrumb > li + li:before {\n  padding: 0 5px;\n  color: #ccc;\n  content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n  color: #999;\n}\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n.pagination > li {\n  display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n  position: relative;\n  float: left;\n  padding: 6px 12px;\n  margin-left: -1px;\n  line-height: 1.42857143;\n  color: #428bca;\n  text-decoration: none;\n  background-color: #fff;\n  border: 1px solid #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  margin-left: 0;\n  border-top-left-radius: 4px;\n  border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n  color: #2a6496;\n  background-color: #eee;\n  border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n  z-index: 2;\n  color: #fff;\n  cursor: default;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n  color: #999;\n  cursor: not-allowed;\n  background-color: #fff;\n  border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n  padding: 10px 16px;\n  font-size: 18px;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n  border-top-left-radius: 6px;\n  border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n  border-top-right-radius: 6px;\n  border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n  border-top-left-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n}\n.pager li {\n  display: inline;\n}\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #eee;\n}\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #999;\n  cursor: not-allowed;\n  background-color: #fff;\n}\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: #fff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n}\n.label[href]:hover,\n.label[href]:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.label:empty {\n  display: none;\n}\n.btn .label {\n  position: relative;\n  top: -1px;\n}\n.label-default {\n  background-color: #999;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n  background-color: #808080;\n}\n.label-primary {\n  background-color: #428bca;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n  background-color: #3071a9;\n}\n.label-success {\n  background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n.label-info {\n  background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\n.label-warning {\n  background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n.label-danger {\n  background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\n}\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: 12px;\n  font-weight: bold;\n  line-height: 1;\n  color: #fff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999;\n  border-radius: 10px;\n}\n.badge:empty {\n  display: none;\n}\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n.btn-xs .badge {\n  top: 0;\n  padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #fff;\n}\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  color: inherit;\n  background-color: #eee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n  color: inherit;\n}\n.jumbotron p {\n  margin-bottom: 15px;\n  font-size: 21px;\n  font-weight: 200;\n}\n.container .jumbotron {\n  border-radius: 6px;\n}\n.jumbotron .container {\n  max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n  .jumbotron {\n    padding-top: 48px;\n    padding-bottom: 48px;\n  }\n  .container .jumbotron {\n    padding-right: 60px;\n    padding-left: 60px;\n  }\n  .jumbotron h1,\n  .jumbotron .h1 {\n    font-size: 63px;\n  }\n}\n.thumbnail {\n  display: block;\n  padding: 4px;\n  margin-bottom: 20px;\n  line-height: 1.42857143;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 4px;\n  -webkit-transition: all .2s ease-in-out;\n          transition: all .2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n  margin-right: auto;\n  margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n  border-color: #428bca;\n}\n.thumbnail .caption {\n  padding: 9px;\n  color: #333;\n}\n.alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n.alert .alert-link {\n  font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n  margin-bottom: 0;\n}\n.alert > p + p {\n  margin-top: 5px;\n}\n.alert-dismissable {\n  padding-right: 35px;\n}\n.alert-dismissable .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n.alert-success {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n  color: #2b542c;\n}\n.alert-info {\n  color: #31708f;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n  color: #245269;\n}\n.alert-warning {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n.alert-warning hr {\n  border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n  color: #66512c;\n}\n.alert-danger {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n.alert-danger hr {\n  border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n  color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n}\n.progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  line-height: 20px;\n  color: #fff;\n  text-align: center;\n  background-color: #428bca;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n  -webkit-transition: width .6s ease;\n          transition: width .6s ease;\n}\n.progress-striped .progress-bar {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-size: 40px 40px;\n}\n.progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n  background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n.media,\n.media .media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n.media-object {\n  display: block;\n}\n.media-heading {\n  margin: 0 0 5px;\n}\n.media > .pull-left {\n  margin-right: 10px;\n}\n.media > .pull-right {\n  margin-left: 10px;\n}\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n.list-group {\n  padding-left: 0;\n  margin-bottom: 20px;\n}\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n  border-top-left-radius: 4px;\n  border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n  margin-bottom: 0;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 4px;\n}\n.list-group-item > .badge {\n  float: right;\n}\n.list-group-item > .badge + .badge {\n  margin-right: 5px;\n}\na.list-group-item {\n  color: #555;\n}\na.list-group-item .list-group-item-heading {\n  color: #333;\n}\na.list-group-item:hover,\na.list-group-item:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\na.list-group-item.active,\na.list-group-item.active:hover,\na.list-group-item.active:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\na.list-group-item.active .list-group-item-heading,\na.list-group-item.active:hover .list-group-item-heading,\na.list-group-item.active:focus .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item.active .list-group-item-text,\na.list-group-item.active:hover .list-group-item-text,\na.list-group-item.active:focus .list-group-item-text {\n  color: #e1edf7;\n}\n.list-group-item-success {\n  color: #3c763d;\n  background-color: #dff0d8;\n}\na.list-group-item-success {\n  color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-success:hover,\na.list-group-item-success:focus {\n  color: #3c763d;\n  background-color: #d0e9c6;\n}\na.list-group-item-success.active,\na.list-group-item-success.active:hover,\na.list-group-item-success.active:focus {\n  color: #fff;\n  background-color: #3c763d;\n  border-color: #3c763d;\n}\n.list-group-item-info {\n  color: #31708f;\n  background-color: #d9edf7;\n}\na.list-group-item-info {\n  color: #31708f;\n}\na.list-group-item-info .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-info:hover,\na.list-group-item-info:focus {\n  color: #31708f;\n  background-color: #c4e3f3;\n}\na.list-group-item-info.active,\na.list-group-item-info.active:hover,\na.list-group-item-info.active:focus {\n  color: #fff;\n  background-color: #31708f;\n  border-color: #31708f;\n}\n.list-group-item-warning {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n}\na.list-group-item-warning {\n  color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-warning:hover,\na.list-group-item-warning:focus {\n  color: #8a6d3b;\n  background-color: #faf2cc;\n}\na.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus {\n  color: #fff;\n  background-color: #8a6d3b;\n  border-color: #8a6d3b;\n}\n.list-group-item-danger {\n  color: #a94442;\n  background-color: #f2dede;\n}\na.list-group-item-danger {\n  color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-danger:hover,\na.list-group-item-danger:focus {\n  color: #a94442;\n  background-color: #ebcccc;\n}\na.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus {\n  color: #fff;\n  background-color: #a94442;\n  border-color: #a94442;\n}\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n.panel {\n  margin-bottom: 20px;\n  background-color: #fff;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n          box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n}\n.panel-body {\n  padding: 15px;\n}\n.panel-heading {\n  padding: 10px 15px;\n  border-bottom: 1px solid transparent;\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n  color: inherit;\n}\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 16px;\n  color: inherit;\n}\n.panel-title > a {\n  color: inherit;\n}\n.panel-footer {\n  padding: 10px 15px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel > .list-group {\n  margin-bottom: 0;\n}\n.panel > .list-group .list-group-item {\n  border-width: 1px 0;\n  border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child {\n  border-top: 0;\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child {\n  border-bottom: 0;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n  border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table {\n  margin-bottom: 0;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n  border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n  border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n  border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n  border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive {\n  border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n  border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n  border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n  border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n  border-bottom: 0;\n}\n.panel > .table-responsive {\n  margin-bottom: 0;\n  border: 0;\n}\n.panel-group {\n  margin-bottom: 20px;\n}\n.panel-group .panel {\n  margin-bottom: 0;\n  overflow: hidden;\n  border-radius: 4px;\n}\n.panel-group .panel + .panel {\n  margin-top: 5px;\n}\n.panel-group .panel-heading {\n  border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse .panel-body {\n  border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n  border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n  border-bottom: 1px solid #ddd;\n}\n.panel-default {\n  border-color: #ddd;\n}\n.panel-default > .panel-heading {\n  color: #333;\n  background-color: #f5f5f5;\n  border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #ddd;\n}\n.panel-default > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #ddd;\n}\n.panel-primary {\n  border-color: #428bca;\n}\n.panel-primary > .panel-heading {\n  color: #fff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n.panel-primary > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #428bca;\n}\n.panel-primary > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #428bca;\n}\n.panel-success {\n  border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #d6e9c6;\n}\n.panel-success > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #d6e9c6;\n}\n.panel-info {\n  border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n  color: #31708f;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #bce8f1;\n}\n.panel-info > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #bce8f1;\n}\n.panel-warning {\n  border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #faebcc;\n}\n.panel-warning > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #faebcc;\n}\n.panel-danger {\n  border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #ebccd1;\n}\n.panel-danger > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #ebccd1;\n}\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n}\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, .15);\n}\n.well-lg {\n  padding: 24px;\n  border-radius: 6px;\n}\n.well-sm {\n  padding: 9px;\n  border-radius: 3px;\n}\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  filter: alpha(opacity=20);\n  opacity: .2;\n}\n.close:hover,\n.close:focus {\n  color: #000;\n  text-decoration: none;\n  cursor: pointer;\n  filter: alpha(opacity=50);\n  opacity: .5;\n}\nbutton.close {\n  -webkit-appearance: none;\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n}\n.modal-open {\n  overflow: hidden;\n}\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1050;\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n  -webkit-overflow-scrolling: touch;\n  outline: 0;\n}\n.modal.fade .modal-dialog {\n  -webkit-transition: -webkit-transform .3s ease-out;\n     -moz-transition:    -moz-transform .3s ease-out;\n       -o-transition:      -o-transform .3s ease-out;\n          transition:         transform .3s ease-out;\n  -webkit-transform: translate(0, -25%);\n      -ms-transform: translate(0, -25%);\n          transform: translate(0, -25%);\n}\n.modal.in .modal-dialog {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 10px;\n}\n.modal-content {\n  position: relative;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, .2);\n  border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n          box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n}\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000;\n}\n.modal-backdrop.fade {\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.modal-backdrop.in {\n  filter: alpha(opacity=50);\n  opacity: .5;\n}\n.modal-header {\n  min-height: 16.42857143px;\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n  margin-top: -2px;\n}\n.modal-title {\n  margin: 0;\n  line-height: 1.42857143;\n}\n.modal-body {\n  position: relative;\n  padding: 20px;\n}\n.modal-footer {\n  padding: 19px 20px 20px;\n  margin-top: 15px;\n  text-align: right;\n  border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n@media (min-width: 768px) {\n  .modal-dialog {\n    width: 600px;\n    margin: 30px auto;\n  }\n  .modal-content {\n    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n            box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n  }\n  .modal-sm {\n    width: 300px;\n  }\n}\n@media (min-width: 992px) {\n  .modal-lg {\n    width: 900px;\n  }\n}\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 12px;\n  line-height: 1.4;\n  visibility: visible;\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.tooltip.in {\n  filter: alpha(opacity=90);\n  opacity: .9;\n}\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #fff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000;\n  border-radius: 4px;\n}\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n  right: 5px;\n  bottom: 0;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-width: 5px 5px 5px 0;\n  border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-width: 5px 0 5px 5px;\n  border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  max-width: 276px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, .2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n}\n.popover.top {\n  margin-top: -10px;\n}\n.popover.right {\n  margin-left: 10px;\n}\n.popover.bottom {\n  margin-top: 10px;\n}\n.popover.left {\n  margin-left: -10px;\n}\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  border-radius: 5px 5px 0 0;\n}\n.popover-content {\n  padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.popover > .arrow {\n  border-width: 11px;\n}\n.popover > .arrow:after {\n  content: \"\";\n  border-width: 10px;\n}\n.popover.top > .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999;\n  border-top-color: rgba(0, 0, 0, .25);\n  border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  content: \" \";\n  border-top-color: #fff;\n  border-bottom-width: 0;\n}\n.popover.right > .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999;\n  border-right-color: rgba(0, 0, 0, .25);\n  border-left-width: 0;\n}\n.popover.right > .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  content: \" \";\n  border-right-color: #fff;\n  border-left-width: 0;\n}\n.popover.bottom > .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-width: 0;\n  border-bottom-color: #999;\n  border-bottom-color: rgba(0, 0, 0, .25);\n}\n.popover.bottom > .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  content: \" \";\n  border-top-width: 0;\n  border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-right-width: 0;\n  border-left-color: #999;\n  border-left-color: rgba(0, 0, 0, .25);\n}\n.popover.left > .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  content: \" \";\n  border-right-width: 0;\n  border-left-color: #fff;\n}\n.carousel {\n  position: relative;\n}\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: .6s ease-in-out left;\n          transition: .6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  line-height: 1;\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n.carousel-inner > .active {\n  left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.carousel-inner > .next {\n  left: 100%;\n}\n.carousel-inner > .prev {\n  left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n.carousel-inner > .active.left {\n  left: -100%;\n}\n.carousel-inner > .active.right {\n  left: 100%;\n}\n.carousel-control {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 15%;\n  font-size: 20px;\n  color: #fff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n  filter: alpha(opacity=50);\n  opacity: .5;\n}\n.carousel-control.left {\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .5) 0%), color-stop(rgba(0, 0, 0, .0001) 100%));\n  background-image:         linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n  background-repeat: repeat-x;\n}\n.carousel-control.right {\n  right: 0;\n  left: auto;\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .0001) 0%), color-stop(rgba(0, 0, 0, .5) 100%));\n  background-image:         linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n  background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #fff;\n  text-decoration: none;\n  filter: alpha(opacity=90);\n  outline: none;\n  opacity: .9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n  position: absolute;\n  top: 50%;\n  z-index: 5;\n  display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n  left: 50%;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n  right: 50%;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n  width: 20px;\n  height: 20px;\n  margin-top: -10px;\n  margin-left: -10px;\n  font-family: serif;\n}\n.carousel-control .icon-prev:before {\n  content: '\\2039';\n}\n.carousel-control .icon-next:before {\n  content: '\\203a';\n}\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 60%;\n  padding-left: 0;\n  margin-left: -30%;\n  text-align: center;\n  list-style: none;\n}\n.carousel-indicators li {\n  display: inline-block;\n  width: 10px;\n  height: 10px;\n  margin: 1px;\n  text-indent: -999px;\n  cursor: pointer;\n  background-color: #000 \\9;\n  background-color: rgba(0, 0, 0, 0);\n  border: 1px solid #fff;\n  border-radius: 10px;\n}\n.carousel-indicators .active {\n  width: 12px;\n  height: 12px;\n  margin: 0;\n  background-color: #fff;\n}\n.carousel-caption {\n  position: absolute;\n  right: 15%;\n  bottom: 20px;\n  left: 15%;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: #fff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n}\n.carousel-caption .btn {\n  text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n  .carousel-control .glyphicon-chevron-left,\n  .carousel-control .glyphicon-chevron-right,\n  .carousel-control .icon-prev,\n  .carousel-control .icon-next {\n    width: 30px;\n    height: 30px;\n    margin-top: -15px;\n    margin-left: -15px;\n    font-size: 30px;\n  }\n  .carousel-caption {\n    right: 20%;\n    left: 20%;\n    padding-bottom: 30px;\n  }\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n.clearfix:before,\n.clearfix:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n.clearfix:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-footer:after {\n  clear: both;\n}\n.center-block {\n  display: block;\n  margin-right: auto;\n  margin-left: auto;\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n.hide {\n  display: none !important;\n}\n.show {\n  display: block !important;\n}\n.invisible {\n  visibility: hidden;\n}\n.text-hide {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n.affix {\n  position: fixed;\n}\n@-ms-viewport {\n  width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n  display: none !important;\n}\n@media (max-width: 767px) {\n  .visible-xs {\n    display: block !important;\n  }\n  table.visible-xs {\n    display: table;\n  }\n  tr.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-xs,\n  td.visible-xs {\n    display: table-cell !important;\n  }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm {\n    display: block !important;\n  }\n  table.visible-sm {\n    display: table;\n  }\n  tr.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: table-cell !important;\n  }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md {\n    display: block !important;\n  }\n  table.visible-md {\n    display: table;\n  }\n  tr.visible-md {\n    display: table-row !important;\n  }\n  th.visible-md,\n  td.visible-md {\n    display: table-cell !important;\n  }\n}\n@media (min-width: 1200px) {\n  .visible-lg {\n    display: block !important;\n  }\n  table.visible-lg {\n    display: table;\n  }\n  tr.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-lg,\n  td.visible-lg {\n    display: table-cell !important;\n  }\n}\n@media (max-width: 767px) {\n  .hidden-xs {\n    display: none !important;\n  }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-sm {\n    display: none !important;\n  }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-md {\n    display: none !important;\n  }\n}\n@media (min-width: 1200px) {\n  .hidden-lg {\n    display: none !important;\n  }\n}\n.visible-print {\n  display: none !important;\n}\n@media print {\n  .visible-print {\n    display: block !important;\n  }\n  table.visible-print {\n    display: table;\n  }\n  tr.visible-print {\n    display: table-row !important;\n  }\n  th.visible-print,\n  td.visible-print {\n    display: table-cell !important;\n  }\n}\n@media print {\n  .hidden-print {\n    display: none !important;\n  }\n}\n/*# sourceMappingURL=bootstrap.css.map */\n"
  },
  {
    "path": "client/css/codemirror-mdn.css",
    "content": "/*\n  MDN-LIKE Theme - Mozilla\n  Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>\n  Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues\n  GitHub: @peterkroon\n\n  The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation\n\n*/\n.cm-s-mdn-like.CodeMirror { color: #999; font-family: monospace; background-color: #fff; }\n.cm-s-mdn-like .CodeMirror-selected { background: #cfc !important; }\n\n.cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; }\n.cm-s-mdn-like .CodeMirror-linenumber { color: #aaa; margin-left: 3px; }\ndiv.cm-s-mdn-like .CodeMirror-cursor { border-left: 2px solid #222; }\n\n.cm-s-mdn-like .cm-keyword {  color: #6262FF; }\n.cm-s-mdn-like .cm-atom { color: #F90; }\n.cm-s-mdn-like .cm-number { color:  #ca7841; }\n.cm-s-mdn-like .cm-def { color: #8DA6CE; }\n.cm-s-mdn-like span.cm-variable-2, .cm-s-mdn-like span.cm-tag { color: #690; }\n.cm-s-mdn-like span.cm-variable-3, .cm-s-mdn-like span.cm-def { color: #07a; }\n\n.cm-s-mdn-like .cm-variable { color: #07a; }\n.cm-s-mdn-like .cm-property { color: #905; }\n.cm-s-mdn-like .cm-qualifier { color: #690; }\n\n.cm-s-mdn-like .cm-operator { color: #cda869; }\n.cm-s-mdn-like .cm-comment { color:#777; font-weight:normal; }\n.cm-s-mdn-like .cm-string { color:#07a; font-style:italic; }\n.cm-s-mdn-like .cm-string-2 { color:#bd6b18; } /*?*/\n.cm-s-mdn-like .cm-meta { color: #000; } /*?*/\n.cm-s-mdn-like .cm-builtin { color: #9B7536; } /*?*/\n.cm-s-mdn-like .cm-tag { color: #997643; }\n.cm-s-mdn-like .cm-attribute { color: #d6bb6d; } /*?*/\n.cm-s-mdn-like .cm-header { color: #FF6400; }\n.cm-s-mdn-like .cm-hr { color: #AEAEAE; }\n.cm-s-mdn-like .cm-link {   color:#ad9361; font-style:italic; text-decoration:none; }\n.cm-s-mdn-like .cm-error { border-bottom: 1px solid red; }\n\ndiv.cm-s-mdn-like .CodeMirror-activeline-background {background: #efefff;}\ndiv.cm-s-mdn-like span.CodeMirror-matchingbracket {outline:1px solid grey; color: inherit;}\n\n.cm-s-mdn-like.CodeMirror { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFcAAAAyCAYAAAAp8UeFAAAHvklEQVR42s2b63bcNgyEQZCSHCdt2vd/0tWF7I+Q6XgMXiTtuvU5Pl57ZQKkKHzEAOtF5KeIJBGJ8uvL599FRFREZhFx8DeXv8trn68RuGaC8TRfo3SNp9dlDDHedyLyTUTeRWStXKPZrjtpZxaRw5hPqozRs1N8/enzIiQRWcCgy4MUA0f+XWliDhyL8Lfyvx7ei/Ae3iQFHyw7U/59pQVIMEEPEz0G7XiwdRjzSfC3UTtz9vchIntxvry5iMgfIhJoEflOz2CQr3F5h/HfeFe+GTdLaKcu9L8LTeQb/R/7GgbsfKedyNdoHsN31uRPWrfZ5wsj/NzzRQHuToIdU3ahwnsKPxXCjJITuOsi7XLc7SG/v5GdALs7wf8JjTFiB5+QvTEfRyGOfX3Lrx8wxyQi3sNq46O7QahQiCsRFgqddjBouVEHOKDgXAQHD9gJCr5sMKkEdjwsarG/ww3BMHBU7OBjXnzdyY7SfCxf5/z6ATccrwlKuwC/jhznnPF4CgVzhhVf4xp2EixcBActO75iZ8/fM9zAs2OMzKdslgXWJ9XG8PQoOAMA5fGcsvORgv0doBXyHrCwfLJAOwo71QLNkb8n2Pl6EWiR7OCibtkPaz4Kc/0NNAze2gju3zOwekALDaCFPI5vjPFmgGY5AZqyGEvH1x7QfIb8YtxMnA/b+QQ0aQDAwc6JMFg8CbQZ4qoYEEHbRwNojuK3EHwd7VALSgq+MNDKzfT58T8qdpADrgW0GmgcAS1lhzztJmkAzcPNOQbsWEALBDSlMKUG0Eq4CLAQWvEVQ9WU57gZJwZtgPO3r9oBTQ9WO8TjqXINx8R0EYpiZEUWOF3FxkbJkgU9B2f41YBrIj5ZfsQa0M5kTgiAAqM3ShXLgu8XMqcrQBvJ0CL5pnTsfMB13oB8athpAq2XOQmcGmoACCLydx7nToa23ATaSIY2ichfOdPTGxlasXMLaL0MLZAOwAKIM+y8CmicobGdCcbbK9DzN+yYGVoNNI5iUKTMyYOjPse4A8SM1MmcXgU0toOq1yO/v8FOxlASyc7TgeYaAMBJHcY1CcCwGI/TK4AmDbDyKYBBtFUkRwto8gygiQEaByFgJ00BH2M8JWwQS1nafDXQCidWyOI8AcjDCSjCLk8ngObuAm3JAHAdubAmOaK06V8MNEsKPJOhobSprwQa6gD7DclRQdqcwL4zxqgBrQcabUiBLclRDKAlWp+etPkBaNMA0AKlrHwTdEByZAA4GM+SNluSY6wAzcMNewxmgig5Ks0nkrSpBvSaQHMdKTBAnLojOdYyGpQ254602ZILPdTD1hdlggdIm74jbTp8vDwF5ZYUeLWGJpWsh6XNyXgcYwVoJQTEhhTYkxzZjiU5npU2TaB979TQehlaAVq4kaGpiPwwwLkYUuBbQwocyQTv1tA0+1UFWoJF3iv1oq+qoSk8EQdJmwHkziIF7oOZk14EGitibAdjLYYK78H5vZOhtWpoI0ATGHs0Q8OMb4Ey+2bU2UYztCtA0wFAs7TplGLRVQCcqaFdGSPCeTI1QNIC52iWNzof6Uib7xjEp07mNNoUYmVosVItHrHzRlLgBn9LFyRHaQCtVUMbtTNhoXWiTOO9k/V8BdAc1Oq0ArSQs6/5SU0hckNy9NnXqQY0PGYo5dWJ7nINaN6o958FWin27aBaWRka1r5myvLOAm0j30eBJqCxHLReVclxhxOEN2JfDWjxBtAC7MIH1fVaGdoOp4qJYDgKtKPSFNID2gSnGldrCqkFZ+5UeQXQBIRrSwocbdZYQT/2LwRahBPBXoHrB8nxaGROST62DKUbQOMMzZIC9abkuELfQzQALWTnDNAm8KHWFOJgJ5+SHIvTPcmx1xQyZRhNL5Qci689aXMEaN/uNIWkEwDAvFpOZmgsBaaGnbs1NPa1Jm32gBZAIh1pCtG7TSH4aE0y1uVY4uqoFPisGlpP2rSA5qTecWn5agK6BzSpgAyD+wFaqhnYoSZ1Vwr8CmlTQbrcO3ZaX0NAEyMbYaAlyquFoLKK3SPby9CeVUPThrSJmkCAE0CrKUQadi4DrdSlWhmah0YL9z9vClH59YGbHx1J8VZTyAjQepJjmXwAKTDQI3omc3p1U4gDUf6RfcdYfrUp5ClAi2J3Ba6UOXGo+K+bQrjjssitG2SJzshaLwMtXgRagUNpYYoVkMSBLM+9GGiJZMvduG6DRZ4qc04DMPtQQxOjEtACmhO7K1AbNbQDEggZyJwscFpAGwENhoBeUwh3bWolhe8BTYVKxQEWrSUn/uhcM5KhvUu/+eQu0Lzhi+VrK0PrZZNDQKs9cpYUuFYgMVpD4/NxenJTiMCNqdUEUf1qZWjppLT5qSkkUZbCwkbZMSuVnu80hfSkzRbQeqCZSAh6huR4VtoM2gHAlLf72smuWgE+VV7XpE25Ab2WFDgyhnSuKbs4GuGzCjR+tIoUuMFg3kgcWKLTwRqanJQ2W00hAsenfaApRC42hbCvK1SlE0HtE9BGgneJO+ELamitD1YjjOYnNYVcraGhtKkW0EqVVeDx733I2NH581k1NNxNLG0i0IJ8/NjVaOZ0tYZ2Vtr0Xv7tPV3hkWp9EFkgS/J0vosngTaSoaG06WHi+xObQkaAdlbanP8B2+2l0f90LmUAAAAASUVORK5CYII=); }\n"
  },
  {
    "path": "client/css/codemirror.css",
    "content": "/* BASICS */\n\n.CodeMirror {\n  /* Set height, width, borders, and global font properties here */\n  font-family: monospace;\n  height: 300px;\n}\n.CodeMirror-scroll {\n  /* Set scrolling behaviour here */\n  overflow: auto;\n}\n\n/* PADDING */\n\n.CodeMirror-lines {\n  padding: 4px 0; /* Vertical padding around content */\n}\n.CodeMirror pre {\n  padding: 0 4px; /* Horizontal padding of content */\n}\n\n.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n  background-color: white; /* The little square between H and V scrollbars */\n}\n\n/* GUTTER */\n\n.CodeMirror-gutters {\n  border-right: 1px solid #ddd;\n  background-color: #f7f7f7;\n  white-space: nowrap;\n}\n.CodeMirror-linenumbers {}\n.CodeMirror-linenumber {\n  padding: 0 3px 0 5px;\n  min-width: 20px;\n  text-align: right;\n  color: #999;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n/* CURSOR */\n\n.CodeMirror div.CodeMirror-cursor {\n  border-left: 1px solid black;\n  z-index: 3;\n}\n/* Shown when moving in bi-directional text */\n.CodeMirror div.CodeMirror-secondarycursor {\n  border-left: 1px solid silver;\n}\n.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {\n  width: auto;\n  border: 0;\n  background: #7e7;\n  z-index: 1;\n}\n/* Can style cursor different in overwrite (non-insert) mode */\n.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}\n\n.cm-tab { display: inline-block; }\n\n.CodeMirror-ruler {\n  border-left: 1px solid #ccc;\n  position: absolute;\n}\n\n/* DEFAULT THEME */\n\n.cm-s-default .cm-keyword {color: #708;}\n.cm-s-default .cm-atom {color: #219;}\n.cm-s-default .cm-number {color: #164;}\n.cm-s-default .cm-def {color: #00f;}\n.cm-s-default .cm-variable {color: black;}\n.cm-s-default .cm-variable-2 {color: #05a;}\n.cm-s-default .cm-variable-3 {color: #085;}\n.cm-s-default .cm-property {color: black;}\n.cm-s-default .cm-operator {color: black;}\n.cm-s-default .cm-comment {color: #a50;}\n.cm-s-default .cm-string {color: #a11;}\n.cm-s-default .cm-string-2 {color: #f50;}\n.cm-s-default .cm-meta {color: #555;}\n.cm-s-default .cm-qualifier {color: #555;}\n.cm-s-default .cm-builtin {color: #30a;}\n.cm-s-default .cm-bracket {color: #997;}\n.cm-s-default .cm-tag {color: #170;}\n.cm-s-default .cm-attribute {color: #00c;}\n.cm-s-default .cm-header {color: blue;}\n.cm-s-default .cm-quote {color: #090;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n\n.cm-negative {color: #d44;}\n.cm-positive {color: #292;}\n.cm-header, .cm-strong {font-weight: bold;}\n.cm-em {font-style: italic;}\n.cm-link {text-decoration: underline;}\n\n.cm-s-default .cm-error {color: #f00;}\n.cm-invalidchar {color: #f00;}\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n.CodeMirror-activeline-background {background: #e8f2ff;}\n\n/* STOP */\n\n/* The rest of this file contains styles related to the mechanics of\n   the editor. You probably shouldn't touch them. */\n\n.CodeMirror {\n  line-height: 1;\n  position: relative;\n  overflow: hidden;\n  background: white;\n  color: black;\n}\n\n.CodeMirror-scroll {\n  /* 30px is the magic margin used to hide the element's real scrollbars */\n  /* See overflow: hidden in .CodeMirror */\n  margin-bottom: -30px; margin-right: -30px;\n  padding-bottom: 30px;\n  height: 100%;\n  outline: none; /* Prevent dragging from highlighting the element */\n  position: relative;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n.CodeMirror-sizer {\n  position: relative;\n  border-right: 30px solid transparent;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n/* The fake, visible scrollbars. Used to force redraw during scrolling\n   before actuall scrolling happens, thus preventing shaking and\n   flickering artifacts. */\n.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n  position: absolute;\n  z-index: 6;\n  display: none;\n}\n.CodeMirror-vscrollbar {\n  right: 0; top: 0;\n  overflow-x: hidden;\n  overflow-y: scroll;\n}\n.CodeMirror-hscrollbar {\n  bottom: 0; left: 0;\n  overflow-y: hidden;\n  overflow-x: scroll;\n}\n.CodeMirror-scrollbar-filler {\n  right: 0; bottom: 0;\n}\n.CodeMirror-gutter-filler {\n  left: 0; bottom: 0;\n}\n\n.CodeMirror-gutters {\n  position: absolute; left: 0; top: 0;\n  padding-bottom: 30px;\n  z-index: 3;\n}\n.CodeMirror-gutter {\n  white-space: normal;\n  height: 100%;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  padding-bottom: 30px;\n  margin-bottom: -32px;\n  display: inline-block;\n  /* Hack to make IE7 behave */\n  *zoom:1;\n  *display:inline;\n}\n.CodeMirror-gutter-elt {\n  position: absolute;\n  cursor: default;\n  z-index: 4;\n}\n\n.CodeMirror-lines {\n  cursor: text;\n}\n.CodeMirror pre {\n  /* Reset some styles that the rest of the page might have set */\n  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;\n  border-width: 0;\n  background: transparent;\n  font-family: inherit;\n  font-size: inherit;\n  margin: 0;\n  white-space: pre;\n  word-wrap: normal;\n  line-height: inherit;\n  color: inherit;\n  z-index: 2;\n  position: relative;\n  overflow: visible;\n}\n.CodeMirror-wrap pre {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n  word-break: normal;\n}\n\n.CodeMirror-linebackground {\n  position: absolute;\n  left: 0; right: 0; top: 0; bottom: 0;\n  z-index: 0;\n}\n\n.CodeMirror-linewidget {\n  position: relative;\n  z-index: 2;\n  overflow: auto;\n}\n\n.CodeMirror-widget {}\n\n.CodeMirror-wrap .CodeMirror-scroll {\n  overflow-x: hidden;\n}\n\n.CodeMirror-measure {\n  position: absolute;\n  width: 100%;\n  height: 0;\n  overflow: hidden;\n  visibility: hidden;\n}\n.CodeMirror-measure pre { position: static; }\n\n.CodeMirror div.CodeMirror-cursor {\n  position: absolute;\n  visibility: hidden;\n  border-right: none;\n  width: 0;\n}\n.CodeMirror-focused div.CodeMirror-cursor {\n  visibility: visible;\n}\n\n.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }\n\n.cm-searching {\n  background: #ffa;\n  background: rgba(255, 255, 0, .4);\n}\n\n/* IE7 hack to prevent it from returning funny offsetTops on the spans */\n.CodeMirror span { *vertical-align: text-bottom; }\n\n@media print {\n  /* Hide the cursor when printing */\n  .CodeMirror div.CodeMirror-cursor {\n    visibility: hidden;\n  }\n}\n"
  },
  {
    "path": "client/css/dashboard.css",
    "content": "/*\n * Base structure\n */\n\n/* Move down content because we have a fixed navbar that is 50px tall */\nbody {\n  padding-top: 50px;\n}\n\n/*\n * Global add-ons\n */\n\n.sub-header {\n  padding-bottom: 10px;\n  border-bottom: 1px solid #eee;\n}\n\n\n/*\n * Sidebar\n */\n\n/* Hide for mobile, show later */\n.sidebar {\n  display: none;\n}\n@media (min-width: 768px) {\n  .sidebar {\n    position: fixed;\n    top: 51px;\n    bottom: 0;\n    left: 0;\n    z-index: 1000;\n    display: block;\n    padding: 20px;\n    overflow-x: hidden;\n    overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */\n    background-color: #EAEFF2;\n    border-right: 1px solid #eee;\n  }\n}\n\n/* Sidebar navigation */\n.nav-sidebar {\n  margin-right: -21px; /* 20px padding + 1px border */\n  margin-bottom: 20px;\n  margin-left: -20px;\n}\n.nav-sidebar > li > a {\n  padding-right: 20px;\n  padding-left: 20px;\n}\n.nav-sidebar > .active > a {\n  color: #fff;\n  background-color: #00539F;\n}\n\n\n/*\n * Main content\n */\n\n.main {\n  padding: 20px;\n}\n@media (min-width: 768px) {\n  .main {\n    padding-right: 40px;\n    padding-left: 40px;\n  }\n}\n.main .page-header {\n  margin-top: 0;\n}\n\n\n/*\n * Placeholder dashboard ideas\n */\n\n.placeholders {\n  margin-bottom: 30px;\n  text-align: center;\n}\n.placeholders h4 {\n  margin-bottom: 0;\n}\n.placeholder {\n  margin-bottom: 20px;\n}\n.placeholder img {\n  display: inline-block;\n  border-radius: 50%;\n}\n"
  },
  {
    "path": "client/css/font-awesome.css",
    "content": "/*!\n *  Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome\n *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n */\n/* FONT PATH\n * -------------------------- */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../fonts/fontawesome-webfont.eot?v=4.0.3');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n.fa {\n  display: inline-block;\n  font-family: FontAwesome;\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n/* makes the font 33% larger relative to the icon container */\n.fa-lg {\n  font-size: 1.3333333333333333em;\n  line-height: 0.75em;\n  vertical-align: -15%;\n}\n.fa-2x {\n  font-size: 2em;\n}\n.fa-3x {\n  font-size: 3em;\n}\n.fa-4x {\n  font-size: 4em;\n}\n.fa-5x {\n  font-size: 5em;\n}\n.fa-fw {\n  width: 1.2857142857142858em;\n  text-align: center;\n}\n.fa-ul {\n  padding-left: 0;\n  margin-left: 2.142857142857143em;\n  list-style-type: none;\n}\n.fa-ul > li {\n  position: relative;\n}\n.fa-li {\n  position: absolute;\n  left: -2.142857142857143em;\n  width: 2.142857142857143em;\n  top: 0.14285714285714285em;\n  text-align: center;\n}\n.fa-li.fa-lg {\n  left: -1.8571428571428572em;\n}\n.fa-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eeeeee;\n  border-radius: .1em;\n}\n.pull-right {\n  float: right;\n}\n.pull-left {\n  float: left;\n}\n.fa.pull-left {\n  margin-right: .3em;\n}\n.fa.pull-right {\n  margin-left: .3em;\n}\n.fa-spin {\n  -webkit-animation: spin 2s infinite linear;\n  -moz-animation: spin 2s infinite linear;\n  -o-animation: spin 2s infinite linear;\n  animation: spin 2s infinite linear;\n}\n@-moz-keyframes spin {\n  0% {\n    -moz-transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n  }\n}\n@-webkit-keyframes spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n  }\n}\n@-o-keyframes spin {\n  0% {\n    -o-transform: rotate(0deg);\n  }\n  100% {\n    -o-transform: rotate(359deg);\n  }\n}\n@-ms-keyframes spin {\n  0% {\n    -ms-transform: rotate(0deg);\n  }\n  100% {\n    -ms-transform: rotate(359deg);\n  }\n}\n@keyframes spin {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(359deg);\n  }\n}\n.fa-rotate-90 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);\n  -webkit-transform: rotate(90deg);\n  -moz-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  -o-transform: rotate(90deg);\n  transform: rotate(90deg);\n}\n.fa-rotate-180 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n.fa-rotate-270 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);\n  -webkit-transform: rotate(270deg);\n  -moz-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  -o-transform: rotate(270deg);\n  transform: rotate(270deg);\n}\n.fa-flip-horizontal {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);\n  -webkit-transform: scale(-1, 1);\n  -moz-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  -o-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n.fa-flip-vertical {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);\n  -webkit-transform: scale(1, -1);\n  -moz-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  -o-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n.fa-stack {\n  position: relative;\n  display: inline-block;\n  width: 2em;\n  height: 2em;\n  line-height: 2em;\n  vertical-align: middle;\n}\n.fa-stack-1x,\n.fa-stack-2x {\n  position: absolute;\n  left: 0;\n  width: 100%;\n  text-align: center;\n}\n.fa-stack-1x {\n  line-height: inherit;\n}\n.fa-stack-2x {\n  font-size: 2em;\n}\n.fa-inverse {\n  color: #ffffff;\n}\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n   readers do not read off random characters that represent icons */\n.fa-glass:before {\n  content: \"\\f000\";\n}\n.fa-music:before {\n  content: \"\\f001\";\n}\n.fa-search:before {\n  content: \"\\f002\";\n}\n.fa-envelope-o:before {\n  content: \"\\f003\";\n}\n.fa-heart:before {\n  content: \"\\f004\";\n}\n.fa-star:before {\n  content: \"\\f005\";\n}\n.fa-star-o:before {\n  content: \"\\f006\";\n}\n.fa-user:before {\n  content: \"\\f007\";\n}\n.fa-film:before {\n  content: \"\\f008\";\n}\n.fa-th-large:before {\n  content: \"\\f009\";\n}\n.fa-th:before {\n  content: \"\\f00a\";\n}\n.fa-th-list:before {\n  content: \"\\f00b\";\n}\n.fa-check:before {\n  content: \"\\f00c\";\n}\n.fa-times:before {\n  content: \"\\f00d\";\n}\n.fa-search-plus:before {\n  content: \"\\f00e\";\n}\n.fa-search-minus:before {\n  content: \"\\f010\";\n}\n.fa-power-off:before {\n  content: \"\\f011\";\n}\n.fa-signal:before {\n  content: \"\\f012\";\n}\n.fa-gear:before,\n.fa-cog:before {\n  content: \"\\f013\";\n}\n.fa-trash-o:before {\n  content: \"\\f014\";\n}\n.fa-home:before {\n  content: \"\\f015\";\n}\n.fa-file-o:before {\n  content: \"\\f016\";\n}\n.fa-clock-o:before {\n  content: \"\\f017\";\n}\n.fa-road:before {\n  content: \"\\f018\";\n}\n.fa-download:before {\n  content: \"\\f019\";\n}\n.fa-arrow-circle-o-down:before {\n  content: \"\\f01a\";\n}\n.fa-arrow-circle-o-up:before {\n  content: \"\\f01b\";\n}\n.fa-inbox:before {\n  content: \"\\f01c\";\n}\n.fa-play-circle-o:before {\n  content: \"\\f01d\";\n}\n.fa-rotate-right:before,\n.fa-repeat:before {\n  content: \"\\f01e\";\n}\n.fa-refresh:before {\n  content: \"\\f021\";\n}\n.fa-list-alt:before {\n  content: \"\\f022\";\n}\n.fa-lock:before {\n  content: \"\\f023\";\n}\n.fa-flag:before {\n  content: \"\\f024\";\n}\n.fa-headphones:before {\n  content: \"\\f025\";\n}\n.fa-volume-off:before {\n  content: \"\\f026\";\n}\n.fa-volume-down:before {\n  content: \"\\f027\";\n}\n.fa-volume-up:before {\n  content: \"\\f028\";\n}\n.fa-qrcode:before {\n  content: \"\\f029\";\n}\n.fa-barcode:before {\n  content: \"\\f02a\";\n}\n.fa-tag:before {\n  content: \"\\f02b\";\n}\n.fa-tags:before {\n  content: \"\\f02c\";\n}\n.fa-book:before {\n  content: \"\\f02d\";\n}\n.fa-bookmark:before {\n  content: \"\\f02e\";\n}\n.fa-print:before {\n  content: \"\\f02f\";\n}\n.fa-camera:before {\n  content: \"\\f030\";\n}\n.fa-font:before {\n  content: \"\\f031\";\n}\n.fa-bold:before {\n  content: \"\\f032\";\n}\n.fa-italic:before {\n  content: \"\\f033\";\n}\n.fa-text-height:before {\n  content: \"\\f034\";\n}\n.fa-text-width:before {\n  content: \"\\f035\";\n}\n.fa-align-left:before {\n  content: \"\\f036\";\n}\n.fa-align-center:before {\n  content: \"\\f037\";\n}\n.fa-align-right:before {\n  content: \"\\f038\";\n}\n.fa-align-justify:before {\n  content: \"\\f039\";\n}\n.fa-list:before {\n  content: \"\\f03a\";\n}\n.fa-dedent:before,\n.fa-outdent:before {\n  content: \"\\f03b\";\n}\n.fa-indent:before {\n  content: \"\\f03c\";\n}\n.fa-video-camera:before {\n  content: \"\\f03d\";\n}\n.fa-picture-o:before {\n  content: \"\\f03e\";\n}\n.fa-pencil:before {\n  content: \"\\f040\";\n}\n.fa-map-marker:before {\n  content: \"\\f041\";\n}\n.fa-adjust:before {\n  content: \"\\f042\";\n}\n.fa-tint:before {\n  content: \"\\f043\";\n}\n.fa-edit:before,\n.fa-pencil-square-o:before {\n  content: \"\\f044\";\n}\n.fa-share-square-o:before {\n  content: \"\\f045\";\n}\n.fa-check-square-o:before {\n  content: \"\\f046\";\n}\n.fa-arrows:before {\n  content: \"\\f047\";\n}\n.fa-step-backward:before {\n  content: \"\\f048\";\n}\n.fa-fast-backward:before {\n  content: \"\\f049\";\n}\n.fa-backward:before {\n  content: \"\\f04a\";\n}\n.fa-play:before {\n  content: \"\\f04b\";\n}\n.fa-pause:before {\n  content: \"\\f04c\";\n}\n.fa-stop:before {\n  content: \"\\f04d\";\n}\n.fa-forward:before {\n  content: \"\\f04e\";\n}\n.fa-fast-forward:before {\n  content: \"\\f050\";\n}\n.fa-step-forward:before {\n  content: \"\\f051\";\n}\n.fa-eject:before {\n  content: \"\\f052\";\n}\n.fa-chevron-left:before {\n  content: \"\\f053\";\n}\n.fa-chevron-right:before {\n  content: \"\\f054\";\n}\n.fa-plus-circle:before {\n  content: \"\\f055\";\n}\n.fa-minus-circle:before {\n  content: \"\\f056\";\n}\n.fa-times-circle:before {\n  content: \"\\f057\";\n}\n.fa-check-circle:before {\n  content: \"\\f058\";\n}\n.fa-question-circle:before {\n  content: \"\\f059\";\n}\n.fa-info-circle:before {\n  content: \"\\f05a\";\n}\n.fa-crosshairs:before {\n  content: \"\\f05b\";\n}\n.fa-times-circle-o:before {\n  content: \"\\f05c\";\n}\n.fa-check-circle-o:before {\n  content: \"\\f05d\";\n}\n.fa-ban:before {\n  content: \"\\f05e\";\n}\n.fa-arrow-left:before {\n  content: \"\\f060\";\n}\n.fa-arrow-right:before {\n  content: \"\\f061\";\n}\n.fa-arrow-up:before {\n  content: \"\\f062\";\n}\n.fa-arrow-down:before {\n  content: \"\\f063\";\n}\n.fa-mail-forward:before,\n.fa-share:before {\n  content: \"\\f064\";\n}\n.fa-expand:before {\n  content: \"\\f065\";\n}\n.fa-compress:before {\n  content: \"\\f066\";\n}\n.fa-plus:before {\n  content: \"\\f067\";\n}\n.fa-minus:before {\n  content: \"\\f068\";\n}\n.fa-asterisk:before {\n  content: \"\\f069\";\n}\n.fa-exclamation-circle:before {\n  content: \"\\f06a\";\n}\n.fa-gift:before {\n  content: \"\\f06b\";\n}\n.fa-leaf:before {\n  content: \"\\f06c\";\n}\n.fa-fire:before {\n  content: \"\\f06d\";\n}\n.fa-eye:before {\n  content: \"\\f06e\";\n}\n.fa-eye-slash:before {\n  content: \"\\f070\";\n}\n.fa-warning:before,\n.fa-exclamation-triangle:before {\n  content: \"\\f071\";\n}\n.fa-plane:before {\n  content: \"\\f072\";\n}\n.fa-calendar:before {\n  content: \"\\f073\";\n}\n.fa-random:before {\n  content: \"\\f074\";\n}\n.fa-comment:before {\n  content: \"\\f075\";\n}\n.fa-magnet:before {\n  content: \"\\f076\";\n}\n.fa-chevron-up:before {\n  content: \"\\f077\";\n}\n.fa-chevron-down:before {\n  content: \"\\f078\";\n}\n.fa-retweet:before {\n  content: \"\\f079\";\n}\n.fa-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.fa-folder:before {\n  content: \"\\f07b\";\n}\n.fa-folder-open:before {\n  content: \"\\f07c\";\n}\n.fa-arrows-v:before {\n  content: \"\\f07d\";\n}\n.fa-arrows-h:before {\n  content: \"\\f07e\";\n}\n.fa-bar-chart-o:before {\n  content: \"\\f080\";\n}\n.fa-twitter-square:before {\n  content: \"\\f081\";\n}\n.fa-facebook-square:before {\n  content: \"\\f082\";\n}\n.fa-camera-retro:before {\n  content: \"\\f083\";\n}\n.fa-key:before {\n  content: \"\\f084\";\n}\n.fa-gears:before,\n.fa-cogs:before {\n  content: \"\\f085\";\n}\n.fa-comments:before {\n  content: \"\\f086\";\n}\n.fa-thumbs-o-up:before {\n  content: \"\\f087\";\n}\n.fa-thumbs-o-down:before {\n  content: \"\\f088\";\n}\n.fa-star-half:before {\n  content: \"\\f089\";\n}\n.fa-heart-o:before {\n  content: \"\\f08a\";\n}\n.fa-sign-out:before {\n  content: \"\\f08b\";\n}\n.fa-linkedin-square:before {\n  content: \"\\f08c\";\n}\n.fa-thumb-tack:before {\n  content: \"\\f08d\";\n}\n.fa-external-link:before {\n  content: \"\\f08e\";\n}\n.fa-sign-in:before {\n  content: \"\\f090\";\n}\n.fa-trophy:before {\n  content: \"\\f091\";\n}\n.fa-github-square:before {\n  content: \"\\f092\";\n}\n.fa-upload:before {\n  content: \"\\f093\";\n}\n.fa-lemon-o:before {\n  content: \"\\f094\";\n}\n.fa-phone:before {\n  content: \"\\f095\";\n}\n.fa-square-o:before {\n  content: \"\\f096\";\n}\n.fa-bookmark-o:before {\n  content: \"\\f097\";\n}\n.fa-phone-square:before {\n  content: \"\\f098\";\n}\n.fa-twitter:before {\n  content: \"\\f099\";\n}\n.fa-facebook:before {\n  content: \"\\f09a\";\n}\n.fa-github:before {\n  content: \"\\f09b\";\n}\n.fa-unlock:before {\n  content: \"\\f09c\";\n}\n.fa-credit-card:before {\n  content: \"\\f09d\";\n}\n.fa-rss:before {\n  content: \"\\f09e\";\n}\n.fa-hdd-o:before {\n  content: \"\\f0a0\";\n}\n.fa-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.fa-bell:before {\n  content: \"\\f0f3\";\n}\n.fa-certificate:before {\n  content: \"\\f0a3\";\n}\n.fa-hand-o-right:before {\n  content: \"\\f0a4\";\n}\n.fa-hand-o-left:before {\n  content: \"\\f0a5\";\n}\n.fa-hand-o-up:before {\n  content: \"\\f0a6\";\n}\n.fa-hand-o-down:before {\n  content: \"\\f0a7\";\n}\n.fa-arrow-circle-left:before {\n  content: \"\\f0a8\";\n}\n.fa-arrow-circle-right:before {\n  content: \"\\f0a9\";\n}\n.fa-arrow-circle-up:before {\n  content: \"\\f0aa\";\n}\n.fa-arrow-circle-down:before {\n  content: \"\\f0ab\";\n}\n.fa-globe:before {\n  content: \"\\f0ac\";\n}\n.fa-wrench:before {\n  content: \"\\f0ad\";\n}\n.fa-tasks:before {\n  content: \"\\f0ae\";\n}\n.fa-filter:before {\n  content: \"\\f0b0\";\n}\n.fa-briefcase:before {\n  content: \"\\f0b1\";\n}\n.fa-arrows-alt:before {\n  content: \"\\f0b2\";\n}\n.fa-group:before,\n.fa-users:before {\n  content: \"\\f0c0\";\n}\n.fa-chain:before,\n.fa-link:before {\n  content: \"\\f0c1\";\n}\n.fa-cloud:before {\n  content: \"\\f0c2\";\n}\n.fa-flask:before {\n  content: \"\\f0c3\";\n}\n.fa-cut:before,\n.fa-scissors:before {\n  content: \"\\f0c4\";\n}\n.fa-copy:before,\n.fa-files-o:before {\n  content: \"\\f0c5\";\n}\n.fa-paperclip:before {\n  content: \"\\f0c6\";\n}\n.fa-save:before,\n.fa-floppy-o:before {\n  content: \"\\f0c7\";\n}\n.fa-square:before {\n  content: \"\\f0c8\";\n}\n.fa-bars:before {\n  content: \"\\f0c9\";\n}\n.fa-list-ul:before {\n  content: \"\\f0ca\";\n}\n.fa-list-ol:before {\n  content: \"\\f0cb\";\n}\n.fa-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.fa-underline:before {\n  content: \"\\f0cd\";\n}\n.fa-table:before {\n  content: \"\\f0ce\";\n}\n.fa-magic:before {\n  content: \"\\f0d0\";\n}\n.fa-truck:before {\n  content: \"\\f0d1\";\n}\n.fa-pinterest:before {\n  content: \"\\f0d2\";\n}\n.fa-pinterest-square:before {\n  content: \"\\f0d3\";\n}\n.fa-google-plus-square:before {\n  content: \"\\f0d4\";\n}\n.fa-google-plus:before {\n  content: \"\\f0d5\";\n}\n.fa-money:before {\n  content: \"\\f0d6\";\n}\n.fa-caret-down:before {\n  content: \"\\f0d7\";\n}\n.fa-caret-up:before {\n  content: \"\\f0d8\";\n}\n.fa-caret-left:before {\n  content: \"\\f0d9\";\n}\n.fa-caret-right:before {\n  content: \"\\f0da\";\n}\n.fa-columns:before {\n  content: \"\\f0db\";\n}\n.fa-unsorted:before,\n.fa-sort:before {\n  content: \"\\f0dc\";\n}\n.fa-sort-down:before,\n.fa-sort-asc:before {\n  content: \"\\f0dd\";\n}\n.fa-sort-up:before,\n.fa-sort-desc:before {\n  content: \"\\f0de\";\n}\n.fa-envelope:before {\n  content: \"\\f0e0\";\n}\n.fa-linkedin:before {\n  content: \"\\f0e1\";\n}\n.fa-rotate-left:before,\n.fa-undo:before {\n  content: \"\\f0e2\";\n}\n.fa-legal:before,\n.fa-gavel:before {\n  content: \"\\f0e3\";\n}\n.fa-dashboard:before,\n.fa-tachometer:before {\n  content: \"\\f0e4\";\n}\n.fa-comment-o:before {\n  content: \"\\f0e5\";\n}\n.fa-comments-o:before {\n  content: \"\\f0e6\";\n}\n.fa-flash:before,\n.fa-bolt:before {\n  content: \"\\f0e7\";\n}\n.fa-sitemap:before {\n  content: \"\\f0e8\";\n}\n.fa-umbrella:before {\n  content: \"\\f0e9\";\n}\n.fa-paste:before,\n.fa-clipboard:before {\n  content: \"\\f0ea\";\n}\n.fa-lightbulb-o:before {\n  content: \"\\f0eb\";\n}\n.fa-exchange:before {\n  content: \"\\f0ec\";\n}\n.fa-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.fa-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.fa-user-md:before {\n  content: \"\\f0f0\";\n}\n.fa-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.fa-suitcase:before {\n  content: \"\\f0f2\";\n}\n.fa-bell-o:before {\n  content: \"\\f0a2\";\n}\n.fa-coffee:before {\n  content: \"\\f0f4\";\n}\n.fa-cutlery:before {\n  content: \"\\f0f5\";\n}\n.fa-file-text-o:before {\n  content: \"\\f0f6\";\n}\n.fa-building-o:before {\n  content: \"\\f0f7\";\n}\n.fa-hospital-o:before {\n  content: \"\\f0f8\";\n}\n.fa-ambulance:before {\n  content: \"\\f0f9\";\n}\n.fa-medkit:before {\n  content: \"\\f0fa\";\n}\n.fa-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.fa-beer:before {\n  content: \"\\f0fc\";\n}\n.fa-h-square:before {\n  content: \"\\f0fd\";\n}\n.fa-plus-square:before {\n  content: \"\\f0fe\";\n}\n.fa-angle-double-left:before {\n  content: \"\\f100\";\n}\n.fa-angle-double-right:before {\n  content: \"\\f101\";\n}\n.fa-angle-double-up:before {\n  content: \"\\f102\";\n}\n.fa-angle-double-down:before {\n  content: \"\\f103\";\n}\n.fa-angle-left:before {\n  content: \"\\f104\";\n}\n.fa-angle-right:before {\n  content: \"\\f105\";\n}\n.fa-angle-up:before {\n  content: \"\\f106\";\n}\n.fa-angle-down:before {\n  content: \"\\f107\";\n}\n.fa-desktop:before {\n  content: \"\\f108\";\n}\n.fa-laptop:before {\n  content: \"\\f109\";\n}\n.fa-tablet:before {\n  content: \"\\f10a\";\n}\n.fa-mobile-phone:before,\n.fa-mobile:before {\n  content: \"\\f10b\";\n}\n.fa-circle-o:before {\n  content: \"\\f10c\";\n}\n.fa-quote-left:before {\n  content: \"\\f10d\";\n}\n.fa-quote-right:before {\n  content: \"\\f10e\";\n}\n.fa-spinner:before {\n  content: \"\\f110\";\n}\n.fa-circle:before {\n  content: \"\\f111\";\n}\n.fa-mail-reply:before,\n.fa-reply:before {\n  content: \"\\f112\";\n}\n.fa-github-alt:before {\n  content: \"\\f113\";\n}\n.fa-folder-o:before {\n  content: \"\\f114\";\n}\n.fa-folder-open-o:before {\n  content: \"\\f115\";\n}\n.fa-smile-o:before {\n  content: \"\\f118\";\n}\n.fa-frown-o:before {\n  content: \"\\f119\";\n}\n.fa-meh-o:before {\n  content: \"\\f11a\";\n}\n.fa-gamepad:before {\n  content: \"\\f11b\";\n}\n.fa-keyboard-o:before {\n  content: \"\\f11c\";\n}\n.fa-flag-o:before {\n  content: \"\\f11d\";\n}\n.fa-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.fa-terminal:before {\n  content: \"\\f120\";\n}\n.fa-code:before {\n  content: \"\\f121\";\n}\n.fa-reply-all:before {\n  content: \"\\f122\";\n}\n.fa-mail-reply-all:before {\n  content: \"\\f122\";\n}\n.fa-star-half-empty:before,\n.fa-star-half-full:before,\n.fa-star-half-o:before {\n  content: \"\\f123\";\n}\n.fa-location-arrow:before {\n  content: \"\\f124\";\n}\n.fa-crop:before {\n  content: \"\\f125\";\n}\n.fa-code-fork:before {\n  content: \"\\f126\";\n}\n.fa-unlink:before,\n.fa-chain-broken:before {\n  content: \"\\f127\";\n}\n.fa-question:before {\n  content: \"\\f128\";\n}\n.fa-info:before {\n  content: \"\\f129\";\n}\n.fa-exclamation:before {\n  content: \"\\f12a\";\n}\n.fa-superscript:before {\n  content: \"\\f12b\";\n}\n.fa-subscript:before {\n  content: \"\\f12c\";\n}\n.fa-eraser:before {\n  content: \"\\f12d\";\n}\n.fa-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.fa-microphone:before {\n  content: \"\\f130\";\n}\n.fa-microphone-slash:before {\n  content: \"\\f131\";\n}\n.fa-shield:before {\n  content: \"\\f132\";\n}\n.fa-calendar-o:before {\n  content: \"\\f133\";\n}\n.fa-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.fa-rocket:before {\n  content: \"\\f135\";\n}\n.fa-maxcdn:before {\n  content: \"\\f136\";\n}\n.fa-chevron-circle-left:before {\n  content: \"\\f137\";\n}\n.fa-chevron-circle-right:before {\n  content: \"\\f138\";\n}\n.fa-chevron-circle-up:before {\n  content: \"\\f139\";\n}\n.fa-chevron-circle-down:before {\n  content: \"\\f13a\";\n}\n.fa-html5:before {\n  content: \"\\f13b\";\n}\n.fa-css3:before {\n  content: \"\\f13c\";\n}\n.fa-anchor:before {\n  content: \"\\f13d\";\n}\n.fa-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.fa-bullseye:before {\n  content: \"\\f140\";\n}\n.fa-ellipsis-h:before {\n  content: \"\\f141\";\n}\n.fa-ellipsis-v:before {\n  content: \"\\f142\";\n}\n.fa-rss-square:before {\n  content: \"\\f143\";\n}\n.fa-play-circle:before {\n  content: \"\\f144\";\n}\n.fa-ticket:before {\n  content: \"\\f145\";\n}\n.fa-minus-square:before {\n  content: \"\\f146\";\n}\n.fa-minus-square-o:before {\n  content: \"\\f147\";\n}\n.fa-level-up:before {\n  content: \"\\f148\";\n}\n.fa-level-down:before {\n  content: \"\\f149\";\n}\n.fa-check-square:before {\n  content: \"\\f14a\";\n}\n.fa-pencil-square:before {\n  content: \"\\f14b\";\n}\n.fa-external-link-square:before {\n  content: \"\\f14c\";\n}\n.fa-share-square:before {\n  content: \"\\f14d\";\n}\n.fa-compass:before {\n  content: \"\\f14e\";\n}\n.fa-toggle-down:before,\n.fa-caret-square-o-down:before {\n  content: \"\\f150\";\n}\n.fa-toggle-up:before,\n.fa-caret-square-o-up:before {\n  content: \"\\f151\";\n}\n.fa-toggle-right:before,\n.fa-caret-square-o-right:before {\n  content: \"\\f152\";\n}\n.fa-euro:before,\n.fa-eur:before {\n  content: \"\\f153\";\n}\n.fa-gbp:before {\n  content: \"\\f154\";\n}\n.fa-dollar:before,\n.fa-usd:before {\n  content: \"\\f155\";\n}\n.fa-rupee:before,\n.fa-inr:before {\n  content: \"\\f156\";\n}\n.fa-cny:before,\n.fa-rmb:before,\n.fa-yen:before,\n.fa-jpy:before {\n  content: \"\\f157\";\n}\n.fa-ruble:before,\n.fa-rouble:before,\n.fa-rub:before {\n  content: \"\\f158\";\n}\n.fa-won:before,\n.fa-krw:before {\n  content: \"\\f159\";\n}\n.fa-bitcoin:before,\n.fa-btc:before {\n  content: \"\\f15a\";\n}\n.fa-file:before {\n  content: \"\\f15b\";\n}\n.fa-file-text:before {\n  content: \"\\f15c\";\n}\n.fa-sort-alpha-asc:before {\n  content: \"\\f15d\";\n}\n.fa-sort-alpha-desc:before {\n  content: \"\\f15e\";\n}\n.fa-sort-amount-asc:before {\n  content: \"\\f160\";\n}\n.fa-sort-amount-desc:before {\n  content: \"\\f161\";\n}\n.fa-sort-numeric-asc:before {\n  content: \"\\f162\";\n}\n.fa-sort-numeric-desc:before {\n  content: \"\\f163\";\n}\n.fa-thumbs-up:before {\n  content: \"\\f164\";\n}\n.fa-thumbs-down:before {\n  content: \"\\f165\";\n}\n.fa-youtube-square:before {\n  content: \"\\f166\";\n}\n.fa-youtube:before {\n  content: \"\\f167\";\n}\n.fa-xing:before {\n  content: \"\\f168\";\n}\n.fa-xing-square:before {\n  content: \"\\f169\";\n}\n.fa-youtube-play:before {\n  content: \"\\f16a\";\n}\n.fa-dropbox:before {\n  content: \"\\f16b\";\n}\n.fa-stack-overflow:before {\n  content: \"\\f16c\";\n}\n.fa-instagram:before {\n  content: \"\\f16d\";\n}\n.fa-flickr:before {\n  content: \"\\f16e\";\n}\n.fa-adn:before {\n  content: \"\\f170\";\n}\n.fa-bitbucket:before {\n  content: \"\\f171\";\n}\n.fa-bitbucket-square:before {\n  content: \"\\f172\";\n}\n.fa-tumblr:before {\n  content: \"\\f173\";\n}\n.fa-tumblr-square:before {\n  content: \"\\f174\";\n}\n.fa-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.fa-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.fa-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.fa-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.fa-apple:before {\n  content: \"\\f179\";\n}\n.fa-windows:before {\n  content: \"\\f17a\";\n}\n.fa-android:before {\n  content: \"\\f17b\";\n}\n.fa-linux:before {\n  content: \"\\f17c\";\n}\n.fa-dribbble:before {\n  content: \"\\f17d\";\n}\n.fa-skype:before {\n  content: \"\\f17e\";\n}\n.fa-foursquare:before {\n  content: \"\\f180\";\n}\n.fa-trello:before {\n  content: \"\\f181\";\n}\n.fa-female:before {\n  content: \"\\f182\";\n}\n.fa-male:before {\n  content: \"\\f183\";\n}\n.fa-gittip:before {\n  content: \"\\f184\";\n}\n.fa-sun-o:before {\n  content: \"\\f185\";\n}\n.fa-moon-o:before {\n  content: \"\\f186\";\n}\n.fa-archive:before {\n  content: \"\\f187\";\n}\n.fa-bug:before {\n  content: \"\\f188\";\n}\n.fa-vk:before {\n  content: \"\\f189\";\n}\n.fa-weibo:before {\n  content: \"\\f18a\";\n}\n.fa-renren:before {\n  content: \"\\f18b\";\n}\n.fa-pagelines:before {\n  content: \"\\f18c\";\n}\n.fa-stack-exchange:before {\n  content: \"\\f18d\";\n}\n.fa-arrow-circle-o-right:before {\n  content: \"\\f18e\";\n}\n.fa-arrow-circle-o-left:before {\n  content: \"\\f190\";\n}\n.fa-toggle-left:before,\n.fa-caret-square-o-left:before {\n  content: \"\\f191\";\n}\n.fa-dot-circle-o:before {\n  content: \"\\f192\";\n}\n.fa-wheelchair:before {\n  content: \"\\f193\";\n}\n.fa-vimeo-square:before {\n  content: \"\\f194\";\n}\n.fa-turkish-lira:before,\n.fa-try:before {\n  content: \"\\f195\";\n}\n.fa-plus-square-o:before {\n  content: \"\\f196\";\n}\n"
  },
  {
    "path": "client/css/prettify.css",
    "content": ".pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}"
  },
  {
    "path": "client/index.html",
    "content": "<!DOCTYPE html>\n<html ng-app='scanjs' ng-csp>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"content-security-policy\" content=\"default-src 'self'; object-src 'none'; img-src 'self' data:; script-src 'self' 'unsafe-eval'\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n    <title>ScanJS</title>\n    <link href='css/app.css' rel='stylesheet' media='screen'>\n    <link href='css/angular-csp.css' rel='stylesheet' media='screen'>\n    <!-- Third-party libs -->\n    <!--<script src='js/lib/jquery-2.1.0.min.js'></script>-->\n    <script src='js/lib/angular-1.2.13.min.js'></script>\n    <script src=\"js/lib/angular-route-1.2.13.min.js\"></script>\n    <script src='js/lib/ui-bootstrap-tpls-0.3.0.js'></script>\n    <script src='js/lib/codemirror-compressed.js'></script>\n    <script src='js/lib/jszip.min.js'></script>\n    <script src='js/lib/localforage.min.js'></script>\n    <script src='js/lib/acorn.js'></script>\n    <script src='js/lib/utils.js'></script>\n    <script src='js/lib/walk.js'></script>\n\n\n    <!-- CommonJS modules -->\n    <script src='../common/scan.js'></script>\n    <!-- Client specific files -->\n    <script src='js/main.js'></script>\n      <script src='js/locationctrl.js'></script>\n    <script src='js/scanctrl.js'></script>\n    <script src='js/experimentctrl.js'></script>\n    <script src='js/scanservice.js'></script>\n    <!-- rules ctrl MUST be loaded after scan service-->\n    <script src='js/rulesctrl.js'></script>\n  </head>\n\n  <body>\n\n  <div id=\"header\" class=\"navbar navbar-inverse navbar-fixed-top\" role=\"navigation\">\n    <div class=\"navbar-brand\">ScanJS\n    </div>\n    <ul id=\"header-links\" class=\"nav navbar-nav navbar-left\" ng-controller=\"LocationCtrl\">\n      <li ng-class=\"tabBtnClass('scan')\"><a id=\"scan-header\" href=\"#/scan\">Scan</a></li>\n      <li ng-class=\"tabBtnClass('rules')\"><a id=\"rules-header\" href=\"#/rules\">Rules</a></li>\n      <li ng-class=\"tabBtnClass('experiment')\"><a id=\"experiment-header\" href=\"#/experiment\">Experiment</a></li>\n    </ul>\n  </div>\n  <!-- header -->\n\n  <div ng-view></div>\n\n\n\n\n\n\n\n\n\n  </body>\n</html>\n"
  },
  {
    "path": "client/js/experimentctrl.js",
    "content": "\"use strict\";\n\nscanjsModule.controller('ExperimentCtrl', ['$scope', 'ScanSvc', function ExperimentCtrl($scope, ScanSvc) {\n  if (!document.getElementById(\"experiment-mirror\").children.length) {\n    $scope.codeMirror = new CodeMirror(document.getElementById('experiment-mirror'), {\n      mode: 'javascript',\n      lineNumbers: true,\n      theme: 'mdn-like',\n      value: \"bar.foo\\nfoo=something\\nbaz.bar=stuff\\nfoo(something)\\nfoo.bar\\nfoo.bar()\\neval(test)\\nfoo.innerHTML=danger\",\n      tabsize: 2,\n      styleActiveLine: true\n    });\n  }\n  $scope.results=[];\n  $scope.ready=false;\n  $scope.rule=\"eval()\"\n\n  var ruleData={\n    \"name\": \"manual rule\",\n    \"source\": $scope.rule,\n    \"testhit\": $scope.rule,\n    \"testmiss\": \"\",\n    \"desc\": \"Manual input.\",\n    \"threat\": \"example\"\n  };\n\n  $scope.runScan = function () {\n    $scope.results = [];\n    $scope.error = null;\n    ScanJS.loadRules(ScanSvc.rules);\n    var code = $scope.codeMirror.getValue();\n    try {\n      var ast = acorn.parse(code, { locations: true });\n      $scope.results = ScanJS.scan(ast);\n    } catch(e) {\n      $scope.error = e;\n      console.error(e);\n    }\n    $scope.lastScan = $scope.runScan;\n  };\n\n  $scope.runManualScan = function () {\n    ruleData.source = $scope.rule;\n    ScanJS.loadRules([ruleData]);\n\n    $scope.results = [];\n    $scope.error = null;\n    var code = $scope.codeMirror.getValue();\n    try {\n      var ast = acorn.parse(code, { locations: true });\n      $scope.results = ScanJS.scan(ast);\n      //put ast on global variable for debugging purposes.\n      window.ast = ast;\n    } catch(e) {\n      $scope.error = e;\n      console.error(e);\n    }\n    $scope.lastScan = $scope.runManualScan;\n  };\n\n  $scope.showResult = function (filename,line, col) {\n    $scope.codeMirror.setCursor(line - 1, col || 0);\n    $scope.codeMirror.focus();\n  };\n\n  $scope.add_placeholder_char = function() {\n    $scope.rule += '$_any';\n  }\n  $scope.lastScan=$scope.runScan;\n  \n}]);\n"
  },
  {
    "path": "client/js/lib/acorn.js",
    "content": "// Acorn is a tiny, fast JavaScript parser written in JavaScript.\n//\n// Acorn was written by Marijn Haverbeke and released under an MIT\n// license. The Unicode regexps (for identifiers and whitespace) were\n// taken from [Esprima](http://esprima.org) by Ariya Hidayat.\n//\n// Git repositories for Acorn are available at\n//\n//     http://marijnhaverbeke.nl/git/acorn\n//     https://github.com/marijnh/acorn.git\n//\n// Please use the [github bug tracker][ghbt] to report issues.\n//\n// [ghbt]: https://github.com/marijnh/acorn/issues\n//\n// This file defines the main parser interface. The library also comes\n// with a [error-tolerant parser][dammit] and an\n// [abstract syntax tree walker][walk], defined in other files.\n//\n// [dammit]: acorn_loose.js\n// [walk]: util/walk.js\n\n(function(root, mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") return mod(exports); // CommonJS\n  if (typeof define == \"function\" && define.amd) return define([\"exports\"], mod); // AMD\n  mod(root.acorn || (root.acorn = {})); // Plain browser env\n})(this, function(exports) {\n  \"use strict\";\n\n  exports.version = \"0.5.1\";\n\n  // The main exported interface (under `self.acorn` when in the\n  // browser) is a `parse` function that takes a code string and\n  // returns an abstract syntax tree as specified by [Mozilla parser\n  // API][api], with the caveat that the SpiderMonkey-specific syntax\n  // (`let`, `yield`, inline XML, etc) is not recognized.\n  //\n  // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API\n\n  var options, input, inputLen, sourceFile;\n\n  exports.parse = function(inpt, opts) {\n    input = String(inpt); inputLen = input.length;\n    setOptions(opts);\n    initTokenState();\n    return parseTopLevel(options.program);\n  };\n\n  // A second optional argument can be given to further configure\n  // the parser process. These options are recognized:\n\n  var defaultOptions = exports.defaultOptions = {\n    // `ecmaVersion` indicates the ECMAScript version to parse. Must\n    // be either 3 or 5. This\n    // influences support for strict mode, the set of reserved words, and\n    // support for getters and setter.\n    ecmaVersion: 5,\n    // Turn on `strictSemicolons` to prevent the parser from doing\n    // automatic semicolon insertion.\n    strictSemicolons: false,\n    // When `allowTrailingCommas` is false, the parser will not allow\n    // trailing commas in array and object literals.\n    allowTrailingCommas: true,\n    // By default, reserved words are not enforced. Enable\n    // `forbidReserved` to enforce them. When this option has the\n    // value \"everywhere\", reserved words and keywords can also not be\n    // used as property names.\n    forbidReserved: false,\n    // When enabled, a return at the top level is not considered an\n    // error.\n    allowReturnOutsideFunction: false,\n    // When `locations` is on, `loc` properties holding objects with\n    // `start` and `end` properties in `{line, column}` form (with\n    // line being 1-based and column 0-based) will be attached to the\n    // nodes.\n    locations: false,\n    // A function can be passed as `onComment` option, which will\n    // cause Acorn to call that function with `(block, text, start,\n    // end)` parameters whenever a comment is skipped. `block` is a\n    // boolean indicating whether this is a block (`/* */`) comment,\n    // `text` is the content of the comment, and `start` and `end` are\n    // character offsets that denote the start and end of the comment.\n    // When the `locations` option is on, two more parameters are\n    // passed, the full `{line, column}` locations of the start and\n    // end of the comments. Note that you are not allowed to call the\n    // parser from the callback—that will corrupt its internal state.\n    onComment: null,\n    // Nodes have their start and end characters offsets recorded in\n    // `start` and `end` properties (directly on the node, rather than\n    // the `loc` object, which holds line/column data. To also add a\n    // [semi-standardized][range] `range` property holding a `[start,\n    // end]` array with the same numbers, set the `ranges` option to\n    // `true`.\n    //\n    // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678\n    ranges: false,\n    // It is possible to parse multiple files into a single AST by\n    // passing the tree produced by parsing the first file as\n    // `program` option in subsequent parses. This will add the\n    // toplevel forms of the parsed file to the `Program` (top) node\n    // of an existing parse tree.\n    program: null,\n    // When `locations` is on, you can pass this to record the source\n    // file in every node's `loc` object.\n    sourceFile: null,\n    // This value, if given, is stored in every node, whether\n    // `locations` is on or off.\n    directSourceFile: null\n  };\n\n  function setOptions(opts) {\n    options = opts || {};\n    for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt))\n      options[opt] = defaultOptions[opt];\n    sourceFile = options.sourceFile || null;\n  }\n\n  // The `getLineInfo` function is mostly useful when the\n  // `locations` option is off (for performance reasons) and you\n  // want to find the line/column position for a given character\n  // offset. `input` should be the code string that the offset refers\n  // into.\n\n  var getLineInfo = exports.getLineInfo = function(input, offset) {\n    for (var line = 1, cur = 0;;) {\n      lineBreak.lastIndex = cur;\n      var match = lineBreak.exec(input);\n      if (match && match.index < offset) {\n        ++line;\n        cur = match.index + match[0].length;\n      } else break;\n    }\n    return {line: line, column: offset - cur};\n  };\n\n  // Acorn is organized as a tokenizer and a recursive-descent parser.\n  // The `tokenize` export provides an interface to the tokenizer.\n  // Because the tokenizer is optimized for being efficiently used by\n  // the Acorn parser itself, this interface is somewhat crude and not\n  // very modular. Performing another parse or call to `tokenize` will\n  // reset the internal state, and invalidate existing tokenizers.\n\n  exports.tokenize = function(inpt, opts) {\n    input = String(inpt); inputLen = input.length;\n    setOptions(opts);\n    initTokenState();\n\n    var t = {};\n    function getToken(forceRegexp) {\n      lastEnd = tokEnd;\n      readToken(forceRegexp);\n      t.start = tokStart; t.end = tokEnd;\n      t.startLoc = tokStartLoc; t.endLoc = tokEndLoc;\n      t.type = tokType; t.value = tokVal;\n      return t;\n    }\n    getToken.jumpTo = function(pos, reAllowed) {\n      tokPos = pos;\n      if (options.locations) {\n        tokCurLine = 1;\n        tokLineStart = lineBreak.lastIndex = 0;\n        var match;\n        while ((match = lineBreak.exec(input)) && match.index < pos) {\n          ++tokCurLine;\n          tokLineStart = match.index + match[0].length;\n        }\n      }\n      tokRegexpAllowed = reAllowed;\n      skipSpace();\n    };\n    return getToken;\n  };\n\n  // State is kept in (closure-)global variables. We already saw the\n  // `options`, `input`, and `inputLen` variables above.\n\n  // The current position of the tokenizer in the input.\n\n  var tokPos;\n\n  // The start and end offsets of the current token.\n\n  var tokStart, tokEnd;\n\n  // When `options.locations` is true, these hold objects\n  // containing the tokens start and end line/column pairs.\n\n  var tokStartLoc, tokEndLoc;\n\n  // The type and value of the current token. Token types are objects,\n  // named by variables against which they can be compared, and\n  // holding properties that describe them (indicating, for example,\n  // the precedence of an infix operator, and the original name of a\n  // keyword token). The kind of value that's held in `tokVal` depends\n  // on the type of the token. For literals, it is the literal value,\n  // for operators, the operator name, and so on.\n\n  var tokType, tokVal;\n\n  // Interal state for the tokenizer. To distinguish between division\n  // operators and regular expressions, it remembers whether the last\n  // token was one that is allowed to be followed by an expression.\n  // (If it is, a slash is probably a regexp, if it isn't it's a\n  // division operator. See the `parseStatement` function for a\n  // caveat.)\n\n  var tokRegexpAllowed;\n\n  // When `options.locations` is true, these are used to keep\n  // track of the current line, and know when a new line has been\n  // entered.\n\n  var tokCurLine, tokLineStart;\n\n  // These store the position of the previous token, which is useful\n  // when finishing a node and assigning its `end` position.\n\n  var lastStart, lastEnd, lastEndLoc;\n\n  // This is the parser's state. `inFunction` is used to reject\n  // `return` statements outside of functions, `labels` to verify that\n  // `break` and `continue` have somewhere to jump to, and `strict`\n  // indicates whether strict mode is on.\n\n  var inFunction, labels, strict;\n\n  // This function is used to raise exceptions on parse errors. It\n  // takes an offset integer (into the current `input`) to indicate\n  // the location of the error, attaches the position to the end\n  // of the error message, and then raises a `SyntaxError` with that\n  // message.\n\n  function raise(pos, message) {\n    var loc = getLineInfo(input, pos);\n    message += \" (\" + loc.line + \":\" + loc.column + \")\";\n    var err = new SyntaxError(message);\n    err.pos = pos; err.loc = loc; err.raisedAt = tokPos;\n    throw err;\n  }\n\n  // Reused empty array added for node fields that are always empty.\n\n  var empty = [];\n\n  // ## Token types\n\n  // The assignment of fine-grained, information-carrying type objects\n  // allows the tokenizer to store the information it has about a\n  // token in a way that is very cheap for the parser to look up.\n\n  // All token type variables start with an underscore, to make them\n  // easy to recognize.\n\n  // These are the general types. The `type` property is only used to\n  // make them recognizeable when debugging.\n\n  var _num = {type: \"num\"}, _regexp = {type: \"regexp\"}, _string = {type: \"string\"};\n  var _name = {type: \"name\"}, _eof = {type: \"eof\"};\n\n  // Keyword tokens. The `keyword` property (also used in keyword-like\n  // operators) indicates that the token originated from an\n  // identifier-like word, which is used when parsing property names.\n  //\n  // The `beforeExpr` property is used to disambiguate between regular\n  // expressions and divisions. It is set on all token types that can\n  // be followed by an expression (thus, a slash after them would be a\n  // regular expression).\n  //\n  // `isLoop` marks a keyword as starting a loop, which is important\n  // to know when parsing a label, in order to allow or disallow\n  // continue jumps to that label.\n\n  var _break = {keyword: \"break\"}, _case = {keyword: \"case\", beforeExpr: true}, _catch = {keyword: \"catch\"};\n  var _continue = {keyword: \"continue\"}, _debugger = {keyword: \"debugger\"}, _default = {keyword: \"default\"};\n  var _do = {keyword: \"do\", isLoop: true}, _else = {keyword: \"else\", beforeExpr: true};\n  var _finally = {keyword: \"finally\"}, _for = {keyword: \"for\", isLoop: true}, _function = {keyword: \"function\"};\n  var _if = {keyword: \"if\"}, _return = {keyword: \"return\", beforeExpr: true}, _switch = {keyword: \"switch\"};\n  var _throw = {keyword: \"throw\", beforeExpr: true}, _try = {keyword: \"try\"}, _var = {keyword: \"var\"};\n  var _while = {keyword: \"while\", isLoop: true}, _with = {keyword: \"with\"}, _new = {keyword: \"new\", beforeExpr: true};\n  var _this = {keyword: \"this\"};\n\n  // The keywords that denote values.\n\n  var _null = {keyword: \"null\", atomValue: null}, _true = {keyword: \"true\", atomValue: true};\n  var _false = {keyword: \"false\", atomValue: false};\n\n  // Some keywords are treated as regular operators. `in` sometimes\n  // (when parsing `for`) needs to be tested against specifically, so\n  // we assign a variable name to it for quick comparing.\n\n  var _in = {keyword: \"in\", binop: 7, beforeExpr: true};\n\n  // Map keyword names to token types.\n\n  var keywordTypes = {\"break\": _break, \"case\": _case, \"catch\": _catch,\n    \"continue\": _continue, \"debugger\": _debugger, \"default\": _default,\n    \"do\": _do, \"else\": _else, \"finally\": _finally, \"for\": _for,\n    \"function\": _function, \"if\": _if, \"return\": _return, \"switch\": _switch,\n    \"throw\": _throw, \"try\": _try, \"var\": _var, \"while\": _while, \"with\": _with,\n    \"null\": _null, \"true\": _true, \"false\": _false, \"new\": _new, \"in\": _in,\n    \"instanceof\": {keyword: \"instanceof\", binop: 7, beforeExpr: true}, \"this\": _this,\n    \"typeof\": {keyword: \"typeof\", prefix: true, beforeExpr: true},\n    \"void\": {keyword: \"void\", prefix: true, beforeExpr: true},\n    \"delete\": {keyword: \"delete\", prefix: true, beforeExpr: true}};\n\n  // Punctuation token types. Again, the `type` property is purely for debugging.\n\n  var _bracketL = {type: \"[\", beforeExpr: true}, _bracketR = {type: \"]\"}, _braceL = {type: \"{\", beforeExpr: true};\n  var _braceR = {type: \"}\"}, _parenL = {type: \"(\", beforeExpr: true}, _parenR = {type: \")\"};\n  var _comma = {type: \",\", beforeExpr: true}, _semi = {type: \";\", beforeExpr: true};\n  var _colon = {type: \":\", beforeExpr: true}, _dot = {type: \".\"}, _question = {type: \"?\", beforeExpr: true};\n\n  // Operators. These carry several kinds of properties to help the\n  // parser use them properly (the presence of these properties is\n  // what categorizes them as operators).\n  //\n  // `binop`, when present, specifies that this operator is a binary\n  // operator, and will refer to its precedence.\n  //\n  // `prefix` and `postfix` mark the operator as a prefix or postfix\n  // unary operator. `isUpdate` specifies that the node produced by\n  // the operator should be of type UpdateExpression rather than\n  // simply UnaryExpression (`++` and `--`).\n  //\n  // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as\n  // binary operators with a very low precedence, that should result\n  // in AssignmentExpression nodes.\n\n  var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true};\n  var _assign = {isAssign: true, beforeExpr: true};\n  var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true};\n  var _logicalOR = {binop: 1, beforeExpr: true};\n  var _logicalAND = {binop: 2, beforeExpr: true};\n  var _bitwiseOR = {binop: 3, beforeExpr: true};\n  var _bitwiseXOR = {binop: 4, beforeExpr: true};\n  var _bitwiseAND = {binop: 5, beforeExpr: true};\n  var _equality = {binop: 6, beforeExpr: true};\n  var _relational = {binop: 7, beforeExpr: true};\n  var _bitShift = {binop: 8, beforeExpr: true};\n  var _plusMin = {binop: 9, prefix: true, beforeExpr: true};\n  var _multiplyModulo = {binop: 10, beforeExpr: true};\n\n  // Provide access to the token types for external users of the\n  // tokenizer.\n\n  exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,\n    parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,\n    dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof,\n    num: _num, regexp: _regexp, string: _string};\n  for (var kw in keywordTypes) exports.tokTypes[\"_\" + kw] = keywordTypes[kw];\n\n  // This is a trick taken from Esprima. It turns out that, on\n  // non-Chrome browsers, to check whether a string is in a set, a\n  // predicate containing a big ugly `switch` statement is faster than\n  // a regular expression, and on Chrome the two are about on par.\n  // This function uses `eval` (non-lexical) to produce such a\n  // predicate from a space-separated string of words.\n  //\n  // It starts by sorting the words by length.\n\n  function makePredicate(words) {\n    words = words.split(\" \");\n    var f = \"\", cats = [];\n    out: for (var i = 0; i < words.length; ++i) {\n      for (var j = 0; j < cats.length; ++j)\n        if (cats[j][0].length == words[i].length) {\n          cats[j].push(words[i]);\n          continue out;\n        }\n      cats.push([words[i]]);\n    }\n    function compareTo(arr) {\n      if (arr.length == 1) return f += \"return str === \" + JSON.stringify(arr[0]) + \";\";\n      f += \"switch(str){\";\n      for (var i = 0; i < arr.length; ++i) f += \"case \" + JSON.stringify(arr[i]) + \":\";\n      f += \"return true}return false;\";\n    }\n\n    // When there are more than three length categories, an outer\n    // switch first dispatches on the lengths, to save on comparisons.\n\n    if (cats.length > 3) {\n      cats.sort(function(a, b) {return b.length - a.length;});\n      f += \"switch(str.length){\";\n      for (var i = 0; i < cats.length; ++i) {\n        var cat = cats[i];\n        f += \"case \" + cat[0].length + \":\";\n        compareTo(cat);\n      }\n      f += \"}\";\n\n      // Otherwise, simply generate a flat `switch` statement.\n\n    } else {\n      compareTo(words);\n    }\n    return new Function(\"str\", f);\n  }\n\n  // The ECMAScript 3 reserved word list.\n\n  var isReservedWord3 = makePredicate(\"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile\");\n\n  // ECMAScript 5 reserved words.\n\n  var isReservedWord5 = makePredicate(\"class enum extends super const export import\");\n\n  // The additional reserved words in strict mode.\n\n  var isStrictReservedWord = makePredicate(\"implements interface let package private protected public static yield\");\n\n  // The forbidden variable names in strict mode.\n\n  var isStrictBadIdWord = makePredicate(\"eval arguments\");\n\n  // And the keywords.\n\n  var isKeyword = makePredicate(\"break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this\");\n\n  // ## Character categories\n\n  // Big ugly regular expressions that match characters in the\n  // whitespace, identifier, and identifier-start categories. These\n  // are only applied when a character is found to actually have a\n  // code point above 128.\n\n  var nonASCIIwhitespace = /[\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]/;\n  var nonASCIIidentifierStartChars = \"\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0\\u08a2-\\u08ac\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097f\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d\\u0c58\\u0c59\\u0c60\\u0c61\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d60\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19c1-\\u19c7\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d\\u212f-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2e2f\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309d-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua697\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa80-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc\";\n  var nonASCIIidentifierChars = \"\\u0300-\\u036f\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u0620-\\u0649\\u0672-\\u06d3\\u06e7-\\u06e8\\u06fb-\\u06fc\\u0730-\\u074a\\u0800-\\u0814\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0840-\\u0857\\u08e4-\\u08fe\\u0900-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962-\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09d7\\u09df-\\u09e0\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5f-\\u0b60\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2-\\u0ce3\\u0ce6-\\u0cef\\u0d02\\u0d03\\u0d46-\\u0d48\\u0d57\\u0d62-\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e34-\\u0e3a\\u0e40-\\u0e45\\u0e50-\\u0e59\\u0eb4-\\u0eb9\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f41-\\u0f47\\u0f71-\\u0f84\\u0f86-\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1029\\u1040-\\u1049\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u170e-\\u1710\\u1720-\\u1730\\u1740-\\u1750\\u1772\\u1773\\u1780-\\u17b2\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1920-\\u192b\\u1930-\\u193b\\u1951-\\u196d\\u19b0-\\u19c0\\u19c8-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a15\\u1a20-\\u1a53\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1b46-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c00-\\u1c22\\u1c40-\\u1c49\\u1c5b-\\u1c7d\\u1cd0-\\u1cd2\\u1d00-\\u1dbe\\u1e01-\\u1f15\\u200c\\u200d\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2d81-\\u2d96\\u2de0-\\u2dff\\u3021-\\u3028\\u3099\\u309a\\ua640-\\ua66d\\ua674-\\ua67d\\ua69f\\ua6f0-\\ua6f1\\ua7f8-\\ua800\\ua806\\ua80b\\ua823-\\ua827\\ua880-\\ua881\\ua8b4-\\ua8c4\\ua8d0-\\ua8d9\\ua8f3-\\ua8f7\\ua900-\\ua909\\ua926-\\ua92d\\ua930-\\ua945\\ua980-\\ua983\\ua9b3-\\ua9c0\\uaa00-\\uaa27\\uaa40-\\uaa41\\uaa4c-\\uaa4d\\uaa50-\\uaa59\\uaa7b\\uaae0-\\uaae9\\uaaf2-\\uaaf3\\uabc0-\\uabe1\\uabec\\uabed\\uabf0-\\uabf9\\ufb20-\\ufb28\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f\";\n  var nonASCIIidentifierStart = new RegExp(\"[\" + nonASCIIidentifierStartChars + \"]\");\n  var nonASCIIidentifier = new RegExp(\"[\" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + \"]\");\n\n  // Whether a single character denotes a newline.\n\n  var newline = /[\\n\\r\\u2028\\u2029]/;\n\n  // Matches a whole line break (where CRLF is considered a single\n  // line break). Used to count lines.\n\n  var lineBreak = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n\n  // Test whether a given character code starts an identifier.\n\n  var isIdentifierStart = exports.isIdentifierStart = function(code) {\n    if (code < 65) return code === 36;\n    if (code < 91) return true;\n    if (code < 97) return code === 95;\n    if (code < 123)return true;\n    return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));\n  };\n\n  // Test whether a given character is part of an identifier.\n\n  var isIdentifierChar = exports.isIdentifierChar = function(code) {\n    if (code < 48) return code === 36;\n    if (code < 58) return true;\n    if (code < 65) return false;\n    if (code < 91) return true;\n    if (code < 97) return code === 95;\n    if (code < 123)return true;\n    return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));\n  };\n\n  // ## Tokenizer\n\n  // These are used when `options.locations` is on, for the\n  // `tokStartLoc` and `tokEndLoc` properties.\n\n  function Position() {\n    this.line = tokCurLine;\n    this.column = tokPos - tokLineStart;\n  }\n\n  // Reset the token state. Used at the start of a parse.\n\n  function initTokenState() {\n    tokCurLine = 1;\n    tokPos = tokLineStart = 0;\n    tokRegexpAllowed = true;\n    skipSpace();\n  }\n\n  // Called at the end of every token. Sets `tokEnd`, `tokVal`, and\n  // `tokRegexpAllowed`, and skips the space after the token, so that\n  // the next one's `tokStart` will point at the right position.\n\n  function finishToken(type, val) {\n    tokEnd = tokPos;\n    if (options.locations) tokEndLoc = new Position;\n    tokType = type;\n    skipSpace();\n    tokVal = val;\n    tokRegexpAllowed = type.beforeExpr;\n  }\n\n  function skipBlockComment() {\n    var startLoc = options.onComment && options.locations && new Position;\n    var start = tokPos, end = input.indexOf(\"*/\", tokPos += 2);\n    if (end === -1) raise(tokPos - 2, \"Unterminated comment\");\n    tokPos = end + 2;\n    if (options.locations) {\n      lineBreak.lastIndex = start;\n      var match;\n      while ((match = lineBreak.exec(input)) && match.index < tokPos) {\n        ++tokCurLine;\n        tokLineStart = match.index + match[0].length;\n      }\n    }\n    if (options.onComment)\n      options.onComment(true, input.slice(start + 2, end), start, tokPos,\n        startLoc, options.locations && new Position);\n  }\n\n  function skipLineComment() {\n    var start = tokPos;\n    var startLoc = options.onComment && options.locations && new Position;\n    var ch = input.charCodeAt(tokPos+=2);\n    while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {\n      ++tokPos;\n      ch = input.charCodeAt(tokPos);\n    }\n    if (options.onComment)\n      options.onComment(false, input.slice(start + 2, tokPos), start, tokPos,\n        startLoc, options.locations && new Position);\n  }\n\n  // Called at the start of the parse and after every token. Skips\n  // whitespace and comments, and.\n\n  function skipSpace() {\n    while (tokPos < inputLen) {\n      var ch = input.charCodeAt(tokPos);\n      if (ch === 32) { // ' '\n        ++tokPos;\n      } else if (ch === 13) {\n        ++tokPos;\n        var next = input.charCodeAt(tokPos);\n        if (next === 10) {\n          ++tokPos;\n        }\n        if (options.locations) {\n          ++tokCurLine;\n          tokLineStart = tokPos;\n        }\n      } else if (ch === 10 || ch === 8232 || ch === 8233) {\n        ++tokPos;\n        if (options.locations) {\n          ++tokCurLine;\n          tokLineStart = tokPos;\n        }\n      } else if (ch > 8 && ch < 14) {\n        ++tokPos;\n      } else if (ch === 47) { // '/'\n        var next = input.charCodeAt(tokPos + 1);\n        if (next === 42) { // '*'\n          skipBlockComment();\n        } else if (next === 47) { // '/'\n          skipLineComment();\n        } else break;\n      } else if (ch === 160) { // '\\xa0'\n        ++tokPos;\n      } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {\n        ++tokPos;\n      } else {\n        break;\n      }\n    }\n  }\n\n  // ### Token reading\n\n  // This is the function that is called to fetch the next token. It\n  // is somewhat obscure, because it works in character codes rather\n  // than characters, and because operator parsing has been inlined\n  // into it.\n  //\n  // All in the name of speed.\n  //\n  // The `forceRegexp` parameter is used in the one case where the\n  // `tokRegexpAllowed` trick does not work. See `parseStatement`.\n\n  function readToken_dot() {\n    var next = input.charCodeAt(tokPos + 1);\n    if (next >= 48 && next <= 57) return readNumber(true);\n    ++tokPos;\n    return finishToken(_dot);\n  }\n\n  function readToken_slash() { // '/'\n    var next = input.charCodeAt(tokPos + 1);\n    if (tokRegexpAllowed) {++tokPos; return readRegexp();}\n    if (next === 61) return finishOp(_assign, 2);\n    return finishOp(_slash, 1);\n  }\n\n  function readToken_mult_modulo() { // '%*'\n    var next = input.charCodeAt(tokPos + 1);\n    if (next === 61) return finishOp(_assign, 2);\n    return finishOp(_multiplyModulo, 1);\n  }\n\n  function readToken_pipe_amp(code) { // '|&'\n    var next = input.charCodeAt(tokPos + 1);\n    if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2);\n    if (next === 61) return finishOp(_assign, 2);\n    return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);\n  }\n\n  function readToken_caret() { // '^'\n    var next = input.charCodeAt(tokPos + 1);\n    if (next === 61) return finishOp(_assign, 2);\n    return finishOp(_bitwiseXOR, 1);\n  }\n\n  function readToken_plus_min(code) { // '+-'\n    var next = input.charCodeAt(tokPos + 1);\n    if (next === code) {\n      if (next == 45 && input.charCodeAt(tokPos + 2) == 62 &&\n        newline.test(input.slice(lastEnd, tokPos))) {\n        // A `-->` line comment\n        tokPos += 3;\n        skipLineComment();\n        skipSpace();\n        return readToken();\n      }\n      return finishOp(_incDec, 2);\n    }\n    if (next === 61) return finishOp(_assign, 2);\n    return finishOp(_plusMin, 1);\n  }\n\n  function readToken_lt_gt(code) { // '<>'\n    var next = input.charCodeAt(tokPos + 1);\n    var size = 1;\n    if (next === code) {\n      size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2;\n      if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);\n      return finishOp(_bitShift, size);\n    }\n    if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 &&\n      input.charCodeAt(tokPos + 3) == 45) {\n      // `<!--`, an XML-style comment that should be interpreted as a line comment\n      tokPos += 4;\n      skipLineComment();\n      skipSpace();\n      return readToken();\n    }\n    if (next === 61)\n      size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;\n    return finishOp(_relational, size);\n  }\n\n  function readToken_eq_excl(code) { // '=!'\n    var next = input.charCodeAt(tokPos + 1);\n    if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);\n    return finishOp(code === 61 ? _eq : _prefix, 1);\n  }\n\n  function getTokenFromCode(code) {\n    switch(code) {\n      // The interpretation of a dot depends on whether it is followed\n      // by a digit.\n      case 46: // '.'\n        return readToken_dot();\n\n      // Punctuation tokens.\n      case 40: ++tokPos; return finishToken(_parenL);\n      case 41: ++tokPos; return finishToken(_parenR);\n      case 59: ++tokPos; return finishToken(_semi);\n      case 44: ++tokPos; return finishToken(_comma);\n      case 91: ++tokPos; return finishToken(_bracketL);\n      case 93: ++tokPos; return finishToken(_bracketR);\n      case 123: ++tokPos; return finishToken(_braceL);\n      case 125: ++tokPos; return finishToken(_braceR);\n      case 58: ++tokPos; return finishToken(_colon);\n      case 63: ++tokPos; return finishToken(_question);\n\n      // '0x' is a hexadecimal number.\n      case 48: // '0'\n        var next = input.charCodeAt(tokPos + 1);\n        if (next === 120 || next === 88) return readHexNumber();\n      // Anything else beginning with a digit is an integer, octal\n      // number, or float.\n      case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9\n      return readNumber(false);\n\n      // Quotes produce strings.\n      case 34: case 39: // '\"', \"'\"\n      return readString(code);\n\n      // Operators are parsed inline in tiny state machines. '=' (61) is\n      // often referred to. `finishOp` simply skips the amount of\n      // characters it is given as second argument, and returns a token\n      // of the type given by its first argument.\n\n      case 47: // '/'\n        return readToken_slash(code);\n\n      case 37: case 42: // '%*'\n      return readToken_mult_modulo();\n\n      case 124: case 38: // '|&'\n      return readToken_pipe_amp(code);\n\n      case 94: // '^'\n        return readToken_caret();\n\n      case 43: case 45: // '+-'\n      return readToken_plus_min(code);\n\n      case 60: case 62: // '<>'\n      return readToken_lt_gt(code);\n\n      case 61: case 33: // '=!'\n      return readToken_eq_excl(code);\n\n      case 126: // '~'\n        return finishOp(_prefix, 1);\n    }\n\n    return false;\n  }\n\n  function readToken(forceRegexp) {\n    if (!forceRegexp) tokStart = tokPos;\n    else tokPos = tokStart + 1;\n    if (options.locations) tokStartLoc = new Position;\n    if (forceRegexp) return readRegexp();\n    if (tokPos >= inputLen) return finishToken(_eof);\n\n    var code = input.charCodeAt(tokPos);\n    // Identifier or keyword. '\\uXXXX' sequences are allowed in\n    // identifiers, so '\\' also dispatches to that.\n    if (isIdentifierStart(code) || code === 92 /* '\\' */) return readWord();\n\n    var tok = getTokenFromCode(code);\n\n    if (tok === false) {\n      // If we are here, we either found a non-ASCII identifier\n      // character, or something that's entirely disallowed.\n      var ch = String.fromCharCode(code);\n      if (ch === \"\\\\\" || nonASCIIidentifierStart.test(ch)) return readWord();\n      raise(tokPos, \"Unexpected character '\" + ch + \"'\");\n    }\n    return tok;\n  }\n\n  function finishOp(type, size) {\n    var str = input.slice(tokPos, tokPos + size);\n    tokPos += size;\n    finishToken(type, str);\n  }\n\n  // Parse a regular expression. Some context-awareness is necessary,\n  // since a '/' inside a '[]' set does not end the expression.\n\n  function readRegexp() {\n    var content = \"\", escaped, inClass, start = tokPos;\n    for (;;) {\n      if (tokPos >= inputLen) raise(start, \"Unterminated regular expression\");\n      var ch = input.charAt(tokPos);\n      if (newline.test(ch)) raise(start, \"Unterminated regular expression\");\n      if (!escaped) {\n        if (ch === \"[\") inClass = true;\n        else if (ch === \"]\" && inClass) inClass = false;\n        else if (ch === \"/\" && !inClass) break;\n        escaped = ch === \"\\\\\";\n      } else escaped = false;\n      ++tokPos;\n    }\n    var content = input.slice(start, tokPos);\n    ++tokPos;\n    // Need to use `readWord1` because '\\uXXXX' sequences are allowed\n    // here (don't ask).\n    var mods = readWord1();\n    if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, \"Invalid regular expression flag\");\n    try {\n      var value = new RegExp(content, mods);\n    } catch (e) {\n      if (e instanceof SyntaxError) raise(start, \"Error parsing regular expression: \" + e.message);\n      raise(e);\n    }\n    return finishToken(_regexp, value);\n  }\n\n  // Read an integer in the given radix. Return null if zero digits\n  // were read, the integer value otherwise. When `len` is given, this\n  // will return `null` unless the integer has exactly `len` digits.\n\n  function readInt(radix, len) {\n    var start = tokPos, total = 0;\n    for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {\n      var code = input.charCodeAt(tokPos), val;\n      if (code >= 97) val = code - 97 + 10; // a\n      else if (code >= 65) val = code - 65 + 10; // A\n      else if (code >= 48 && code <= 57) val = code - 48; // 0-9\n      else val = Infinity;\n      if (val >= radix) break;\n      ++tokPos;\n      total = total * radix + val;\n    }\n    if (tokPos === start || len != null && tokPos - start !== len) return null;\n\n    return total;\n  }\n\n  function readHexNumber() {\n    tokPos += 2; // 0x\n    var val = readInt(16);\n    if (val == null) raise(tokStart + 2, \"Expected hexadecimal number\");\n    if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, \"Identifier directly after number\");\n    return finishToken(_num, val);\n  }\n\n  // Read an integer, octal integer, or floating-point number.\n\n  function readNumber(startsWithDot) {\n    var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48;\n    if (!startsWithDot && readInt(10) === null) raise(start, \"Invalid number\");\n    if (input.charCodeAt(tokPos) === 46) {\n      ++tokPos;\n      readInt(10);\n      isFloat = true;\n    }\n    var next = input.charCodeAt(tokPos);\n    if (next === 69 || next === 101) { // 'eE'\n      next = input.charCodeAt(++tokPos);\n      if (next === 43 || next === 45) ++tokPos; // '+-'\n      if (readInt(10) === null) raise(start, \"Invalid number\");\n      isFloat = true;\n    }\n    if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, \"Identifier directly after number\");\n\n    var str = input.slice(start, tokPos), val;\n    if (isFloat) val = parseFloat(str);\n    else if (!octal || str.length === 1) val = parseInt(str, 10);\n    else if (/[89]/.test(str) || strict) raise(start, \"Invalid number\");\n    else val = parseInt(str, 8);\n    return finishToken(_num, val);\n  }\n\n  // Read a string value, interpreting backslash-escapes.\n\n  function readString(quote) {\n    tokPos++;\n    var out = \"\";\n    for (;;) {\n      if (tokPos >= inputLen) raise(tokStart, \"Unterminated string constant\");\n      var ch = input.charCodeAt(tokPos);\n      if (ch === quote) {\n        ++tokPos;\n        return finishToken(_string, out);\n      }\n      if (ch === 92) { // '\\'\n        ch = input.charCodeAt(++tokPos);\n        var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));\n        if (octal) octal = octal[0];\n        while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);\n        if (octal === \"0\") octal = null;\n        ++tokPos;\n        if (octal) {\n          if (strict) raise(tokPos - 2, \"Octal literal in strict mode\");\n          out += String.fromCharCode(parseInt(octal, 8));\n          tokPos += octal.length - 1;\n        } else {\n          switch (ch) {\n            case 110: out += \"\\n\"; break; // 'n' -> '\\n'\n            case 114: out += \"\\r\"; break; // 'r' -> '\\r'\n            case 120: out += String.fromCharCode(readHexChar(2)); break; // 'x'\n            case 117: out += String.fromCharCode(readHexChar(4)); break; // 'u'\n            case 85: out += String.fromCharCode(readHexChar(8)); break; // 'U'\n            case 116: out += \"\\t\"; break; // 't' -> '\\t'\n            case 98: out += \"\\b\"; break; // 'b' -> '\\b'\n            case 118: out += \"\\u000b\"; break; // 'v' -> '\\u000b'\n            case 102: out += \"\\f\"; break; // 'f' -> '\\f'\n            case 48: out += \"\\0\"; break; // 0 -> '\\0'\n            case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\\r\\n'\n            case 10: // ' \\n'\n              if (options.locations) { tokLineStart = tokPos; ++tokCurLine; }\n              break;\n            default: out += String.fromCharCode(ch); break;\n          }\n        }\n      } else {\n        if (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) raise(tokStart, \"Unterminated string constant\");\n        out += String.fromCharCode(ch); // '\\'\n        ++tokPos;\n      }\n    }\n  }\n\n  // Used to read character escape sequences ('\\x', '\\u', '\\U').\n\n  function readHexChar(len) {\n    var n = readInt(16, len);\n    if (n === null) raise(tokStart, \"Bad character escape sequence\");\n    return n;\n  }\n\n  // Used to signal to callers of `readWord1` whether the word\n  // contained any escape sequences. This is needed because words with\n  // escape sequences must not be interpreted as keywords.\n\n  var containsEsc;\n\n  // Read an identifier, and return it as a string. Sets `containsEsc`\n  // to whether the word contained a '\\u' escape.\n  //\n  // Only builds up the word character-by-character when it actually\n  // containeds an escape, as a micro-optimization.\n\n  function readWord1() {\n    containsEsc = false;\n    var word, first = true, start = tokPos;\n    for (;;) {\n      var ch = input.charCodeAt(tokPos);\n      if (isIdentifierChar(ch)) {\n        if (containsEsc) word += input.charAt(tokPos);\n        ++tokPos;\n      } else if (ch === 92) { // \"\\\"\n        if (!containsEsc) word = input.slice(start, tokPos);\n        containsEsc = true;\n        if (input.charCodeAt(++tokPos) != 117) // \"u\"\n          raise(tokPos, \"Expecting Unicode escape sequence \\\\uXXXX\");\n        ++tokPos;\n        var esc = readHexChar(4);\n        var escStr = String.fromCharCode(esc);\n        if (!escStr) raise(tokPos - 1, \"Invalid Unicode escape\");\n        if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))\n          raise(tokPos - 4, \"Invalid Unicode escape\");\n        word += escStr;\n      } else {\n        break;\n      }\n      first = false;\n    }\n    return containsEsc ? word : input.slice(start, tokPos);\n  }\n\n  // Read an identifier or keyword token. Will check for reserved\n  // words when necessary.\n\n  function readWord() {\n    var word = readWord1();\n    var type = _name;\n    if (!containsEsc && isKeyword(word))\n      type = keywordTypes[word];\n    return finishToken(type, word);\n  }\n\n  // ## Parser\n\n  // A recursive descent parser operates by defining functions for all\n  // syntactic elements, and recursively calling those, each function\n  // advancing the input stream and returning an AST node. Precedence\n  // of constructs (for example, the fact that `!x[1]` means `!(x[1])`\n  // instead of `(!x)[1]` is handled by the fact that the parser\n  // function that parses unary prefix operators is called first, and\n  // in turn calls the function that parses `[]` subscripts — that\n  // way, it'll receive the node for `x[1]` already parsed, and wraps\n  // *that* in the unary operator node.\n  //\n  // Acorn uses an [operator precedence parser][opp] to handle binary\n  // operator precedence, because it is much more compact than using\n  // the technique outlined above, which uses different, nesting\n  // functions to specify precedence, for all of the ten binary\n  // precedence levels that JavaScript defines.\n  //\n  // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser\n\n  // ### Parser utilities\n\n  // Continue to the next token.\n\n  function next() {\n    lastStart = tokStart;\n    lastEnd = tokEnd;\n    lastEndLoc = tokEndLoc;\n    readToken();\n  }\n\n  // Enter strict mode. Re-reads the next token to please pedantic\n  // tests (\"use strict\"; 010; -- should fail).\n\n  function setStrict(strct) {\n    strict = strct;\n    tokPos = tokStart;\n    if (options.locations) {\n      while (tokPos < tokLineStart) {\n        tokLineStart = input.lastIndexOf(\"\\n\", tokLineStart - 2) + 1;\n        --tokCurLine;\n      }\n    }\n    skipSpace();\n    readToken();\n  }\n\n  // Start an AST node, attaching a start offset.\n\n  function Node() {\n    this.type = null;\n    this.start = tokStart;\n    this.end = null;\n  }\n\n  exports.Node = Node;\n\n  function SourceLocation() {\n    this.start = tokStartLoc;\n    this.end = null;\n    if (sourceFile !== null) this.source = sourceFile;\n  }\n\n  function startNode() {\n    var node = new Node();\n    if (options.locations)\n      node.loc = new SourceLocation();\n    if (options.directSourceFile)\n      node.sourceFile = options.directSourceFile;\n    if (options.ranges)\n      node.range = [tokStart, 0];\n    return node;\n  }\n\n  // Start a node whose start offset information should be based on\n  // the start of another node. For example, a binary operator node is\n  // only started after its left-hand side has already been parsed.\n\n  function startNodeFrom(other) {\n    var node = new Node();\n    node.start = other.start;\n    if (options.locations) {\n      node.loc = new SourceLocation();\n      node.loc.start = other.loc.start;\n    }\n    if (options.ranges)\n      node.range = [other.range[0], 0];\n\n    return node;\n  }\n\n  // Finish an AST node, adding `type` and `end` properties.\n\n  function finishNode(node, type) {\n    node.type = type;\n    node.end = lastEnd;\n    if (options.locations)\n      node.loc.end = lastEndLoc;\n    if (options.ranges)\n      node.range[1] = lastEnd;\n    return node;\n  }\n\n  // Test whether a statement node is the string literal `\"use strict\"`.\n\n  function isUseStrict(stmt) {\n    return options.ecmaVersion >= 5 && stmt.type === \"ExpressionStatement\" &&\n      stmt.expression.type === \"Literal\" && stmt.expression.value === \"use strict\";\n  }\n\n  // Predicate that tests whether the next token is of the given\n  // type, and if yes, consumes it as a side effect.\n\n  function eat(type) {\n    if (tokType === type) {\n      next();\n      return true;\n    }\n  }\n\n  // Test whether a semicolon can be inserted at the current position.\n\n  function canInsertSemicolon() {\n    return !options.strictSemicolons &&\n      (tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));\n  }\n\n  // Consume a semicolon, or, failing that, see if we are allowed to\n  // pretend that there is a semicolon at this position.\n\n  function semicolon() {\n    if (!eat(_semi) && !canInsertSemicolon()) unexpected();\n  }\n\n  // Expect a token of a given type. If found, consume it, otherwise,\n  // raise an unexpected token error.\n\n  function expect(type) {\n    if (tokType === type) next();\n    else unexpected();\n  }\n\n  // Raise an unexpected token error.\n\n  function unexpected() {\n    raise(tokStart, \"Unexpected token\");\n  }\n\n  // Verify that a node is an lval — something that can be assigned\n  // to.\n\n  function checkLVal(expr) {\n    if (expr.type !== \"Identifier\" && expr.type !== \"MemberExpression\")\n      raise(expr.start, \"Assigning to rvalue\");\n    if (strict && expr.type === \"Identifier\" && isStrictBadIdWord(expr.name))\n      raise(expr.start, \"Assigning to \" + expr.name + \" in strict mode\");\n  }\n\n  // ### Statement parsing\n\n  // Parse a program. Initializes the parser, reads any number of\n  // statements, and wraps them in a Program node.  Optionally takes a\n  // `program` argument.  If present, the statements will be appended\n  // to its body instead of creating a new node.\n\n  function parseTopLevel(program) {\n    lastStart = lastEnd = tokPos;\n    if (options.locations) lastEndLoc = new Position;\n    inFunction = strict = null;\n    labels = [];\n    readToken();\n\n    var node = program || startNode(), first = true;\n    if (!program) node.body = [];\n    while (tokType !== _eof) {\n      var stmt = parseStatement();\n      node.body.push(stmt);\n      if (first && isUseStrict(stmt)) setStrict(true);\n      first = false;\n    }\n    return finishNode(node, \"Program\");\n  }\n\n  var loopLabel = {kind: \"loop\"}, switchLabel = {kind: \"switch\"};\n\n  // Parse a single statement.\n  //\n  // If expecting a statement and finding a slash operator, parse a\n  // regular expression literal. This is to handle cases like\n  // `if (foo) /blah/.exec(foo);`, where looking at the previous token\n  // does not help.\n\n  function parseStatement() {\n    if (tokType === _slash || tokType === _assign && tokVal == \"/=\")\n      readToken(true);\n\n    var starttype = tokType, node = startNode();\n\n    // Most types of statements are recognized by the keyword they\n    // start with. Many are trivial to parse, some require a bit of\n    // complexity.\n\n    switch (starttype) {\n      case _break: case _continue:\n      next();\n      var isBreak = starttype === _break;\n      if (eat(_semi) || canInsertSemicolon()) node.label = null;\n      else if (tokType !== _name) unexpected();\n      else {\n        node.label = parseIdent();\n        semicolon();\n      }\n\n      // Verify that there is an actual destination to break or\n      // continue to.\n      for (var i = 0; i < labels.length; ++i) {\n        var lab = labels[i];\n        if (node.label == null || lab.name === node.label.name) {\n          if (lab.kind != null && (isBreak || lab.kind === \"loop\")) break;\n          if (node.label && isBreak) break;\n        }\n      }\n      if (i === labels.length) raise(node.start, \"Unsyntactic \" + starttype.keyword);\n      return finishNode(node, isBreak ? \"BreakStatement\" : \"ContinueStatement\");\n\n      case _debugger:\n        next();\n        semicolon();\n        return finishNode(node, \"DebuggerStatement\");\n\n      case _do:\n        next();\n        labels.push(loopLabel);\n        node.body = parseStatement();\n        labels.pop();\n        expect(_while);\n        node.test = parseParenExpression();\n        semicolon();\n        return finishNode(node, \"DoWhileStatement\");\n\n      // Disambiguating between a `for` and a `for`/`in` loop is\n      // non-trivial. Basically, we have to parse the init `var`\n      // statement or expression, disallowing the `in` operator (see\n      // the second parameter to `parseExpression`), and then check\n      // whether the next token is `in`. When there is no init part\n      // (semicolon immediately after the opening parenthesis), it is\n      // a regular `for` loop.\n\n      case _for:\n        next();\n        labels.push(loopLabel);\n        expect(_parenL);\n        if (tokType === _semi) return parseFor(node, null);\n        if (tokType === _var) {\n          var init = startNode();\n          next();\n          parseVar(init, true);\n          finishNode(init, \"VariableDeclaration\");\n          if (init.declarations.length === 1 && eat(_in))\n            return parseForIn(node, init);\n          return parseFor(node, init);\n        }\n        var init = parseExpression(false, true);\n        if (eat(_in)) {checkLVal(init); return parseForIn(node, init);}\n        return parseFor(node, init);\n\n      case _function:\n        next();\n        return parseFunction(node, true);\n\n      case _if:\n        next();\n        node.test = parseParenExpression();\n        node.consequent = parseStatement();\n        node.alternate = eat(_else) ? parseStatement() : null;\n        return finishNode(node, \"IfStatement\");\n\n      case _return:\n        if (!inFunction && !options.allowReturnOutsideFunction)\n          raise(tokStart, \"'return' outside of function\");\n        next();\n\n        // In `return` (and `break`/`continue`), the keywords with\n        // optional arguments, we eagerly look for a semicolon or the\n        // possibility to insert one.\n\n        if (eat(_semi) || canInsertSemicolon()) node.argument = null;\n        else { node.argument = parseExpression(); semicolon(); }\n        return finishNode(node, \"ReturnStatement\");\n\n      case _switch:\n        next();\n        node.discriminant = parseParenExpression();\n        node.cases = [];\n        expect(_braceL);\n        labels.push(switchLabel);\n\n        // Statements under must be grouped (by label) in SwitchCase\n        // nodes. `cur` is used to keep the node that we are currently\n        // adding statements to.\n\n        for (var cur, sawDefault; tokType != _braceR;) {\n          if (tokType === _case || tokType === _default) {\n            var isCase = tokType === _case;\n            if (cur) finishNode(cur, \"SwitchCase\");\n            node.cases.push(cur = startNode());\n            cur.consequent = [];\n            next();\n            if (isCase) cur.test = parseExpression();\n            else {\n              if (sawDefault) raise(lastStart, \"Multiple default clauses\"); sawDefault = true;\n              cur.test = null;\n            }\n            expect(_colon);\n          } else {\n            if (!cur) unexpected();\n            cur.consequent.push(parseStatement());\n          }\n        }\n        if (cur) finishNode(cur, \"SwitchCase\");\n        next(); // Closing brace\n        labels.pop();\n        return finishNode(node, \"SwitchStatement\");\n\n      case _throw:\n        next();\n        if (newline.test(input.slice(lastEnd, tokStart)))\n          raise(lastEnd, \"Illegal newline after throw\");\n        node.argument = parseExpression();\n        semicolon();\n        return finishNode(node, \"ThrowStatement\");\n\n      case _try:\n        next();\n        node.block = parseBlock();\n        node.handler = null;\n        if (tokType === _catch) {\n          var clause = startNode();\n          next();\n          expect(_parenL);\n          clause.param = parseIdent();\n          if (strict && isStrictBadIdWord(clause.param.name))\n            raise(clause.param.start, \"Binding \" + clause.param.name + \" in strict mode\");\n          expect(_parenR);\n          clause.guard = null;\n          clause.body = parseBlock();\n          node.handler = finishNode(clause, \"CatchClause\");\n        }\n        node.guardedHandlers = empty;\n        node.finalizer = eat(_finally) ? parseBlock() : null;\n        if (!node.handler && !node.finalizer)\n          raise(node.start, \"Missing catch or finally clause\");\n        return finishNode(node, \"TryStatement\");\n\n      case _var:\n        next();\n        parseVar(node);\n        semicolon();\n        return finishNode(node, \"VariableDeclaration\");\n\n      case _while:\n        next();\n        node.test = parseParenExpression();\n        labels.push(loopLabel);\n        node.body = parseStatement();\n        labels.pop();\n        return finishNode(node, \"WhileStatement\");\n\n      case _with:\n        if (strict) raise(tokStart, \"'with' in strict mode\");\n        next();\n        node.object = parseParenExpression();\n        node.body = parseStatement();\n        return finishNode(node, \"WithStatement\");\n\n      case _braceL:\n        return parseBlock();\n\n      case _semi:\n        next();\n        return finishNode(node, \"EmptyStatement\");\n\n      // If the statement does not start with a statement keyword or a\n      // brace, it's an ExpressionStatement or LabeledStatement. We\n      // simply start parsing an expression, and afterwards, if the\n      // next token is a colon and the expression was a simple\n      // Identifier node, we switch to interpreting it as a label.\n\n      default:\n        var maybeName = tokVal, expr = parseExpression();\n        if (starttype === _name && expr.type === \"Identifier\" && eat(_colon)) {\n          for (var i = 0; i < labels.length; ++i)\n            if (labels[i].name === maybeName) raise(expr.start, \"Label '\" + maybeName + \"' is already declared\");\n          var kind = tokType.isLoop ? \"loop\" : tokType === _switch ? \"switch\" : null;\n          labels.push({name: maybeName, kind: kind});\n          node.body = parseStatement();\n          labels.pop();\n          node.label = expr;\n          return finishNode(node, \"LabeledStatement\");\n        } else {\n          node.expression = expr;\n          semicolon();\n          return finishNode(node, \"ExpressionStatement\");\n        }\n    }\n  }\n\n  // Used for constructs like `switch` and `if` that insist on\n  // parentheses around their expression.\n\n  function parseParenExpression() {\n    expect(_parenL);\n    var val = parseExpression();\n    expect(_parenR);\n    return val;\n  }\n\n  // Parse a semicolon-enclosed block of statements, handling `\"use\n  // strict\"` declarations when `allowStrict` is true (used for\n  // function bodies).\n\n  function parseBlock(allowStrict) {\n    var node = startNode(), first = true, strict = false, oldStrict;\n    node.body = [];\n    expect(_braceL);\n    while (!eat(_braceR)) {\n      var stmt = parseStatement();\n      node.body.push(stmt);\n      if (first && allowStrict && isUseStrict(stmt)) {\n        oldStrict = strict;\n        setStrict(strict = true);\n      }\n      first = false;\n    }\n    if (strict && !oldStrict) setStrict(false);\n    return finishNode(node, \"BlockStatement\");\n  }\n\n  // Parse a regular `for` loop. The disambiguation code in\n  // `parseStatement` will already have parsed the init statement or\n  // expression.\n\n  function parseFor(node, init) {\n    node.init = init;\n    expect(_semi);\n    node.test = tokType === _semi ? null : parseExpression();\n    expect(_semi);\n    node.update = tokType === _parenR ? null : parseExpression();\n    expect(_parenR);\n    node.body = parseStatement();\n    labels.pop();\n    return finishNode(node, \"ForStatement\");\n  }\n\n  // Parse a `for`/`in` loop.\n\n  function parseForIn(node, init) {\n    node.left = init;\n    node.right = parseExpression();\n    expect(_parenR);\n    node.body = parseStatement();\n    labels.pop();\n    return finishNode(node, \"ForInStatement\");\n  }\n\n  // Parse a list of variable declarations.\n\n  function parseVar(node, noIn) {\n    node.declarations = [];\n    node.kind = \"var\";\n    for (;;) {\n      var decl = startNode();\n      decl.id = parseIdent();\n      if (strict && isStrictBadIdWord(decl.id.name))\n        raise(decl.id.start, \"Binding \" + decl.id.name + \" in strict mode\");\n      decl.init = eat(_eq) ? parseExpression(true, noIn) : null;\n      node.declarations.push(finishNode(decl, \"VariableDeclarator\"));\n      if (!eat(_comma)) break;\n    }\n    return node;\n  }\n\n  // ### Expression parsing\n\n  // These nest, from the most general expression type at the top to\n  // 'atomic', nondivisible expression types at the bottom. Most of\n  // the functions will simply let the function(s) below them parse,\n  // and, *if* the syntactic construct they handle is present, wrap\n  // the AST node that the inner parser gave them in another node.\n\n  // Parse a full expression. The arguments are used to forbid comma\n  // sequences (in argument lists, array literals, or object literals)\n  // or the `in` operator (in for loops initalization expressions).\n\n  function parseExpression(noComma, noIn) {\n    var expr = parseMaybeAssign(noIn);\n    if (!noComma && tokType === _comma) {\n      var node = startNodeFrom(expr);\n      node.expressions = [expr];\n      while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));\n      return finishNode(node, \"SequenceExpression\");\n    }\n    return expr;\n  }\n\n  // Parse an assignment expression. This includes applications of\n  // operators like `+=`.\n\n  function parseMaybeAssign(noIn) {\n    var left = parseMaybeConditional(noIn);\n    if (tokType.isAssign) {\n      var node = startNodeFrom(left);\n      node.operator = tokVal;\n      node.left = left;\n      next();\n      node.right = parseMaybeAssign(noIn);\n      checkLVal(left);\n      return finishNode(node, \"AssignmentExpression\");\n    }\n    return left;\n  }\n\n  // Parse a ternary conditional (`?:`) operator.\n\n  function parseMaybeConditional(noIn) {\n    var expr = parseExprOps(noIn);\n    if (eat(_question)) {\n      var node = startNodeFrom(expr);\n      node.test = expr;\n      node.consequent = parseExpression(true);\n      expect(_colon);\n      node.alternate = parseExpression(true, noIn);\n      return finishNode(node, \"ConditionalExpression\");\n    }\n    return expr;\n  }\n\n  // Start the precedence parser.\n\n  function parseExprOps(noIn) {\n    return parseExprOp(parseMaybeUnary(), -1, noIn);\n  }\n\n  // Parse binary operators with the operator precedence parsing\n  // algorithm. `left` is the left-hand side of the operator.\n  // `minPrec` provides context that allows the function to stop and\n  // defer further parser to one of its callers when it encounters an\n  // operator that has a lower precedence than the set it is parsing.\n\n  function parseExprOp(left, minPrec, noIn) {\n    var prec = tokType.binop;\n    if (prec != null && (!noIn || tokType !== _in)) {\n      if (prec > minPrec) {\n        var node = startNodeFrom(left);\n        node.left = left;\n        node.operator = tokVal;\n        var op = tokType;\n        next();\n        node.right = parseExprOp(parseMaybeUnary(), prec, noIn);\n        var exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? \"LogicalExpression\" : \"BinaryExpression\");\n        return parseExprOp(exprNode, minPrec, noIn);\n      }\n    }\n    return left;\n  }\n\n  // Parse unary operators, both prefix and postfix.\n\n  function parseMaybeUnary() {\n    if (tokType.prefix) {\n      var node = startNode(), update = tokType.isUpdate;\n      node.operator = tokVal;\n      node.prefix = true;\n      tokRegexpAllowed = true;\n      next();\n      node.argument = parseMaybeUnary();\n      if (update) checkLVal(node.argument);\n      else if (strict && node.operator === \"delete\" &&\n        node.argument.type === \"Identifier\")\n        raise(node.start, \"Deleting local variable in strict mode\");\n      return finishNode(node, update ? \"UpdateExpression\" : \"UnaryExpression\");\n    }\n    var expr = parseExprSubscripts();\n    while (tokType.postfix && !canInsertSemicolon()) {\n      var node = startNodeFrom(expr);\n      node.operator = tokVal;\n      node.prefix = false;\n      node.argument = expr;\n      checkLVal(expr);\n      next();\n      expr = finishNode(node, \"UpdateExpression\");\n    }\n    return expr;\n  }\n\n  // Parse call, dot, and `[]`-subscript expressions.\n\n  function parseExprSubscripts() {\n    return parseSubscripts(parseExprAtom());\n  }\n\n  function parseSubscripts(base, noCalls) {\n    if (eat(_dot)) {\n      var node = startNodeFrom(base);\n      node.object = base;\n      node.property = parseIdent(true);\n      node.computed = false;\n      return parseSubscripts(finishNode(node, \"MemberExpression\"), noCalls);\n    } else if (eat(_bracketL)) {\n      var node = startNodeFrom(base);\n      node.object = base;\n      node.property = parseExpression();\n      node.computed = true;\n      expect(_bracketR);\n      return parseSubscripts(finishNode(node, \"MemberExpression\"), noCalls);\n    } else if (!noCalls && eat(_parenL)) {\n      var node = startNodeFrom(base);\n      node.callee = base;\n      node.arguments = parseExprList(_parenR, false);\n      return parseSubscripts(finishNode(node, \"CallExpression\"), noCalls);\n    } else return base;\n  }\n\n  // Parse an atomic expression — either a single token that is an\n  // expression, an expression started by a keyword like `function` or\n  // `new`, or an expression wrapped in punctuation like `()`, `[]`,\n  // or `{}`.\n\n  function parseExprAtom() {\n    switch (tokType) {\n      case _this:\n        var node = startNode();\n        next();\n        return finishNode(node, \"ThisExpression\");\n      case _name:\n        return parseIdent();\n      case _num: case _string: case _regexp:\n      var node = startNode();\n      node.value = tokVal;\n      node.raw = input.slice(tokStart, tokEnd);\n      next();\n      return finishNode(node, \"Literal\");\n\n      case _null: case _true: case _false:\n      var node = startNode();\n      node.value = tokType.atomValue;\n      node.raw = tokType.keyword;\n      next();\n      return finishNode(node, \"Literal\");\n\n      case _parenL:\n        var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart;\n        next();\n        var val = parseExpression();\n        val.start = tokStart1;\n        val.end = tokEnd;\n        if (options.locations) {\n          val.loc.start = tokStartLoc1;\n          val.loc.end = tokEndLoc;\n        }\n        if (options.ranges)\n          val.range = [tokStart1, tokEnd];\n        expect(_parenR);\n        return val;\n\n      case _bracketL:\n        var node = startNode();\n        next();\n        node.elements = parseExprList(_bracketR, true, true);\n        return finishNode(node, \"ArrayExpression\");\n\n      case _braceL:\n        return parseObj();\n\n      case _function:\n        var node = startNode();\n        next();\n        return parseFunction(node, false);\n\n      case _new:\n        return parseNew();\n\n      default:\n        unexpected();\n    }\n  }\n\n  // New's precedence is slightly tricky. It must allow its argument\n  // to be a `[]` or dot subscript expression, but not a call — at\n  // least, not without wrapping it in parentheses. Thus, it uses the\n\n  function parseNew() {\n    var node = startNode();\n    next();\n    node.callee = parseSubscripts(parseExprAtom(), true);\n    if (eat(_parenL)) node.arguments = parseExprList(_parenR, false);\n    else node.arguments = empty;\n    return finishNode(node, \"NewExpression\");\n  }\n\n  // Parse an object literal.\n\n  function parseObj() {\n    var node = startNode(), first = true, sawGetSet = false;\n    node.properties = [];\n    next();\n    while (!eat(_braceR)) {\n      if (!first) {\n        expect(_comma);\n        if (options.allowTrailingCommas && eat(_braceR)) break;\n      } else first = false;\n\n      var prop = {key: parsePropertyName()}, isGetSet = false, kind;\n      if (eat(_colon)) {\n        prop.value = parseExpression(true);\n        kind = prop.kind = \"init\";\n      } else if (options.ecmaVersion >= 5 && prop.key.type === \"Identifier\" &&\n        (prop.key.name === \"get\" || prop.key.name === \"set\")) {\n        isGetSet = sawGetSet = true;\n        kind = prop.kind = prop.key.name;\n        prop.key = parsePropertyName();\n        if (tokType !== _parenL) unexpected();\n        prop.value = parseFunction(startNode(), false);\n      } else unexpected();\n\n      // getters and setters are not allowed to clash — either with\n      // each other or with an init property — and in strict mode,\n      // init properties are also not allowed to be repeated.\n\n      if (prop.key.type === \"Identifier\" && (strict || sawGetSet)) {\n        for (var i = 0; i < node.properties.length; ++i) {\n          var other = node.properties[i];\n          if (other.key.name === prop.key.name) {\n            var conflict = kind == other.kind || isGetSet && other.kind === \"init\" ||\n              kind === \"init\" && (other.kind === \"get\" || other.kind === \"set\");\n            if (conflict && !strict && kind === \"init\" && other.kind === \"init\") conflict = false;\n            if (conflict) raise(prop.key.start, \"Redefinition of property\");\n          }\n        }\n      }\n      node.properties.push(prop);\n    }\n    return finishNode(node, \"ObjectExpression\");\n  }\n\n  function parsePropertyName() {\n    if (tokType === _num || tokType === _string) return parseExprAtom();\n    return parseIdent(true);\n  }\n\n  // Parse a function declaration or literal (depending on the\n  // `isStatement` parameter).\n\n  function parseFunction(node, isStatement) {\n    if (tokType === _name) node.id = parseIdent();\n    else if (isStatement) unexpected();\n    else node.id = null;\n    node.params = [];\n    var first = true;\n    expect(_parenL);\n    while (!eat(_parenR)) {\n      if (!first) expect(_comma); else first = false;\n      node.params.push(parseIdent());\n    }\n\n    // Start a new scope with regard to labels and the `inFunction`\n    // flag (restore them to their old value afterwards).\n    var oldInFunc = inFunction, oldLabels = labels;\n    inFunction = true; labels = [];\n    node.body = parseBlock(true);\n    inFunction = oldInFunc; labels = oldLabels;\n\n    // If this is a strict mode function, verify that argument names\n    // are not repeated, and it does not try to bind the words `eval`\n    // or `arguments`.\n    if (strict || node.body.body.length && isUseStrict(node.body.body[0])) {\n      for (var i = node.id ? -1 : 0; i < node.params.length; ++i) {\n        var id = i < 0 ? node.id : node.params[i];\n        if (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))\n          raise(id.start, \"Defining '\" + id.name + \"' in strict mode\");\n        if (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)\n          raise(id.start, \"Argument name clash in strict mode\");\n      }\n    }\n\n    return finishNode(node, isStatement ? \"FunctionDeclaration\" : \"FunctionExpression\");\n  }\n\n  // Parses a comma-separated list of expressions, and returns them as\n  // an array. `close` is the token type that ends the list, and\n  // `allowEmpty` can be turned on to allow subsequent commas with\n  // nothing in between them to be parsed as `null` (which is needed\n  // for array literals).\n\n  function parseExprList(close, allowTrailingComma, allowEmpty) {\n    var elts = [], first = true;\n    while (!eat(close)) {\n      if (!first) {\n        expect(_comma);\n        if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break;\n      } else first = false;\n\n      if (allowEmpty && tokType === _comma) elts.push(null);\n      else elts.push(parseExpression(true));\n    }\n    return elts;\n  }\n\n  // Parse the next token as an identifier. If `liberal` is true (used\n  // when parsing properties), it will also convert keywords into\n  // identifiers.\n\n  function parseIdent(liberal) {\n    var node = startNode();\n    if (liberal && options.forbidReserved == \"everywhere\") liberal = false;\n    if (tokType === _name) {\n      if (!liberal &&\n        (options.forbidReserved &&\n          (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(tokVal) ||\n          strict && isStrictReservedWord(tokVal)) &&\n        input.slice(tokStart, tokEnd).indexOf(\"\\\\\") == -1)\n        raise(tokStart, \"The keyword '\" + tokVal + \"' is reserved\");\n      node.name = tokVal;\n    } else if (liberal && tokType.keyword) {\n      node.name = tokType.keyword;\n    } else {\n      unexpected();\n    }\n    tokRegexpAllowed = false;\n    next();\n    return finishNode(node, \"Identifier\");\n  }\n\n});\n"
  },
  {
    "path": "client/js/lib/acorn_loose.js",
    "content": "// Acorn: Loose parser\n//\n// This module provides an alternative parser (`parse_dammit`) that\n// exposes that same interface as `parse`, but will try to parse\n// anything as JavaScript, repairing syntax error the best it can.\n// There are circumstances in which it will raise an error and give\n// up, but they are very rare. The resulting AST will be a mostly\n// valid JavaScript AST (as per the [Mozilla parser API][api], except\n// that:\n//\n// - Return outside functions is allowed\n//\n// - Label consistency (no conflicts, break only to existing labels)\n//   is not enforced.\n//\n// - Bogus Identifier nodes with a name of `\"✖\"` are inserted whenever\n//   the parser got too confused to return anything meaningful.\n//\n// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API\n//\n// The expected use for this is to *first* try `acorn.parse`, and only\n// if that fails switch to `parse_dammit`. The loose parser might\n// parse badly indented code incorrectly, so **don't** use it as\n// your default parser.\n//\n// Quite a lot of acorn.js is duplicated here. The alternative was to\n// add a *lot* of extra cruft to that file, making it less readable\n// and slower. Copying and editing the code allowed me to make\n// invasive changes and simplifications without creating a complicated\n// tangle.\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") return mod(exports, require(\"./acorn\")); // CommonJS\n  if (typeof define == \"function\" && define.amd) return define([\"exports\", \"./acorn\"], mod); // AMD\n  mod(this.acorn || (this.acorn = {}), this.acorn); // Plain browser env\n})(function(exports, acorn) {\n  \"use strict\";\n\n  var tt = acorn.tokTypes;\n\n  var options, input, fetchToken, context;\n\n  exports.parse_dammit = function(inpt, opts) {\n    if (!opts) opts = {};\n    input = String(inpt);\n    options = opts;\n    if (!opts.tabSize) opts.tabSize = 4;\n    fetchToken = acorn.tokenize(inpt, opts);\n    sourceFile = options.sourceFile || null;\n    context = [];\n    nextLineStart = 0;\n    ahead.length = 0;\n    next();\n    return parseTopLevel();\n  };\n\n  var lastEnd, token = {start: 0, end: 0}, ahead = [];\n  var curLineStart, nextLineStart, curIndent, lastEndLoc, sourceFile;\n\n  function next() {\n    lastEnd = token.end;\n    if (options.locations)\n      lastEndLoc = token.endLoc;\n\n    if (ahead.length)\n      token = ahead.shift();\n    else\n      token = readToken();\n\n    if (token.start >= nextLineStart) {\n      while (token.start >= nextLineStart) {\n        curLineStart = nextLineStart;\n        nextLineStart = lineEnd(curLineStart) + 1;\n      }\n      curIndent = indentationAfter(curLineStart);\n    }\n  }\n\n  function readToken() {\n    for (;;) {\n      try {\n        return fetchToken();\n      } catch(e) {\n        if (!(e instanceof SyntaxError)) throw e;\n\n        // Try to skip some text, based on the error message, and then continue\n        var msg = e.message, pos = e.raisedAt, replace = true;\n        if (/unterminated/i.test(msg)) {\n          pos = lineEnd(e.pos);\n          if (/string/.test(msg)) {\n            replace = {start: e.pos, end: pos, type: tt.string, value: input.slice(e.pos + 1, pos)};\n          } else if (/regular expr/i.test(msg)) {\n            var re = input.slice(e.pos, pos);\n            try { re = new RegExp(re); } catch(e) {}\n            replace = {start: e.pos, end: pos, type: tt.regexp, value: re};\n          } else {\n            replace = false;\n          }\n        } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number/i.test(msg)) {\n          while (pos < input.length && !isSpace(input.charCodeAt(pos))) ++pos;\n        } else if (/character escape|expected hexadecimal/i.test(msg)) {\n          while (pos < input.length) {\n            var ch = input.charCodeAt(pos++);\n            if (ch === 34 || ch === 39 || isNewline(ch)) break;\n          }\n        } else if (/unexpected character/i.test(msg)) {\n          pos++;\n          replace = false;\n        } else {\n          throw e;\n        }\n        resetTo(pos);\n        if (replace === true) replace = {start: pos, end: pos, type: tt.name, value: \"✖\"};\n        if (replace) {\n          if (options.locations) {\n            replace.startLoc = acorn.getLineInfo(input, replace.start);\n            replace.endLoc = acorn.getLineInfo(input, replace.end);\n          }\n          return replace;\n        }\n      }\n    }\n  }\n\n  function resetTo(pos) {\n    var ch = input.charAt(pos - 1);\n    var reAllowed = !ch || /[\\[\\{\\(,;:?\\/*=+\\-~!|&%^<>]/.test(ch) ||\n      /[enwfd]/.test(ch) && /\\b(keywords|case|else|return|throw|new|in|(instance|type)of|delete|void)$/.test(input.slice(pos - 10, pos));\n    fetchToken.jumpTo(pos, reAllowed);\n  }\n\n  function copyToken(token) {\n    var copy = {start: token.start, end: token.end, type: token.type, value: token.value};\n    if (options.locations) {\n      copy.startLoc = token.startLoc;\n      copy.endLoc = token.endLoc;\n    }\n    return copy;\n  }\n\n  function lookAhead(n) {\n    // Copy token objects, because fetchToken will overwrite the one\n    // it returns, and in this case we still need it\n    if (!ahead.length)\n      token = copyToken(token);\n    while (n > ahead.length)\n      ahead.push(copyToken(readToken()));\n    return ahead[n-1];\n  }\n\n  var newline = /[\\n\\r\\u2028\\u2029]/;\n\n  function isNewline(ch) {\n    return ch === 10 || ch === 13 || ch === 8232 || ch === 8329;\n  }\n  function isSpace(ch) {\n    return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || isNewline(ch);\n  }\n\n  function pushCx() {\n    context.push(curIndent);\n  }\n  function popCx() {\n    curIndent = context.pop();\n  }\n\n  function lineEnd(pos) {\n    while (pos < input.length && !isNewline(input.charCodeAt(pos))) ++pos;\n    return pos;\n  }\n  function lineStart(pos) {\n    while (pos > 0 && !isNewline(input.charCodeAt(pos - 1))) --pos;\n    return pos;\n  }\n  function indentationAfter(pos) {\n    for (var count = 0;; ++pos) {\n      var ch = input.charCodeAt(pos);\n      if (ch === 32) ++count;\n      else if (ch === 9) count += options.tabSize;\n      else return count;\n    }\n  }\n\n  function closes(closeTok, indent, line, blockHeuristic) {\n    if (token.type === closeTok || token.type === tt.eof) return true;\n    if (line != curLineStart && curIndent < indent && tokenStartsLine() &&\n        (!blockHeuristic || nextLineStart >= input.length ||\n         indentationAfter(nextLineStart) < indent)) return true;\n    return false;\n  }\n\n  function tokenStartsLine() {\n    for (var p = token.start - 1; p >= curLineStart; --p) {\n      var ch = input.charCodeAt(p);\n      if (ch !== 9 && ch !== 32) return false;\n    }\n    return true;\n  }\n\n  function node_t(start) {\n    this.type = null;\n    this.start = start;\n    this.end = null;\n  }\n\n  function node_loc_t(start) {\n    this.start = start || token.startLoc || {line: 1, column: 0};\n    this.end = null;\n    if (sourceFile !== null) this.source = sourceFile;\n  }\n\n  function startNode() {\n    var node = new node_t(token.start);\n    if (options.locations)\n      node.loc = new node_loc_t();\n    return node;\n  }\n\n  function startNodeFrom(other) {\n    var node = new node_t(other.start);\n    if (options.locations)\n      node.loc = new node_loc_t(other.loc.start);\n    return node;\n  }\n\n  function finishNode(node, type) {\n    node.type = type;\n    node.end = lastEnd;\n    if (options.locations)\n      node.loc.end = lastEndLoc;\n    return node;\n  }\n\n  function getDummyLoc() {\n    if (options.locations) {\n      var loc = new node_loc_t();\n      loc.end = loc.start;\n      return loc;\n    }\n  };\n\n  function dummyIdent() {\n    var dummy = new node_t(token.start);\n    dummy.type = \"Identifier\";\n    dummy.end = token.start;\n    dummy.name = \"✖\";\n    dummy.loc = getDummyLoc();\n    return dummy;\n  }\n  function isDummy(node) { return node.name == \"✖\"; }\n\n  function eat(type) {\n    if (token.type === type) {\n      next();\n      return true;\n    }\n  }\n\n  function canInsertSemicolon() {\n    return (token.type === tt.eof || token.type === tt.braceR || newline.test(input.slice(lastEnd, token.start)));\n  }\n  function semicolon() {\n    eat(tt.semi);\n  }\n\n  function expect(type) {\n    if (eat(type)) return true;\n    if (lookAhead(1).type == type) {\n      next(); next();\n      return true;\n    }\n    if (lookAhead(2).type == type) {\n      next(); next(); next();\n      return true;\n    }\n  }\n\n  function checkLVal(expr) {\n    if (expr.type === \"Identifier\" || expr.type === \"MemberExpression\") return expr;\n    return dummyIdent();\n  }\n\n  function parseTopLevel() {\n    var node = startNode();\n    node.body = [];\n    while (token.type !== tt.eof) node.body.push(parseStatement());\n    return finishNode(node, \"Program\");\n  }\n\n  function parseStatement() {\n    var starttype = token.type, node = startNode();\n\n    switch (starttype) {\n    case tt._break: case tt._continue:\n      next();\n      var isBreak = starttype === tt._break;\n      node.label = token.type === tt.name ? parseIdent() : null;\n      semicolon();\n      return finishNode(node, isBreak ? \"BreakStatement\" : \"ContinueStatement\");\n\n    case tt._debugger:\n      next();\n      semicolon();\n      return finishNode(node, \"DebuggerStatement\");\n\n    case tt._do:\n      next();\n      node.body = parseStatement();\n      node.test = eat(tt._while) ? parseParenExpression() : dummyIdent();\n      semicolon();\n      return finishNode(node, \"DoWhileStatement\");\n\n    case tt._for:\n      next();\n      pushCx();\n      expect(tt.parenL);\n      if (token.type === tt.semi) return parseFor(node, null);\n      if (token.type === tt._var) {\n        var init = startNode();\n        next();\n        parseVar(init, true);\n        if (init.declarations.length === 1 && eat(tt._in))\n          return parseForIn(node, init);\n        return parseFor(node, init);\n      }\n      var init = parseExpression(false, true);\n      if (eat(tt._in)) {return parseForIn(node, checkLVal(init));}\n      return parseFor(node, init);\n\n    case tt._function:\n      next();\n      return parseFunction(node, true);\n\n    case tt._if:\n      next();\n      node.test = parseParenExpression();\n      node.consequent = parseStatement();\n      node.alternate = eat(tt._else) ? parseStatement() : null;\n      return finishNode(node, \"IfStatement\");\n\n    case tt._return:\n      next();\n      if (eat(tt.semi) || canInsertSemicolon()) node.argument = null;\n      else { node.argument = parseExpression(); semicolon(); }\n      return finishNode(node, \"ReturnStatement\");\n\n    case tt._switch:\n      var blockIndent = curIndent, line = curLineStart;\n      next();\n      node.discriminant = parseParenExpression();\n      node.cases = [];\n      pushCx();\n      expect(tt.braceL);\n\n      for (var cur; !closes(tt.braceR, blockIndent, line, true);) {\n        if (token.type === tt._case || token.type === tt._default) {\n          var isCase = token.type === tt._case;\n          if (cur) finishNode(cur, \"SwitchCase\");\n          node.cases.push(cur = startNode());\n          cur.consequent = [];\n          next();\n          if (isCase) cur.test = parseExpression();\n          else cur.test = null;\n          expect(tt.colon);\n        } else {\n          if (!cur) {\n            node.cases.push(cur = startNode());\n            cur.consequent = [];\n            cur.test = null;\n          }\n          cur.consequent.push(parseStatement());\n        }\n      }\n      if (cur) finishNode(cur, \"SwitchCase\");\n      popCx();\n      eat(tt.braceR);\n      return finishNode(node, \"SwitchStatement\");\n\n    case tt._throw:\n      next();\n      node.argument = parseExpression();\n      semicolon();\n      return finishNode(node, \"ThrowStatement\");\n\n    case tt._try:\n      next();\n      node.block = parseBlock();\n      node.handler = null;\n      if (token.type === tt._catch) {\n        var clause = startNode();\n        next();\n        expect(tt.parenL);\n        clause.param = parseIdent();\n        expect(tt.parenR);\n        clause.guard = null;\n        clause.body = parseBlock();\n        node.handler = finishNode(clause, \"CatchClause\");\n      }\n      node.finalizer = eat(tt._finally) ? parseBlock() : null;\n      if (!node.handler && !node.finalizer) return node.block;\n      return finishNode(node, \"TryStatement\");\n\n    case tt._var:\n      next();\n      node = parseVar(node);\n      semicolon();\n      return node;\n\n    case tt._while:\n      next();\n      node.test = parseParenExpression();\n      node.body = parseStatement();\n      return finishNode(node, \"WhileStatement\");\n\n    case tt._with:\n      next();\n      node.object = parseParenExpression();\n      node.body = parseStatement();\n      return finishNode(node, \"WithStatement\");\n\n    case tt.braceL:\n      return parseBlock();\n\n    case tt.semi:\n      next();\n      return finishNode(node, \"EmptyStatement\");\n\n    default:\n      var maybeName = token.value, expr = parseExpression();\n      if (isDummy(expr)) {\n        next();\n        if (token.type === tt.eof) return finishNode(node, \"EmptyStatement\");\n        return parseStatement();\n      } else if (starttype === tt.name && expr.type === \"Identifier\" && eat(tt.colon)) {\n        node.body = parseStatement();\n        node.label = expr;\n        return finishNode(node, \"LabeledStatement\");\n      } else {\n        node.expression = expr;\n        semicolon();\n        return finishNode(node, \"ExpressionStatement\");\n      }\n    }\n  }\n\n  function parseBlock() {\n    var node = startNode();\n    pushCx();\n    expect(tt.braceL);\n    var blockIndent = curIndent, line = curLineStart;\n    node.body = [];\n    while (!closes(tt.braceR, blockIndent, line, true))\n      node.body.push(parseStatement());\n    popCx();\n    eat(tt.braceR);\n    return finishNode(node, \"BlockStatement\");\n  }\n\n  function parseFor(node, init) {\n    node.init = init;\n    node.test = node.update = null;\n    if (eat(tt.semi) && token.type !== tt.semi) node.test = parseExpression();\n    if (eat(tt.semi) && token.type !== tt.parenR) node.update = parseExpression();\n    popCx();\n    expect(tt.parenR);\n    node.body = parseStatement();\n    return finishNode(node, \"ForStatement\");\n  }\n\n  function parseForIn(node, init) {\n    node.left = init;\n    node.right = parseExpression();\n    popCx();\n    expect(tt.parenR);\n    node.body = parseStatement();\n    return finishNode(node, \"ForInStatement\");\n  }\n\n  function parseVar(node, noIn) {\n    node.declarations = [];\n    node.kind = \"var\";\n    while (token.type === tt.name) {\n      var decl = startNode();\n      decl.id = parseIdent();\n      decl.init = eat(tt.eq) ? parseExpression(true, noIn) : null;\n      node.declarations.push(finishNode(decl, \"VariableDeclarator\"));\n      if (!eat(tt.comma)) break;\n    }\n    return finishNode(node, \"VariableDeclaration\");\n  }\n\n  function parseExpression(noComma, noIn) {\n    var expr = parseMaybeAssign(noIn);\n    if (!noComma && token.type === tt.comma) {\n      var node = startNodeFrom(expr);\n      node.expressions = [expr];\n      while (eat(tt.comma)) node.expressions.push(parseMaybeAssign(noIn));\n      return finishNode(node, \"SequenceExpression\");\n    }\n    return expr;\n  }\n\n  function parseParenExpression() {\n    pushCx();\n    expect(tt.parenL);\n    var val = parseExpression();\n    popCx();\n    expect(tt.parenR);\n    return val;\n  }\n\n  function parseMaybeAssign(noIn) {\n    var left = parseMaybeConditional(noIn);\n    if (token.type.isAssign) {\n      var node = startNodeFrom(left);\n      node.operator = token.value;\n      node.left = checkLVal(left);\n      next();\n      node.right = parseMaybeAssign(noIn);\n      return finishNode(node, \"AssignmentExpression\");\n    }\n    return left;\n  }\n\n  function parseMaybeConditional(noIn) {\n    var expr = parseExprOps(noIn);\n    if (eat(tt.question)) {\n      var node = startNodeFrom(expr);\n      node.test = expr;\n      node.consequent = parseExpression(true);\n      node.alternate = expect(tt.colon) ? parseExpression(true, noIn) : dummyIdent();\n      return finishNode(node, \"ConditionalExpression\");\n    }\n    return expr;\n  }\n\n  function parseExprOps(noIn) {\n    var indent = curIndent, line = curLineStart;\n    return parseExprOp(parseMaybeUnary(noIn), -1, noIn, indent, line);\n  }\n\n  function parseExprOp(left, minPrec, noIn, indent, line) {\n    if (curLineStart != line && curIndent < indent && tokenStartsLine()) return left;\n    var prec = token.type.binop;\n    if (prec != null && (!noIn || token.type !== tt._in)) {\n      if (prec > minPrec) {\n        var node = startNodeFrom(left);\n        node.left = left;\n        node.operator = token.value;\n        next();\n        if (curLineStart != line && curIndent < indent && tokenStartsLine())\n          node.right = dummyIdent();\n        else\n          node.right = parseExprOp(parseMaybeUnary(noIn), prec, noIn, indent, line);\n        var node = finishNode(node, /&&|\\|\\|/.test(node.operator) ? \"LogicalExpression\" : \"BinaryExpression\");\n        return parseExprOp(node, minPrec, noIn, indent, line);\n      }\n    }\n    return left;\n  }\n\n  function parseMaybeUnary(noIn) {\n    if (token.type.prefix) {\n      var node = startNode(), update = token.type.isUpdate;\n      node.operator = token.value;\n      node.prefix = true;\n      next();\n      node.argument = parseMaybeUnary(noIn);\n      if (update) node.argument = checkLVal(node.argument);\n      return finishNode(node, update ? \"UpdateExpression\" : \"UnaryExpression\");\n    }\n    var expr = parseExprSubscripts();\n    while (token.type.postfix && !canInsertSemicolon()) {\n      var node = startNodeFrom(expr);\n      node.operator = token.value;\n      node.prefix = false;\n      node.argument = checkLVal(expr);\n      next();\n      expr = finishNode(node, \"UpdateExpression\");\n    }\n    return expr;\n  }\n\n  function parseExprSubscripts() {\n    var indent = curIndent, line = curLineStart;\n    return parseSubscripts(parseExprAtom(), false, curIndent, line);\n  }\n\n  function parseSubscripts(base, noCalls, startIndent, line) {\n    for (;;) {\n      if (curLineStart != line && curIndent <= startIndent && tokenStartsLine()) {\n        if (token.type == tt.dot && curIndent == startIndent)\n          --startIndent;\n        else\n          return base;\n      }\n\n      if (eat(tt.dot)) {\n        var node = startNodeFrom(base);\n        node.object = base;\n        if (curLineStart != line && curIndent <= startIndent && tokenStartsLine())\n          node.property = dummyIdent();\n        else\n          node.property = parsePropertyName() || dummyIdent();\n        node.computed = false;\n        base = finishNode(node, \"MemberExpression\");\n      } else if (token.type == tt.bracketL) {\n        pushCx();\n        next();\n        var node = startNodeFrom(base);\n        node.object = base;\n        node.property = parseExpression();\n        node.computed = true;\n        popCx();\n        expect(tt.bracketR);\n        base = finishNode(node, \"MemberExpression\");\n      } else if (!noCalls && token.type == tt.parenL) {\n        pushCx();\n        var node = startNodeFrom(base);\n        node.callee = base;\n        node.arguments = parseExprList(tt.parenR);\n        base = finishNode(node, \"CallExpression\");\n      } else {\n        return base;\n      }\n    }\n  }\n\n  function parseExprAtom() {\n    switch (token.type) {\n    case tt._this:\n      var node = startNode();\n      next();\n      return finishNode(node, \"ThisExpression\");\n    case tt.name:\n      return parseIdent();\n    case tt.num: case tt.string: case tt.regexp:\n      var node = startNode();\n      node.value = token.value;\n      node.raw = input.slice(token.start, token.end);\n      next();\n      return finishNode(node, \"Literal\");\n\n    case tt._null: case tt._true: case tt._false:\n      var node = startNode();\n      node.value = token.type.atomValue;\n      node.raw = token.type.keyword;\n      next();\n      return finishNode(node, \"Literal\");\n\n    case tt.parenL:\n      var tokStart1 = token.start;\n      next();\n      var val = parseExpression();\n      val.start = tokStart1;\n      val.end = token.end;\n      expect(tt.parenR);\n      return val;\n\n    case tt.bracketL:\n      var node = startNode();\n      pushCx();\n      node.elements = parseExprList(tt.bracketR);\n      return finishNode(node, \"ArrayExpression\");\n\n    case tt.braceL:\n      return parseObj();\n\n    case tt._function:\n      var node = startNode();\n      next();\n      return parseFunction(node, false);\n\n    case tt._new:\n      return parseNew();\n\n    default:\n      return dummyIdent();\n    }\n  }\n\n  function parseNew() {\n    var node = startNode(), startIndent = curIndent, line = curLineStart;\n    next();\n    node.callee = parseSubscripts(parseExprAtom(), true, startIndent, line);\n    if (token.type == tt.parenL) {\n      pushCx();\n      node.arguments = parseExprList(tt.parenR);\n    } else {\n      node.arguments = [];\n    }\n    return finishNode(node, \"NewExpression\");\n  }\n\n  function parseObj() {\n    var node = startNode();\n    node.properties = [];\n    pushCx();\n    next();\n    var propIndent = curIndent, line = curLineStart;\n    while (!closes(tt.braceR, propIndent, line)) {\n      var name = parsePropertyName();\n      if (!name) { if (isDummy(parseExpression(true))) next(); eat(tt.comma); continue; }\n      var prop = {key: name}, isGetSet = false, kind;\n      if (eat(tt.colon)) {\n        prop.value = parseExpression(true);\n        kind = prop.kind = \"init\";\n      } else if (options.ecmaVersion >= 5 && prop.key.type === \"Identifier\" &&\n                 (prop.key.name === \"get\" || prop.key.name === \"set\")) {\n        isGetSet = true;\n        kind = prop.kind = prop.key.name;\n        prop.key = parsePropertyName() || dummyIdent();\n        prop.value = parseFunction(startNode(), false);\n      } else {\n        next();\n        eat(tt.comma);\n        continue;\n      }\n\n      node.properties.push(prop);\n      eat(tt.comma);\n    }\n    popCx();\n    eat(tt.braceR);\n    return finishNode(node, \"ObjectExpression\");\n  }\n\n  function parsePropertyName() {\n    if (token.type === tt.num || token.type === tt.string) return parseExprAtom();\n    if (token.type === tt.name || token.type.keyword) return parseIdent();\n  }\n\n  function parseIdent() {\n    var node = startNode();\n    node.name = token.type === tt.name ? token.value : token.type.keyword;\n    next();\n    return finishNode(node, \"Identifier\");\n  }\n\n  function parseFunction(node, isStatement) {\n    if (token.type === tt.name) node.id = parseIdent();\n    else if (isStatement) node.id = dummyIdent();\n    else node.id = null;\n    node.params = [];\n    pushCx();\n    expect(tt.parenL);\n    while (token.type == tt.name) {\n      node.params.push(parseIdent());\n      eat(tt.comma);\n    }\n    popCx();\n    eat(tt.parenR);\n    node.body = parseBlock();\n    return finishNode(node, isStatement ? \"FunctionDeclaration\" : \"FunctionExpression\");\n  }\n\n  function parseExprList(close) {\n    var indent = curIndent, line = curLineStart, elts = [], continuedLine = nextLineStart;\n    next(); // Opening bracket\n    while (!closes(close, indent + (curLineStart <= continuedLine ? 1 : 0), line)) {\n      var elt = parseExpression(true);\n      if (isDummy(elt)) {\n        if (closes(close, indent, line)) break;\n        next();\n      } else {\n        elts.push(elt);\n      }\n      while (eat(tt.comma)) {}\n    }\n    popCx();\n    eat(close);\n    return elts;\n  }\n});\n"
  },
  {
    "path": "client/js/lib/codemirror-compressed.js",
    "content": "window.CodeMirror=function(){\"use strict\";function z(a,c){if(!(this instanceof z))return new z(a,c);this.options=c=c||{};for(var d in fd)!c.hasOwnProperty(d)&&fd.hasOwnProperty(d)&&(c[d]=fd[d]);M(c);var e=\"string\"==typeof c.value?0:c.value.first,f=this.display=A(a,e);f.wrapper.CodeMirror=this,J(this),c.autofocus&&!r&&Qb(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,draggingText:!1,highlight:new jf},H(this),c.lineWrapping&&(this.display.wrapper.className+=\" CodeMirror-wrap\");var g=c.value;\"string\"==typeof g&&(g=new te(c.value,c.mode)),Ib(this,xe)(this,g),b&&setTimeout(tf(Pb,this,!0),20),Tb(this);var h;try{h=document.activeElement==f.input}catch(i){}h||c.autofocus&&!r?setTimeout(tf(rc,this),20):sc(this),Ib(this,function(){for(var a in ed)ed.propertyIsEnumerable(a)&&ed[a](this,c[a],hd);for(var b=0;b<ld.length;++b)ld[b](this)})()}function A(a,b){var d={},e=d.input=zf(\"textarea\",null,null,\"position: absolute; padding: 0; width: 1px; height: 1em; outline: none\");return h?e.style.width=\"1000px\":e.setAttribute(\"wrap\",\"off\"),q&&(e.style.border=\"1px solid black\"),e.setAttribute(\"autocorrect\",\"off\"),e.setAttribute(\"autocapitalize\",\"off\"),e.setAttribute(\"spellcheck\",\"false\"),d.inputDiv=zf(\"div\",[e],null,\"overflow: hidden; position: relative; width: 3px; height: 0px;\"),d.scrollbarH=zf(\"div\",[zf(\"div\",null,null,\"height: 1px\")],\"CodeMirror-hscrollbar\"),d.scrollbarV=zf(\"div\",[zf(\"div\",null,null,\"width: 1px\")],\"CodeMirror-vscrollbar\"),d.scrollbarFiller=zf(\"div\",null,\"CodeMirror-scrollbar-filler\"),d.gutterFiller=zf(\"div\",null,\"CodeMirror-gutter-filler\"),d.lineDiv=zf(\"div\",null,\"CodeMirror-code\"),d.selectionDiv=zf(\"div\",null,null,\"position: relative; z-index: 1\"),d.cursor=zf(\"div\",\"\\xa0\",\"CodeMirror-cursor\"),d.otherCursor=zf(\"div\",\"\\xa0\",\"CodeMirror-cursor CodeMirror-secondarycursor\"),d.measure=zf(\"div\",null,\"CodeMirror-measure\"),d.lineSpace=zf(\"div\",[d.measure,d.selectionDiv,d.lineDiv,d.cursor,d.otherCursor],null,\"position: relative; outline: none\"),d.mover=zf(\"div\",[zf(\"div\",[d.lineSpace],\"CodeMirror-lines\")],null,\"position: relative\"),d.sizer=zf(\"div\",[d.mover],\"CodeMirror-sizer\"),d.heightForcer=zf(\"div\",null,null,\"position: absolute; height: \"+gf+\"px; width: 1px;\"),d.gutters=zf(\"div\",null,\"CodeMirror-gutters\"),d.lineGutter=null,d.scroller=zf(\"div\",[d.sizer,d.heightForcer,d.gutters],\"CodeMirror-scroll\"),d.scroller.setAttribute(\"tabIndex\",\"-1\"),d.wrapper=zf(\"div\",[d.inputDiv,d.scrollbarH,d.scrollbarV,d.scrollbarFiller,d.gutterFiller,d.scroller],\"CodeMirror\"),c&&(d.gutters.style.zIndex=-1,d.scroller.style.paddingRight=0),a.appendChild?a.appendChild(d.wrapper):a(d.wrapper),q&&(e.style.width=\"0px\"),h||(d.scroller.draggable=!0),m?(d.inputDiv.style.height=\"1px\",d.inputDiv.style.position=\"absolute\"):c&&(d.scrollbarH.style.minWidth=d.scrollbarV.style.minWidth=\"18px\"),d.viewOffset=d.lastSizeC=0,d.showingFrom=d.showingTo=b,d.lineNumWidth=d.lineNumInnerWidth=d.lineNumChars=null,d.prevInput=\"\",d.alignWidgets=!1,d.pollingFast=!1,d.poll=new jf,d.cachedCharWidth=d.cachedTextHeight=d.cachedPaddingH=null,d.measureLineCache=[],d.measureLineCachePos=0,d.inaccurateSelection=!1,d.maxLine=null,d.maxLineLength=0,d.maxLineChanged=!1,d.wheelDX=d.wheelDY=d.wheelStartX=d.wheelStartY=null,d}function B(a){a.doc.mode=z.getMode(a.options,a.doc.modeOption),C(a)}function C(a){a.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),a.doc.frontier=a.doc.first,eb(a,100),a.state.modeGen++,a.curOp&&Lb(a)}function D(a){a.options.lineWrapping?(a.display.wrapper.className+=\" CodeMirror-wrap\",a.display.sizer.style.minWidth=\"\"):(a.display.wrapper.className=a.display.wrapper.className.replace(\" CodeMirror-wrap\",\"\"),L(a)),F(a),Lb(a),sb(a),setTimeout(function(){N(a)},100)}function E(a){var b=Db(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/Eb(a.display)-3);return function(e){return Sd(a.doc,e)?0:c?(Math.ceil(e.text.length/d)||1)*b:b}}function F(a){var b=a.doc,c=E(a);b.iter(function(a){var b=c(a);b!=a.height&&Be(a,b)})}function G(a){var b=qd[a.options.keyMap],c=b.style;a.display.wrapper.className=a.display.wrapper.className.replace(/\\s*cm-keymap-\\S+/g,\"\")+(c?\" cm-keymap-\"+c:\"\")}function H(a){a.display.wrapper.className=a.display.wrapper.className.replace(/\\s*cm-s-\\S+/g,\"\")+a.options.theme.replace(/(^|\\s)\\s*/g,\" cm-s-\"),sb(a)}function I(a){J(a),Lb(a),setTimeout(function(){P(a)},20)}function J(a){var b=a.display.gutters,c=a.options.gutters;Af(b);for(var d=0;d<c.length;++d){var e=c[d],f=b.appendChild(zf(\"div\",null,\"CodeMirror-gutter \"+e));\"CodeMirror-linenumbers\"==e&&(a.display.lineGutter=f,f.style.width=(a.display.lineNumWidth||1)+\"px\")}b.style.display=d?\"\":\"none\"}function K(a,b){if(0==b.height)return 0;for(var d,c=b.text.length,e=b;d=Od(e);){var f=d.find();e=ye(a,f.from.line),c+=f.from.ch-f.to.ch}for(e=b;d=Pd(e);){var f=d.find();c-=e.text.length-f.from.ch,e=ye(a,f.to.line),c+=e.text.length-f.to.ch}return c}function L(a){var b=a.display,c=a.doc;b.maxLine=ye(c,c.first),b.maxLineLength=K(c,b.maxLine),b.maxLineChanged=!0,c.iter(function(a){var d=K(c,a);d>b.maxLineLength&&(b.maxLineLength=d,b.maxLine=a)})}function M(a){var b=pf(a.gutters,\"CodeMirror-linenumbers\");-1==b&&a.lineNumbers?a.gutters=a.gutters.concat([\"CodeMirror-linenumbers\"]):b>-1&&!a.lineNumbers&&(a.gutters=a.gutters.slice(0),a.gutters.splice(b,1))}function N(a){var b=a.display,c=a.doc.height,d=c+jb(b);b.sizer.style.minHeight=b.heightForcer.style.top=d+\"px\",b.gutters.style.height=Math.max(d,b.scroller.clientHeight-gf)+\"px\";var e=Math.max(d,b.scroller.scrollHeight),f=b.scroller.scrollWidth>b.scroller.clientWidth+1,g=e>b.scroller.clientHeight+1;g?(b.scrollbarV.style.display=\"block\",b.scrollbarV.style.bottom=f?Hf(b.measure)+\"px\":\"0\",b.scrollbarV.firstChild.style.height=Math.max(0,e-b.scroller.clientHeight+b.scrollbarV.clientHeight)+\"px\"):(b.scrollbarV.style.display=\"\",b.scrollbarV.firstChild.style.height=\"0\"),f?(b.scrollbarH.style.display=\"block\",b.scrollbarH.style.right=g?Hf(b.measure)+\"px\":\"0\",b.scrollbarH.firstChild.style.width=b.scroller.scrollWidth-b.scroller.clientWidth+b.scrollbarH.clientWidth+\"px\"):(b.scrollbarH.style.display=\"\",b.scrollbarH.firstChild.style.width=\"0\"),f&&g?(b.scrollbarFiller.style.display=\"block\",b.scrollbarFiller.style.height=b.scrollbarFiller.style.width=Hf(b.measure)+\"px\"):b.scrollbarFiller.style.display=\"\",f&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(b.gutterFiller.style.display=\"block\",b.gutterFiller.style.height=Hf(b.measure)+\"px\",b.gutterFiller.style.width=b.gutters.offsetWidth+\"px\"):b.gutterFiller.style.display=\"\",n&&0===Hf(b.measure)&&(b.scrollbarV.style.minWidth=b.scrollbarH.style.minHeight=o?\"18px\":\"12px\",b.scrollbarV.style.pointerEvents=b.scrollbarH.style.pointerEvents=\"none\")}function O(a,b,c){var d=a.scroller.scrollTop,e=a.wrapper.clientHeight;\"number\"==typeof c?d=c:c&&(d=c.top,e=c.bottom-c.top),d=Math.floor(d-ib(a));var f=Math.ceil(d+e);return{from:De(b,d),to:De(b,f)}}function P(a){var b=a.display;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var c=S(b)-b.scroller.scrollLeft+a.doc.scrollLeft,d=b.gutters.offsetWidth,e=c+\"px\",f=b.lineDiv.firstChild;f;f=f.nextSibling)if(f.alignable)for(var g=0,h=f.alignable;g<h.length;++g)h[g].style.left=e;a.options.fixedGutter&&(b.gutters.style.left=c+d+\"px\")}}function Q(a){if(!a.options.lineNumbers)return!1;var b=a.doc,c=R(a.options,b.first+b.size-1),d=a.display;if(c.length!=d.lineNumChars){var e=d.measure.appendChild(zf(\"div\",[zf(\"div\",c)],\"CodeMirror-linenumber CodeMirror-gutter-elt\")),f=e.firstChild.offsetWidth,g=e.offsetWidth-f;return d.lineGutter.style.width=\"\",d.lineNumInnerWidth=Math.max(f,d.lineGutter.offsetWidth-g),d.lineNumWidth=d.lineNumInnerWidth+g,d.lineNumChars=d.lineNumInnerWidth?c.length:-1,d.lineGutter.style.width=d.lineNumWidth+\"px\",!0}return!1}function R(a,b){return String(a.lineNumberFormatter(b+a.firstLineNumber))}function S(a){return Df(a.scroller).left-Df(a.sizer).left}function T(a,b,c,d){for(var g,e=a.display.showingFrom,f=a.display.showingTo,h=O(a.display,a.doc,c),i=!0;;i=!1){var j=a.display.scroller.clientWidth;if(!U(a,b,h,d))break;if(g=!0,b=[],ab(a),N(a),i&&a.options.lineWrapping&&j!=a.display.scroller.clientWidth)d=!0;else if(d=!1,c&&(c=Math.min(a.display.scroller.scrollHeight-a.display.scroller.clientHeight,\"number\"==typeof c?c:c.top)),h=O(a.display,a.doc,c),h.from>=a.display.showingFrom&&h.to<=a.display.showingTo)break}return g&&(bf(a,\"update\",a),(a.display.showingFrom!=e||a.display.showingTo!=f)&&bf(a,\"viewportChange\",a,a.display.showingFrom,a.display.showingTo)),g}function U(a,b,c,d){var e=a.display,f=a.doc;if(!e.wrapper.offsetWidth)return e.showingFrom=e.showingTo=f.first,e.viewOffset=0,void 0;if(!(!d&&0==b.length&&c.from>e.showingFrom&&c.to<e.showingTo)){Q(a)&&(b=[{from:f.first,to:f.first+f.size}]);var g=e.sizer.style.marginLeft=e.gutters.offsetWidth+\"px\";e.scrollbarH.style.left=a.options.fixedGutter?g:\"0\";var h=1/0;if(a.options.lineNumbers)for(var i=0;i<b.length;++i)b[i].diff&&b[i].from<h&&(h=b[i].from);var j=f.first+f.size,k=Math.max(c.from-a.options.viewportMargin,f.first),l=Math.min(j,c.to+a.options.viewportMargin);if(e.showingFrom<k&&k-e.showingFrom<20&&(k=Math.max(f.first,e.showingFrom)),e.showingTo>l&&e.showingTo-l<20&&(l=Math.min(j,e.showingTo)),y)for(k=Ce(Rd(f,ye(f,k)));j>l&&Sd(f,ye(f,l));)++l;var m=[{from:Math.max(e.showingFrom,f.first),to:Math.min(e.showingTo,j)}];if(m=m[0].from>=m[0].to?[]:X(m,b),y)for(var i=0;i<m.length;++i)for(var o,n=m[i];o=Pd(ye(f,n.to-1));){var p=o.find().from.line;if(!(p>n.from)){m.splice(i--,1);break}n.to=p}for(var q=0,i=0;i<m.length;++i){var n=m[i];n.from<k&&(n.from=k),n.to>l&&(n.to=l),n.from>=n.to?m.splice(i--,1):q+=n.to-n.from}if(!d&&q==l-k&&k==e.showingFrom&&l==e.showingTo)return W(a),void 0;m.sort(function(a,b){return a.from-b.from});try{var r=document.activeElement}catch(s){}.7*(l-k)>q&&(e.lineDiv.style.display=\"none\"),Z(a,k,l,m,h),e.lineDiv.style.display=\"\",r&&document.activeElement!=r&&r.offsetHeight&&r.focus();var t=k!=e.showingFrom||l!=e.showingTo||e.lastSizeC!=e.wrapper.clientHeight;return t&&(e.lastSizeC=e.wrapper.clientHeight,eb(a,400)),e.showingFrom=k,e.showingTo=l,e.gutters.style.height=\"\",V(a),W(a),!0}}function V(a){for(var f,b=a.display,d=b.lineDiv.offsetTop,e=b.lineDiv.firstChild;e;e=e.nextSibling)if(e.lineObj){if(c){var g=e.offsetTop+e.offsetHeight;f=g-d,d=g}else{var h=Df(e);f=h.bottom-h.top}var i=e.lineObj.height-f;if(2>f&&(f=Db(b)),i>.001||-.001>i){Be(e.lineObj,f);var j=e.lineObj.widgets;if(j)for(var k=0;k<j.length;++k)j[k].height=j[k].node.offsetHeight}}}function W(a){var b=a.display.viewOffset=Ee(a,ye(a.doc,a.display.showingFrom));a.display.mover.style.top=b+\"px\"}function X(a,b){for(var c=0,d=b.length||0;d>c;++c){for(var e=b[c],f=[],g=e.diff||0,h=0,i=a.length;i>h;++h){var j=a[h];e.to<=j.from&&e.diff?f.push({from:j.from+g,to:j.to+g}):e.to<=j.from||e.from>=j.to?f.push(j):(e.from>j.from&&f.push({from:j.from,to:e.from}),e.to<j.to&&f.push({from:e.to+g,to:j.to+g}))}a=f}return a}function Y(a){for(var b=a.display,c={},d={},e=b.gutters.firstChild,f=0;e;e=e.nextSibling,++f)c[a.options.gutters[f]]=e.offsetLeft,d[a.options.gutters[f]]=e.offsetWidth;return{fixedPos:S(b),gutterTotalWidth:b.gutters.offsetWidth,gutterLeft:c,gutterWidth:d,wrapperWidth:b.wrapper.clientWidth}}function Z(a,b,c,d,e){function l(b){var c=b.nextSibling;return h&&s&&a.display.currentWheelTarget==b?(b.style.display=\"none\",b.lineObj=null):b.parentNode.removeChild(b),c}var f=Y(a),g=a.display,i=a.options.lineNumbers;d.length||h&&a.display.currentWheelTarget||Af(g.lineDiv);var j=g.lineDiv,k=j.firstChild,m=d.shift(),n=b;for(a.doc.iter(b,c,function(b){if(m&&m.to==n&&(m=d.shift()),Sd(a.doc,b)){if(0!=b.height&&Be(b,0),b.widgets&&k&&k.previousSibling)for(var c=0;c<b.widgets.length;++c){var g=b.widgets[c];if(g.showIfHidden){var h=k.previousSibling;if(/pre/i.test(h.nodeName)){var o=zf(\"div\",null,null,\"position: relative\");h.parentNode.replaceChild(o,h),o.appendChild(h),h=o}var p=h.appendChild(zf(\"div\",[g.node],\"CodeMirror-linewidget\"));g.handleMouseEvents||(p.ignoreEvents=!0),_(g,p,h,f)}}}else if(m&&m.from<=n&&m.to>n){for(;k.lineObj!=b;)k=l(k);i&&n>=e&&k.lineNumber&&Cf(k.lineNumber,R(a.options,n)),k=k.nextSibling}else{if(b.widgets)for(var s,q=0,r=k;r&&20>q;++q,r=r.nextSibling)if(r.lineObj==b&&/div/i.test(r.nodeName)){s=r;break}var t=$(a,b,n,f,s);if(t!=s)j.insertBefore(t,k);else{for(;k!=s;)k=l(k);k=k.nextSibling}t.lineObj=b}++n});k;)k=l(k)}function $(a,b,d,e,f){var k,g=ie(a,b),h=g.pre,i=b.gutterMarkers,j=a.display,l=g.bgClass?g.bgClass+\" \"+(b.bgClass||\"\"):b.bgClass;if(!(a.options.lineNumbers||i||l||b.wrapClass||b.widgets))return h;if(f){f.alignable=null;for(var q,m=!0,n=0,o=null,p=f.firstChild;p;p=q)if(q=p.nextSibling,/\\bCodeMirror-linewidget\\b/.test(p.className)){for(var r=0;r<b.widgets.length;++r){var s=b.widgets[r];if(s.node==p.firstChild){s.above||o||(o=p),_(s,p,f,e),++n;break}}if(r==b.widgets.length){m=!1;break}}else f.removeChild(p);f.insertBefore(h,o),m&&n==b.widgets.length&&(k=f,f.className=b.wrapClass||\"\")}if(k||(k=zf(\"div\",null,b.wrapClass,\"position: relative\"),k.appendChild(h)),l&&k.insertBefore(zf(\"div\",null,l+\" CodeMirror-linebackground\"),k.firstChild),a.options.lineNumbers||i){var t=k.insertBefore(zf(\"div\",null,\"CodeMirror-gutter-wrapper\",\"position: absolute; left: \"+(a.options.fixedGutter?e.fixedPos:-e.gutterTotalWidth)+\"px\"),h);if(a.options.fixedGutter&&(k.alignable||(k.alignable=[])).push(t),!a.options.lineNumbers||i&&i[\"CodeMirror-linenumbers\"]||(k.lineNumber=t.appendChild(zf(\"div\",R(a.options,d),\"CodeMirror-linenumber CodeMirror-gutter-elt\",\"left: \"+e.gutterLeft[\"CodeMirror-linenumbers\"]+\"px; width: \"+j.lineNumInnerWidth+\"px\"))),i)for(var u=0;u<a.options.gutters.length;++u){var v=a.options.gutters[u],w=i.hasOwnProperty(v)&&i[v];w&&t.appendChild(zf(\"div\",[w],\"CodeMirror-gutter-elt\",\"left: \"+e.gutterLeft[v]+\"px; width: \"+e.gutterWidth[v]+\"px\"))}}if(c&&(k.style.zIndex=2),b.widgets&&k!=f)for(var r=0,x=b.widgets;r<x.length;++r){var s=x[r],y=zf(\"div\",[s.node],\"CodeMirror-linewidget\");s.handleMouseEvents||(y.ignoreEvents=!0),_(s,y,k,e),s.above?k.insertBefore(y,a.options.lineNumbers&&0!=b.height?t:h):k.appendChild(y),bf(s,\"redraw\")}return k}function _(a,b,c,d){if(a.noHScroll){(c.alignable||(c.alignable=[])).push(b);var e=d.wrapperWidth;b.style.left=d.fixedPos+\"px\",a.coverGutter||(e-=d.gutterTotalWidth,b.style.paddingLeft=d.gutterTotalWidth+\"px\"),b.style.width=e+\"px\"}a.coverGutter&&(b.style.zIndex=5,b.style.position=\"relative\",a.noHScroll||(b.style.marginLeft=-d.gutterTotalWidth+\"px\"))}function ab(a){var b=a.display,c=Hc(a.doc.sel.from,a.doc.sel.to);if(c||a.options.showCursorWhenSelecting?bb(a):b.cursor.style.display=b.otherCursor.style.display=\"none\",c?b.selectionDiv.style.display=\"none\":cb(a),a.options.moveInputWithCursor){var d=yb(a,a.doc.sel.head,\"div\"),e=Df(b.wrapper),f=Df(b.lineDiv);b.inputDiv.style.top=Math.max(0,Math.min(b.wrapper.clientHeight-10,d.top+f.top-e.top))+\"px\",b.inputDiv.style.left=Math.max(0,Math.min(b.wrapper.clientWidth-10,d.left+f.left-e.left))+\"px\"}}function bb(a){var b=a.display,c=yb(a,a.doc.sel.head,\"div\");b.cursor.style.left=c.left+\"px\",b.cursor.style.top=c.top+\"px\",b.cursor.style.height=Math.max(0,c.bottom-c.top)*a.options.cursorHeight+\"px\",b.cursor.style.display=\"\",c.other?(b.otherCursor.style.display=\"\",b.otherCursor.style.left=c.other.left+\"px\",b.otherCursor.style.top=c.other.top+\"px\",b.otherCursor.style.height=.85*(c.other.bottom-c.other.top)+\"px\"):b.otherCursor.style.display=\"none\"}function cb(a){function i(a,b,c,d){0>b&&(b=0),e.appendChild(zf(\"div\",null,\"CodeMirror-selected\",\"position: absolute; left: \"+a+\"px; top: \"+b+\"px; width: \"+(null==c?h-a:c)+\"px; height: \"+(d-b)+\"px\"))}function j(b,d,e){function m(c,d){return xb(a,Gc(b,c),\"div\",f,d)}var k,l,f=ye(c,b),j=f.text.length;return Of(Fe(f),d||0,null==e?j:e,function(a,b,c){var n,o,p,f=m(a,\"left\");if(a==b)n=f,o=p=f.left;else{if(n=m(b-1,\"right\"),\"rtl\"==c){var q=f;f=n,n=q}o=f.left,p=n.right}null==d&&0==a&&(o=g),n.top-f.top>3&&(i(o,f.top,null,f.bottom),o=g,f.bottom<n.top&&i(o,f.bottom,null,n.top)),null==e&&b==j&&(p=h),(!k||f.top<k.top||f.top==k.top&&f.left<k.left)&&(k=f),(!l||n.bottom>l.bottom||n.bottom==l.bottom&&n.right>l.right)&&(l=n),g+1>o&&(o=g),i(o,n.top,p-o,n.bottom)}),{start:k,end:l}}var b=a.display,c=a.doc,d=a.doc.sel,e=document.createDocumentFragment(),f=kb(a.display),g=f.left,h=b.lineSpace.offsetWidth-f.right;if(d.from.line==d.to.line)j(d.from.line,d.from.ch,d.to.ch);else{var k=ye(c,d.from.line),l=ye(c,d.to.line),m=Rd(c,k)==Rd(c,l),n=j(d.from.line,d.from.ch,m?k.text.length:null).end,o=j(d.to.line,m?0:null,d.to.ch).start;m&&(n.top<o.top-2?(i(n.right,n.top,null,n.bottom),i(g,o.top,o.left,o.bottom)):i(n.right,n.top,o.left-n.right,n.bottom)),n.bottom<o.top&&i(g,n.bottom,null,o.top)}Bf(b.selectionDiv,e),b.selectionDiv.style.display=\"\"}function db(a){if(a.state.focused){var b=a.display;clearInterval(b.blinker);var c=!0;b.cursor.style.visibility=b.otherCursor.style.visibility=\"\",a.options.cursorBlinkRate>0&&(b.blinker=setInterval(function(){b.cursor.style.visibility=b.otherCursor.style.visibility=(c=!c)?\"\":\"hidden\"},a.options.cursorBlinkRate))}}function eb(a,b){a.doc.mode.startState&&a.doc.frontier<a.display.showingTo&&a.state.highlight.set(b,tf(fb,a))}function fb(a){var b=a.doc;if(b.frontier<b.first&&(b.frontier=b.first),!(b.frontier>=a.display.showingTo)){var f,c=+new Date+a.options.workTime,d=nd(b.mode,hb(a,b.frontier)),e=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.showingTo+500),function(g){if(b.frontier>=a.display.showingFrom){var h=g.styles;g.styles=ce(a,g,d,!0);for(var i=!h||h.length!=g.styles.length,j=0;!i&&j<h.length;++j)i=h[j]!=g.styles[j];i&&(f&&f.end==b.frontier?f.end++:e.push(f={start:b.frontier,end:b.frontier+1})),g.stateAfter=nd(b.mode,d)}else ee(a,g.text,d),g.stateAfter=0==b.frontier%5?nd(b.mode,d):null;return++b.frontier,+new Date>c?(eb(a,a.options.workDelay),!0):void 0}),e.length&&Ib(a,function(){for(var a=0;a<e.length;++a)Lb(this,e[a].start,e[a].end)})()}}function gb(a,b,c){for(var d,e,f=a.doc,g=c?-1:b-(a.doc.mode.innerMode?1e3:100),h=b;h>g;--h){if(h<=f.first)return f.first;var i=ye(f,h-1);if(i.stateAfter&&(!c||h<=f.frontier))return h;var j=kf(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=h-1,d=j)}return e}function hb(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=gb(a,b,c),g=f>d.first&&ye(d,f-1).stateAfter;return g=g?nd(d.mode,g):od(d.mode),d.iter(f,b,function(c){ee(a,c.text,g);var h=f==b-1||0==f%5||f>=e.showingFrom&&f<e.showingTo;c.stateAfter=h?nd(d.mode,g):null,++f}),c&&(d.frontier=f),g}function ib(a){return a.lineSpace.offsetTop}function jb(a){return a.mover.offsetHeight-a.lineSpace.offsetHeight}function kb(a){if(a.cachedPaddingH)return a.cachedPaddingH;var b=Bf(a.measure,zf(\"pre\",\"x\")),c=window.getComputedStyle?window.getComputedStyle(b):b.currentStyle;return a.cachedPaddingH={left:parseInt(c.paddingLeft),right:parseInt(c.paddingRight)}}function lb(a,b,c,d,e){var f=-1;if(d=d||ob(a,b),d.crude){var g=d.left+c*d.width;return{left:g,right:g+d.width,top:d.top,bottom:d.bottom}}for(var h=c;;h+=f){var i=d[h];if(i)break;0>f&&0==h&&(f=1)}return e=h>c?\"left\":c>h?\"right\":e,\"left\"==e&&i.leftSide?i=i.leftSide:\"right\"==e&&i.rightSide&&(i=i.rightSide),{left:c>h?i.right:i.left,right:h>c?i.left:i.right,top:i.top,bottom:i.bottom}}function mb(a,b){for(var c=a.display.measureLineCache,d=0;d<c.length;++d){var e=c[d];if(e.text==b.text&&e.markedSpans==b.markedSpans&&a.display.scroller.clientWidth==e.width&&e.classes==b.textClass+\"|\"+b.wrapClass)return e}}function nb(a,b){var c=mb(a,b);c&&(c.text=c.measure=c.markedSpans=null)}function ob(a,b){var c=mb(a,b);if(c)return c.measure;var d=pb(a,b),e=a.display.measureLineCache,f={text:b.text,width:a.display.scroller.clientWidth,markedSpans:b.markedSpans,measure:d,classes:b.textClass+\"|\"+b.wrapClass};return 16==e.length?e[++a.display.measureLineCachePos%16]=f:e.push(f),d}function pb(a,e){function t(a){var b=a.top-p.top,c=a.bottom-p.top;c>s&&(c=s),0>b&&(b=0);for(var d=q.length-2;d>=0;d-=2){var e=q[d],f=q[d+1];if(!(e>c||b>f)&&(b>=e&&f>=c||e>=b&&c>=f||Math.min(c,f)-Math.max(b,e)>=c-b>>1)){q[d]=Math.min(b,e),q[d+1]=Math.max(c,f);break}}return 0>d&&(d=q.length,q.push(b,c)),{left:a.left-p.left,right:a.right-p.left,top:d,bottom:null}}function u(a){a.bottom=q[a.top+1],a.top=q[a.top]}if(!a.options.lineWrapping&&e.text.length>=a.options.crudeMeasuringFrom)return qb(a,e);var f=a.display,g=sf(e.text.length),h=ie(a,e,g,!0).pre;if(b&&!c&&!a.options.lineWrapping&&h.childNodes.length>100){for(var i=document.createDocumentFragment(),j=10,k=h.childNodes.length,l=0,m=Math.ceil(k/j);m>l;++l){for(var n=zf(\"div\",null,null,\"display: inline-block\"),o=0;j>o&&k;++o)n.appendChild(h.firstChild),--k;i.appendChild(n)}h.appendChild(i)}Bf(f.measure,h);var p=Df(f.lineDiv),q=[],r=sf(e.text.length),s=h.offsetHeight;d&&f.measure.first!=h&&Bf(f.measure,h);for(var v,l=0;l<g.length;++l)if(v=g[l]){var w=v,x=null;if(/\\bCodeMirror-widget\\b/.test(v.className)&&v.getClientRects){1==v.firstChild.nodeType&&(w=v.firstChild);var y=w.getClientRects();y.length>1&&(x=r[l]=t(y[0]),x.rightSide=t(y[y.length-1]))}x||(x=r[l]=t(Df(w))),v.measureRight&&(x.right=Df(v.measureRight).left-p.left),v.leftSide&&(x.leftSide=t(Df(v.leftSide)))}Af(a.display.measure);for(var v,l=0;l<r.length;++l)(v=r[l])&&(u(v),v.leftSide&&u(v.leftSide),v.rightSide&&u(v.rightSide));return r}function qb(a,b){var c=new $d(b.text.slice(0,100),null);b.textClass&&(c.textClass=b.textClass);var d=pb(a,c),e=lb(a,c,0,d,\"left\"),f=lb(a,c,99,d,\"right\");return{crude:!0,top:e.top,left:e.left,bottom:e.bottom,width:(f.right-e.left)/100}}function rb(a,b){var c=!1;if(b.markedSpans)for(var d=0;d<b.markedSpans;++d){var e=b.markedSpans[d];!e.collapsed||null!=e.to&&e.to!=b.text.length||(c=!0)}var f=!c&&mb(a,b);if(f||b.text.length>=a.options.crudeMeasuringFrom)return lb(a,b,b.text.length,f&&f.measure,\"right\").right;var g=ie(a,b,null,!0).pre,h=g.appendChild(Jf(a.display.measure));return Bf(a.display.measure,g),Df(h).right-Df(a.display.lineDiv).left}function sb(a){a.display.measureLineCache.length=a.display.measureLineCachePos=0,a.display.cachedCharWidth=a.display.cachedTextHeight=a.display.cachedPaddingH=null,a.options.lineWrapping||(a.display.maxLineChanged=!0),a.display.lineNumChars=null}function tb(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function ub(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function vb(a,b,c,d){if(b.widgets)for(var e=0;e<b.widgets.length;++e)if(b.widgets[e].above){var f=Yd(b.widgets[e]);c.top+=f,c.bottom+=f}if(\"line\"==d)return c;d||(d=\"local\");var g=Ee(a,b);if(\"local\"==d?g+=ib(a.display):g-=a.display.viewOffset,\"page\"==d||\"window\"==d){var h=Df(a.display.lineSpace);g+=h.top+(\"window\"==d?0:ub());var i=h.left+(\"window\"==d?0:tb());c.left+=i,c.right+=i}return c.top+=g,c.bottom+=g,c}function wb(a,b,c){if(\"div\"==c)return b;var d=b.left,e=b.top;if(\"page\"==c)d-=tb(),e-=ub();else if(\"local\"==c||!c){var f=Df(a.display.sizer);d+=f.left,e+=f.top}var g=Df(a.display.lineSpace);return{left:d-g.left,top:e-g.top}}function xb(a,b,c,d,e){return d||(d=ye(a.doc,b.line)),vb(a,d,lb(a,d,b.ch,null,e),c)}function yb(a,b,c,d,e){function f(b,f){var g=lb(a,d,b,e,f?\"right\":\"left\");return f?g.left=g.right:g.right=g.left,vb(a,d,g,c)}function g(a,b){var c=h[b],d=c.level%2;return a==Pf(c)&&b&&c.level<h[b-1].level?(c=h[--b],a=Qf(c)-(c.level%2?0:1),d=!0):a==Qf(c)&&b<h.length-1&&c.level<h[b+1].level&&(c=h[++b],a=Pf(c)-c.level%2,d=!1),d&&a==c.to&&a>c.from?f(a-1):f(a,d)}d=d||ye(a.doc,b.line),e||(e=ob(a,d));var h=Fe(d),i=b.ch;if(!h)return f(i);var j=Xf(h,i),k=g(i,j);return null!=Wf&&(k.other=g(i,Wf)),k}function zb(a,b,c,d){var e=new Gc(a,b);return e.xRel=d,c&&(e.outside=!0),e}function Ab(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return zb(d.first,0,!0,-1);var e=De(d,c),f=d.first+d.size-1;if(e>f)return zb(d.first+d.size-1,ye(d,f).text.length,!0,1);for(0>b&&(b=0);;){var g=ye(d,e),h=Bb(a,g,e,b,c),i=Pd(g),j=i&&i.find();if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=j.to.line}}function Bb(a,b,c,d,e){function j(d){var e=yb(a,Gc(c,d),\"line\",b,i);return g=!0,f>e.bottom?e.left-h:f<e.top?e.left+h:(g=!1,e.left)}var f=e-Ee(a,b),g=!1,h=2*a.display.wrapper.clientWidth,i=ob(a,b),k=Fe(b),l=b.text.length,m=Rf(b),n=Sf(b),o=j(m),p=g,q=j(n),r=g;if(d>q)return zb(c,n,r,1);for(;;){if(k?n==m||n==Zf(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);yf(b.text.charAt(s));)++s;var u=zb(c,s,s==m?p:r,0>t?-1:t?1:0);return u}var v=Math.ceil(l/2),w=m+v;if(k){w=m;for(var x=0;v>x;++x)w=Zf(b,w,1)}var y=j(w);y>d?(n=w,q=y,(r=g)&&(q+=1e3),l=v):(m=w,o=y,p=g,l-=v)}}function Db(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==Cb){Cb=zf(\"pre\");for(var b=0;49>b;++b)Cb.appendChild(document.createTextNode(\"x\")),Cb.appendChild(zf(\"br\"));Cb.appendChild(document.createTextNode(\"x\"))}Bf(a.measure,Cb);var c=Cb.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),Af(a.measure),c||1}function Eb(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=zf(\"span\",\"x\"),c=zf(\"pre\",[b]);Bf(a.measure,c);var d=b.offsetWidth;return d>2&&(a.cachedCharWidth=d),d||10}function Gb(a){a.curOp={changes:[],forceUpdate:!1,updateInput:null,userSelChange:null,textChanged:null,selectionChanged:!1,cursorActivity:!1,updateMaxLine:!1,updateScrollPos:!1,id:++Fb},af++||(_e=[])}function Hb(a){var b=a.curOp,c=a.doc,d=a.display;if(a.curOp=null,b.updateMaxLine&&L(a),d.maxLineChanged&&!a.options.lineWrapping&&d.maxLine){var e=rb(a,d.maxLine);d.sizer.style.minWidth=Math.max(0,e+3)+\"px\",d.maxLineChanged=!1;var f=Math.max(0,d.sizer.offsetLeft+d.sizer.offsetWidth-d.scroller.clientWidth);f<c.scrollLeft&&!b.updateScrollPos&&ec(a,Math.min(d.scroller.scrollLeft,f),!0)}var g,h;if(b.updateScrollPos)g=b.updateScrollPos;else if(b.selectionChanged&&d.scroller.clientHeight){var i=yb(a,c.sel.head);g=Xc(a,i.left,i.top,i.left,i.bottom)}if((b.changes.length||b.forceUpdate||g&&null!=g.scrollTop)&&(h=T(a,b.changes,g&&g.scrollTop,b.forceUpdate),a.display.scroller.offsetHeight&&(a.doc.scrollTop=a.display.scroller.scrollTop)),!h&&b.selectionChanged&&ab(a),b.updateScrollPos){var j=Math.max(0,Math.min(d.scroller.scrollHeight-d.scroller.clientHeight,g.scrollTop)),k=Math.max(0,Math.min(d.scroller.scrollWidth-d.scroller.clientWidth,g.scrollLeft));d.scroller.scrollTop=d.scrollbarV.scrollTop=c.scrollTop=j,d.scroller.scrollLeft=d.scrollbarH.scrollLeft=c.scrollLeft=k,P(a),b.scrollToPos&&Vc(a,Mc(a.doc,b.scrollToPos.from),Mc(a.doc,b.scrollToPos.to),b.scrollToPos.margin)}else g&&Uc(a);b.selectionChanged&&db(a),a.state.focused&&b.updateInput&&Pb(a,b.userSelChange);var l=b.maybeHiddenMarkers,m=b.maybeUnhiddenMarkers;if(l)for(var n=0;n<l.length;++n)l[n].lines.length||$e(l[n],\"hide\");if(m)for(var n=0;n<m.length;++n)m[n].lines.length&&$e(m[n],\"unhide\");var o;if(--af||(o=_e,_e=null),b.textChanged&&$e(a,\"change\",a,b.textChanged),b.cursorActivity&&$e(a,\"cursorActivity\",a),o)for(var n=0;n<o.length;++n)o[n]()}function Ib(a,b){return function(){var c=a||this,d=!c.curOp;d&&Gb(c);try{var e=b.apply(c,arguments)}finally{d&&Hb(c)}return e}}function Jb(a){return function(){var c,b=this.cm&&!this.cm.curOp;b&&Gb(this.cm);try{c=a.apply(this,arguments)}finally{b&&Hb(this.cm)}return c}}function Kb(a,b){var d,c=!a.curOp;c&&Gb(a);try{d=b()}finally{c&&Hb(a)}return d}function Lb(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),a.curOp.changes.push({from:b,to:c,diff:d})}function Mb(a){a.display.pollingFast||a.display.poll.set(a.options.pollInterval,function(){Ob(a),a.state.focused&&Mb(a)})}function Nb(a){function c(){var d=Ob(a);d||b?(a.display.pollingFast=!1,Mb(a)):(b=!0,a.display.poll.set(60,c))}var b=!1;a.display.pollingFast=!0,a.display.poll.set(20,c)}function Ob(a){var b=a.display.input,c=a.display.prevInput,e=a.doc,f=e.sel;if(!a.state.focused||Lf(b)||Sb(a)||a.options.disableInput)return!1;a.state.pasteIncoming&&a.state.fakedLastChar&&(b.value=b.value.substring(0,b.value.length-1),a.state.fakedLastChar=!1);var h=b.value;if(h==c&&Hc(f.from,f.to))return!1;if(g&&!d&&a.display.inputHasSelection===h)return Pb(a,!0),!1;var i=!a.curOp;i&&Gb(a),f.shift=!1;for(var j=0,k=Math.min(c.length,h.length);k>j&&c.charCodeAt(j)==h.charCodeAt(j);)++j;var l=f.from,m=f.to,n=h.slice(j);j<c.length?l=Gc(l.line,l.ch-(c.length-j)):a.state.overwrite&&Hc(l,m)&&!a.state.pasteIncoming&&(m=Gc(m.line,Math.min(ye(e,m.line).text.length,m.ch+n.length)));var o=a.curOp.updateInput,p={from:l,to:m,text:Kf(n),origin:a.state.pasteIncoming?\"paste\":a.state.cutIncoming?\"cut\":\"+input\"};if(zc(a.doc,p,\"end\"),a.curOp.updateInput=o,bf(a,\"inputRead\",a,p),n&&!a.state.pasteIncoming&&a.options.electricChars&&a.options.smartIndent&&f.head.ch<100){var q=a.getModeAt(f.head).electricChars;if(q)for(var r=0;r<q.length;r++)if(n.indexOf(q.charAt(r))>-1){$c(a,f.head.line,\"smart\");break}}return h.length>1e3||h.indexOf(\"\\n\")>-1?b.value=a.display.prevInput=\"\":a.display.prevInput=h,i&&Hb(a),a.state.pasteIncoming=a.state.cutIncoming=!1,!0}function Pb(a,b){var c,e,f=a.doc;if(Hc(f.sel.from,f.sel.to))b&&(a.display.prevInput=a.display.input.value=\"\",g&&!d&&(a.display.inputHasSelection=null));else{a.display.prevInput=\"\",c=Mf&&(f.sel.to.line-f.sel.from.line>100||(e=a.getSelection()).length>1e3);var h=c?\"-\":e||a.getSelection();a.display.input.value=h,a.state.focused&&of(a.display.input),g&&!d&&(a.display.inputHasSelection=h)}a.display.inaccurateSelection=c}function Qb(a){\"nocursor\"==a.options.readOnly||r&&document.activeElement==a.display.input||a.display.input.focus()}function Rb(a){a.state.focused||(Qb(a),rc(a))}function Sb(a){return a.options.readOnly||a.doc.cantEdit}function Tb(a){function e(){a.state.focused&&setTimeout(tf(Qb,a),0)}function i(){null==f&&(f=setTimeout(function(){f=null,c.cachedCharWidth=c.cachedTextHeight=c.cachedPaddingH=Gf=null,sb(a),Kb(a,tf(Lb,a))},100))}function j(){for(var a=c.wrapper.parentNode;a&&a!=document.body;a=a.parentNode);a?setTimeout(j,5e3):Ze(window,\"resize\",i)}function k(b){cf(a,b)||a.options.onDragEvent&&a.options.onDragEvent(a,Re(b))||Ve(b)}function l(b){c.inaccurateSelection&&(c.prevInput=\"\",c.inaccurateSelection=!1,c.input.value=a.getSelection(),of(c.input)),\"cut\"==b.type&&(a.state.cutIncoming=!0)}var c=a.display;Ye(c.scroller,\"mousedown\",Ib(a,Yb)),b?Ye(c.scroller,\"dblclick\",Ib(a,function(b){if(!cf(a,b)){var c=Vb(a,b);if(c&&!_b(a,b)&&!Ub(a.display,b)){Se(b);var d=cd(ye(a.doc,c.line).text,c);Pc(a.doc,d.from,d.to)}}})):Ye(c.scroller,\"dblclick\",function(b){cf(a,b)||Se(b)}),Ye(c.lineSpace,\"selectstart\",function(a){Ub(c,a)||Se(a)}),w||Ye(c.scroller,\"contextmenu\",function(b){uc(a,b)}),Ye(c.scroller,\"scroll\",function(){c.scroller.clientHeight&&(dc(a,c.scroller.scrollTop),ec(a,c.scroller.scrollLeft,!0),$e(a,\"scroll\",a))}),Ye(c.scrollbarV,\"scroll\",function(){c.scroller.clientHeight&&dc(a,c.scrollbarV.scrollTop)}),Ye(c.scrollbarH,\"scroll\",function(){c.scroller.clientHeight&&ec(a,c.scrollbarH.scrollLeft)}),Ye(c.scroller,\"mousewheel\",function(b){hc(a,b)}),Ye(c.scroller,\"DOMMouseScroll\",function(b){hc(a,b)}),Ye(c.scrollbarH,\"mousedown\",e),Ye(c.scrollbarV,\"mousedown\",e),Ye(c.wrapper,\"scroll\",function(){c.wrapper.scrollTop=c.wrapper.scrollLeft=0});var f;Ye(window,\"resize\",i),setTimeout(j,5e3),Ye(c.input,\"keyup\",Ib(a,nc)),Ye(c.input,\"input\",function(){g&&!d&&a.display.inputHasSelection&&(a.display.inputHasSelection=null),Nb(a)}),Ye(c.input,\"keydown\",Ib(a,pc)),Ye(c.input,\"keypress\",Ib(a,qc)),Ye(c.input,\"focus\",tf(rc,a)),Ye(c.input,\"blur\",tf(sc,a)),a.options.dragDrop&&(Ye(c.scroller,\"dragstart\",function(b){cc(a,b)}),Ye(c.scroller,\"dragenter\",k),Ye(c.scroller,\"dragover\",k),Ye(c.scroller,\"drop\",Ib(a,bc))),Ye(c.scroller,\"paste\",function(b){Ub(c,b)||(Qb(a),Nb(a))}),Ye(c.input,\"paste\",function(){if(h&&!a.state.fakedLastChar&&!(new Date-a.state.lastMiddleDown<200)){var b=c.input.selectionStart,d=c.input.selectionEnd;c.input.value+=\"$\",c.input.selectionStart=b,c.input.selectionEnd=d,a.state.fakedLastChar=!0}a.state.pasteIncoming=!0,Nb(a)}),Ye(c.input,\"cut\",l),Ye(c.input,\"copy\",l),m&&Ye(c.sizer,\"mouseup\",function(){document.activeElement==c.input&&c.input.blur(),Qb(a)\n})}function Ub(a,b){for(var c=We(b);c!=a.wrapper;c=c.parentNode)if(!c||c.ignoreEvents||c.parentNode==a.sizer&&c!=a.mover)return!0}function Vb(a,b,c){var d=a.display;if(!c){var e=We(b);if(e==d.scrollbarH||e==d.scrollbarH.firstChild||e==d.scrollbarV||e==d.scrollbarV.firstChild||e==d.scrollbarFiller||e==d.gutterFiller)return null}var f,g,h=Df(d.lineSpace);try{f=b.clientX,g=b.clientY}catch(b){return null}return Ab(a,f-h.left,g-h.top)}function Yb(a){function t(a){if(!Hc(s,a)){if(s=a,\"single\"==m)return Pc(c.doc,Mc(i,k),a),void 0;if(q=Mc(i,q),r=Mc(i,r),\"double\"==m){var b=cd(ye(i,a.line).text,a);Ic(a,q)?Pc(c.doc,b.from,r):Pc(c.doc,q,b.to)}else\"triple\"==m&&(Ic(a,q)?Pc(c.doc,r,Mc(i,Gc(a.line,0))):Pc(c.doc,q,Mc(i,Gc(a.line+1,0))))}}function x(a){var b=++v,d=Vb(c,a,!0);if(d)if(Hc(d,o)){var g=a.clientY<u.top?-20:a.clientY>u.bottom?20:0;g&&setTimeout(Ib(c,function(){v==b&&(f.scroller.scrollTop+=g,x(a))}),50)}else{Rb(c),o=d,t(d);var e=O(f,i);(d.line>=e.to||d.line<e.from)&&setTimeout(Ib(c,function(){v==b&&x(a)}),150)}}function y(a){v=1/0,Se(a),Qb(c),Ze(document,\"mousemove\",z),Ze(document,\"mouseup\",A)}if(!cf(this,a)){var c=this,f=c.display,i=c.doc,j=i.sel;if(j.shift=a.shiftKey,Ub(f,a))return h||(f.scroller.draggable=!1,setTimeout(function(){f.scroller.draggable=!0},100)),void 0;if(!_b(c,a)){var k=Vb(c,a);switch(window.focus(),Xe(a)){case 3:return w&&uc.call(c,c,a),void 0;case 2:return h&&(c.state.lastMiddleDown=+new Date),k&&Pc(c.doc,k),setTimeout(tf(Qb,c),20),Se(a),void 0}if(!k)return We(a)==f.scroller&&Se(a),void 0;setTimeout(tf(Rb,c),0);var l=+new Date,m=\"single\";if(Xb&&Xb.time>l-400&&Hc(Xb.pos,k))m=\"triple\",Se(a),setTimeout(tf(Qb,c),20),dd(c,k.line);else if(Wb&&Wb.time>l-400&&Hc(Wb.pos,k)){m=\"double\",Xb={time:l,pos:k},Se(a);var n=cd(ye(i,k.line).text,k);Pc(c.doc,n.from,n.to)}else Wb={time:l,pos:k};var o=k;if(c.options.dragDrop&&Ef&&!Sb(c)&&!Hc(j.from,j.to)&&!Ic(k,j.from)&&!Ic(j.to,k)&&\"single\"==m){var p=Ib(c,function(e){h&&(f.scroller.draggable=!1),c.state.draggingText=!1,Ze(document,\"mouseup\",p),Ze(f.scroller,\"drop\",p),Math.abs(a.clientX-e.clientX)+Math.abs(a.clientY-e.clientY)<10&&(Se(e),Pc(c.doc,k),Qb(c),b&&!d&&setTimeout(function(){document.body.focus(),Qb(c)},20))});return h&&(f.scroller.draggable=!0),c.state.draggingText=p,f.scroller.dragDrop&&f.scroller.dragDrop(),Ye(document,\"mouseup\",p),Ye(f.scroller,\"drop\",p),void 0}Se(a),\"single\"==m&&Pc(c.doc,Mc(i,k));var q=j.from,r=j.to,s=k,u=Df(f.wrapper),v=0,z=Ib(c,function(a){(g&&!e?a.buttons:Xe(a))?x(a):y(a)}),A=Ib(c,y);Ye(document,\"mousemove\",z),Ye(document,\"mouseup\",A)}}}function Zb(a,b,c,d,e){try{var f=b.clientX,g=b.clientY}catch(b){return!1}if(f>=Math.floor(Df(a.display.gutters).right))return!1;d&&Se(b);var h=a.display,i=Df(h.lineDiv);if(g>i.bottom||!ef(a,c))return Ue(b);g-=i.top-h.viewOffset;for(var j=0;j<a.options.gutters.length;++j){var k=h.gutters.childNodes[j];if(k&&Df(k).right>=f){var l=De(a.doc,g),m=a.options.gutters[j];return e(a,c,a,l,m,b),Ue(b)}}}function $b(a,b){return ef(a,\"gutterContextMenu\")?Zb(a,b,\"gutterContextMenu\",!1,$e):!1}function _b(a,b){return Zb(a,b,\"gutterClick\",!0,bf)}function bc(a){var b=this;if(!(cf(b,a)||Ub(b.display,a)||b.options.onDragEvent&&b.options.onDragEvent(b,Re(a)))){Se(a),g&&(ac=+new Date);var c=Vb(b,a,!0),d=a.dataTransfer.files;if(c&&!Sb(b))if(d&&d.length&&window.FileReader&&window.File)for(var e=d.length,f=Array(e),h=0,i=function(a,d){var g=new FileReader;g.onload=function(){f[d]=g.result,++h==e&&(c=Mc(b.doc,c),zc(b.doc,{from:c,to:c,text:Kf(f.join(\"\\n\")),origin:\"paste\"},\"around\"))},g.readAsText(a)},j=0;e>j;++j)i(d[j],j);else{if(b.state.draggingText&&!Ic(c,b.doc.sel.from)&&!Ic(b.doc.sel.to,c))return b.state.draggingText(a),setTimeout(tf(Qb,b),20),void 0;try{var f=a.dataTransfer.getData(\"Text\");if(f){var k=b.doc.sel.from,l=b.doc.sel.to;Rc(b.doc,c,c),b.state.draggingText&&Fc(b.doc,\"\",k,l,\"paste\"),b.replaceSelection(f,null,\"paste\"),Qb(b)}}catch(a){}}}}function cc(a,b){if(g&&(!a.state.draggingText||+new Date-ac<100))return Ve(b),void 0;if(!cf(a,b)&&!Ub(a.display,b)){var c=a.getSelection();if(b.dataTransfer.setData(\"Text\",c),b.dataTransfer.setDragImage&&!l){var d=zf(\"img\",null,null,\"position: fixed; left: 0; top: 0;\");d.src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\",k&&(d.width=d.height=1,a.display.wrapper.appendChild(d),d._top=d.offsetTop),b.dataTransfer.setDragImage(d,0,0),k&&d.parentNode.removeChild(d)}}}function dc(b,c){Math.abs(b.doc.scrollTop-c)<2||(b.doc.scrollTop=c,a||T(b,[],c),b.display.scroller.scrollTop!=c&&(b.display.scroller.scrollTop=c),b.display.scrollbarV.scrollTop!=c&&(b.display.scrollbarV.scrollTop=c),a&&T(b,[]),eb(b,100))}function ec(a,b,c){(c?b==a.doc.scrollLeft:Math.abs(a.doc.scrollLeft-b)<2)||(b=Math.min(b,a.display.scroller.scrollWidth-a.display.scroller.clientWidth),a.doc.scrollLeft=b,P(a),a.display.scroller.scrollLeft!=b&&(a.display.scroller.scrollLeft=b),a.display.scrollbarH.scrollLeft!=b&&(a.display.scrollbarH.scrollLeft=b))}function hc(b,c){var d=c.wheelDeltaX,e=c.wheelDeltaY;null==d&&c.detail&&c.axis==c.HORIZONTAL_AXIS&&(d=c.detail),null==e&&c.detail&&c.axis==c.VERTICAL_AXIS?e=c.detail:null==e&&(e=c.wheelDelta);var f=b.display,g=f.scroller;if(d&&g.scrollWidth>g.clientWidth||e&&g.scrollHeight>g.clientHeight){if(e&&s&&h)for(var i=c.target;i!=g;i=i.parentNode)if(i.lineObj){b.display.currentWheelTarget=i;break}if(d&&!a&&!k&&null!=gc)return e&&dc(b,Math.max(0,Math.min(g.scrollTop+e*gc,g.scrollHeight-g.clientHeight))),ec(b,Math.max(0,Math.min(g.scrollLeft+d*gc,g.scrollWidth-g.clientWidth))),Se(c),f.wheelStartX=null,void 0;if(e&&null!=gc){var j=e*gc,l=b.doc.scrollTop,m=l+f.wrapper.clientHeight;0>j?l=Math.max(0,l+j-50):m=Math.min(b.doc.height,m+j+50),T(b,[],{top:l,bottom:m})}20>fc&&(null==f.wheelStartX?(f.wheelStartX=g.scrollLeft,f.wheelStartY=g.scrollTop,f.wheelDX=d,f.wheelDY=e,setTimeout(function(){if(null!=f.wheelStartX){var a=g.scrollLeft-f.wheelStartX,b=g.scrollTop-f.wheelStartY,c=b&&f.wheelDY&&b/f.wheelDY||a&&f.wheelDX&&a/f.wheelDX;f.wheelStartX=f.wheelStartY=null,c&&(gc=(gc*fc+c)/(fc+1),++fc)}},200)):(f.wheelDX+=d,f.wheelDY+=e))}}function ic(a,b,c){if(\"string\"==typeof b&&(b=pd[b],!b))return!1;a.display.pollingFast&&Ob(a)&&(a.display.pollingFast=!1);var d=a.doc,e=d.sel.shift,f=!1;try{Sb(a)&&(a.state.suppressEdits=!0),c&&(d.sel.shift=!1),f=b(a)!=hf}finally{d.sel.shift=e,a.state.suppressEdits=!1}return f}function jc(a){var b=a.state.keyMaps.slice(0);return a.options.extraKeys&&b.push(a.options.extraKeys),b.push(a.options.keyMap),b}function lc(a,b){var c=rd(a.options.keyMap),e=c.auto;clearTimeout(kc),e&&!td(b)&&(kc=setTimeout(function(){rd(a.options.keyMap)==c&&(a.options.keyMap=e.call?e.call(null,a):e,G(a))},50));var f=ud(b,!0),g=!1;if(!f)return!1;var h=jc(a);return g=b.shiftKey?sd(\"Shift-\"+f,h,function(b){return ic(a,b,!0)})||sd(f,h,function(b){return(\"string\"==typeof b?/^go[A-Z]/.test(b):b.motion)?ic(a,b):void 0}):sd(f,h,function(b){return ic(a,b)}),g&&(Se(b),db(a),d&&(b.oldKeyCode=b.keyCode,b.keyCode=0),bf(a,\"keyHandled\",a,f,b)),g}function mc(a,b,c){var d=sd(\"'\"+c+\"'\",jc(a),function(b){return ic(a,b,!0)});return d&&(Se(b),db(a),bf(a,\"keyHandled\",a,\"'\"+c+\"'\",b)),d}function nc(a){var b=this;cf(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Re(a))||16==a.keyCode&&(b.doc.sel.shift=!1)}function pc(a){var c=this;if(Rb(c),!(cf(c,a)||c.options.onKeyEvent&&c.options.onKeyEvent(c,Re(a)))){b&&27==a.keyCode&&(a.returnValue=!1);var d=a.keyCode;c.doc.sel.shift=16==d||a.shiftKey;var e=lc(c,a);k&&(oc=e?d:null,!e&&88==d&&!Mf&&(s?a.metaKey:a.ctrlKey)&&c.replaceSelection(\"\"))}}function qc(a){var b=this;if(!(cf(b,a)||b.options.onKeyEvent&&b.options.onKeyEvent(b,Re(a)))){var c=a.keyCode,e=a.charCode;if(k&&c==oc)return oc=null,Se(a),void 0;if(!(k&&(!a.which||a.which<10)||m)||!lc(b,a)){var f=String.fromCharCode(null==e?c:e);mc(b,a,f)||(g&&!d&&(b.display.inputHasSelection=null),Nb(b))}}}function rc(a){\"nocursor\"!=a.options.readOnly&&(a.state.focused||($e(a,\"focus\",a),a.state.focused=!0,-1==a.display.wrapper.className.search(/\\bCodeMirror-focused\\b/)&&(a.display.wrapper.className+=\" CodeMirror-focused\"),a.curOp||(Pb(a,!0),h&&setTimeout(tf(Pb,a,!0),0))),Mb(a),db(a))}function sc(a){a.state.focused&&($e(a,\"blur\",a),a.state.focused=!1,a.display.wrapper.className=a.display.wrapper.className.replace(\" CodeMirror-focused\",\"\")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.doc.sel.shift=!1)},150)}function uc(a,b){function l(){if(null!=c.input.selectionStart){var a=c.input.value=\"\\u200b\"+(Hc(e.from,e.to)?\"\":c.input.value);c.prevInput=\"\\u200b\",c.input.selectionStart=1,c.input.selectionEnd=a.length}}function m(){if(c.inputDiv.style.position=\"relative\",c.input.style.cssText=j,d&&(c.scrollbarV.scrollTop=c.scroller.scrollTop=h),Mb(a),null!=c.input.selectionStart){(!g||d)&&l(),clearTimeout(tc);var b=0,e=function(){\"\\u200b\"==c.prevInput&&0==c.input.selectionStart?Ib(a,pd.selectAll)(a):b++<10?tc=setTimeout(e,500):Pb(a)};tc=setTimeout(e,200)}}if(!cf(a,b,\"contextmenu\")){var c=a.display,e=a.doc.sel;if(!Ub(c,b)&&!$b(a,b)){var f=Vb(a,b),h=c.scroller.scrollTop;if(f&&!k){var i=a.options.resetSelectionOnContextMenu;i&&(Hc(e.from,e.to)||Ic(f,e.from)||!Ic(f,e.to))&&Ib(a,Rc)(a.doc,f,f);var j=c.input.style.cssText;if(c.inputDiv.style.position=\"absolute\",c.input.style.cssText=\"position: fixed; width: 30px; height: 30px; top: \"+(b.clientY-5)+\"px; left: \"+(b.clientX-5)+\"px; z-index: 1000; background: transparent; outline: none;\"+\"border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);\",Qb(a),Pb(a,!0),Hc(e.from,e.to)&&(c.input.value=c.prevInput=\" \"),g&&!d&&l(),w){Ve(b);var n=function(){Ze(window,\"mouseup\",n),setTimeout(m,20)};Ye(window,\"mouseup\",n)}else setTimeout(m,50)}}}}function wc(a,b,c){if(!Ic(b.from,c))return Mc(a,c);var d=b.text.length-1-(b.to.line-b.from.line);if(c.line>b.to.line+d){var e=c.line-d,f=a.first+a.size-1;return e>f?Gc(f,ye(a,f).text.length):Nc(c,ye(a,e).text.length)}if(c.line==b.to.line+d)return Nc(c,nf(b.text).length+(1==b.text.length?b.from.ch:0)+ye(a,b.to.line).text.length-b.to.ch);var g=c.line-b.from.line;return Nc(c,b.text[g].length+(g?0:b.from.ch))}function xc(a,b,c){if(c&&\"object\"==typeof c)return{anchor:wc(a,b,c.anchor),head:wc(a,b,c.head)};if(\"start\"==c)return{anchor:b.from,head:b.from};var d=vc(b);if(\"around\"==c)return{anchor:b.from,head:d};if(\"end\"==c)return{anchor:d,head:d};var e=function(a){if(Ic(a,b.from))return a;if(!Ic(b.to,a))return d;var c=a.line+b.text.length-(b.to.line-b.from.line)-1,e=a.ch;return a.line==b.to.line&&(e+=d.ch-b.to.ch),Gc(c,e)};return{anchor:e(a.sel.anchor),head:e(a.sel.head)}}function yc(a,b,c){var d={canceled:!1,from:b.from,to:b.to,text:b.text,origin:b.origin,cancel:function(){this.canceled=!0}};return c&&(d.update=function(b,c,d,e){b&&(this.from=Mc(a,b)),c&&(this.to=Mc(a,c)),d&&(this.text=d),void 0!==e&&(this.origin=e)}),$e(a,\"beforeChange\",a,d),a.cm&&$e(a.cm,\"beforeChange\",a.cm,d),d.canceled?null:{from:d.from,to:d.to,text:d.text,origin:d.origin}}function zc(a,b,c,d){if(a.cm){if(!a.cm.curOp)return Ib(a.cm,zc)(a,b,c,d);if(a.cm.state.suppressEdits)return}if(!(ef(a,\"beforeChange\")||a.cm&&ef(a.cm,\"beforeChange\"))||(b=yc(a,b,!0))){var e=x&&!d&&Jd(a,b.from,b.to);if(e){for(var f=e.length-1;f>=1;--f)Ac(a,{from:e[f].from,to:e[f].to,text:[\"\"]});e.length&&Ac(a,{from:e[0].from,to:e[0].to,text:b.text},c)}else Ac(a,b,c)}}function Ac(a,b,c){if(1!=b.text.length||\"\"!=b.text[0]||!Hc(b.from,b.to)){var d=xc(a,b,c);Je(a,b,d,a.cm?a.cm.curOp.id:0/0),Dc(a,b,d,Gd(a,b));var e=[];we(a,function(a,c){c||-1!=pf(e,a.history)||(Pe(a.history,b),e.push(a.history)),Dc(a,b,null,Gd(a,b))})}}function Bc(a,b){if(!a.cm||!a.cm.state.suppressEdits){var c=a.history,d=(\"undo\"==b?c.done:c.undone).pop();if(d){var e={changes:[],anchorBefore:d.anchorAfter,headBefore:d.headAfter,anchorAfter:d.anchorBefore,headAfter:d.headBefore,generation:c.generation};(\"undo\"==b?c.undone:c.done).push(e),c.generation=d.generation||++c.maxGeneration;for(var f=ef(a,\"beforeChange\")||a.cm&&ef(a.cm,\"beforeChange\"),g=d.changes.length-1;g>=0;--g){var h=d.changes[g];if(h.origin=b,f&&!yc(a,h,!1))return(\"undo\"==b?c.done:c.undone).length=0,void 0;e.changes.push(Ie(a,h));var i=g?xc(a,h,null):{anchor:d.anchorBefore,head:d.headBefore};Dc(a,h,i,Id(a,h));var j=[];we(a,function(a,b){b||-1!=pf(j,a.history)||(Pe(a.history,h),j.push(a.history)),Dc(a,h,null,Id(a,h))})}}}}function Cc(a,b){function c(a){return Gc(a.line+b,a.ch)}a.first+=b,a.cm&&Lb(a.cm,a.first,a.first,b),a.sel.head=c(a.sel.head),a.sel.anchor=c(a.sel.anchor),a.sel.from=c(a.sel.from),a.sel.to=c(a.sel.to)}function Dc(a,b,c,d){if(a.cm&&!a.cm.curOp)return Ib(a.cm,Dc)(a,b,c,d);if(b.to.line<a.first)return Cc(a,b.text.length-1-(b.to.line-b.from.line)),void 0;if(!(b.from.line>a.lastLine())){if(b.from.line<a.first){var e=b.text.length-1-(a.first-b.from.line);Cc(a,e),b={from:Gc(a.first,0),to:Gc(b.to.line+e,b.to.ch),text:[nf(b.text)],origin:b.origin}}var f=a.lastLine();b.to.line>f&&(b={from:b.from,to:Gc(f,ye(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=ze(a,b.from,b.to),c||(c=xc(a,b,null)),a.cm?Ec(a.cm,b,d,c):pe(a,b,d,c)}}function Ec(a,b,c,d){var e=a.doc,f=a.display,g=b.from,h=b.to,i=!1,j=g.line;a.options.lineWrapping||(j=Ce(Rd(e,ye(e,g.line))),e.iter(j,h.line+1,function(a){return a==f.maxLine?(i=!0,!0):void 0})),Ic(e.sel.head,b.from)||Ic(b.to,e.sel.head)||(a.curOp.cursorActivity=!0),pe(e,b,c,d,E(a)),a.options.lineWrapping||(e.iter(j,g.line+b.text.length,function(a){var b=K(e,a);b>f.maxLineLength&&(f.maxLine=a,f.maxLineLength=b,f.maxLineChanged=!0,i=!1)}),i&&(a.curOp.updateMaxLine=!0)),e.frontier=Math.min(e.frontier,g.line),eb(a,400);var k=b.text.length-(h.line-g.line)-1;if(Lb(a,g.line,h.line+1,k),ef(a,\"change\")){var l={from:g,to:h,text:b.text,removed:b.removed,origin:b.origin};if(a.curOp.textChanged){for(var m=a.curOp.textChanged;m.next;m=m.next);m.next=l}else a.curOp.textChanged=l}}function Fc(a,b,c,d,e){if(d||(d=c),Ic(d,c)){var f=d;d=c,c=f}\"string\"==typeof b&&(b=Kf(b)),zc(a,{from:c,to:d,text:b,origin:e},null)}function Gc(a,b){return this instanceof Gc?(this.line=a,this.ch=b,void 0):new Gc(a,b)}function Hc(a,b){return a.line==b.line&&a.ch==b.ch}function Ic(a,b){return a.line<b.line||a.line==b.line&&a.ch<b.ch}function Jc(a,b){return a.line-b.line||a.ch-b.ch}function Kc(a){return Gc(a.line,a.ch)}function Lc(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function Mc(a,b){if(b.line<a.first)return Gc(a.first,0);var c=a.first+a.size-1;return b.line>c?Gc(c,ye(a,c).text.length):Nc(b,ye(a,b.line).text.length)}function Nc(a,b){var c=a.ch;return null==c||c>b?Gc(a.line,b):0>c?Gc(a.line,0):a}function Oc(a,b){return b>=a.first&&b<a.first+a.size}function Pc(a,b,c,d){if(a.sel.shift||a.sel.extend){var e=a.sel.anchor;if(c){var f=Ic(b,e);f!=Ic(c,e)?(e=b,b=c):f!=Ic(b,c)&&(b=c)}Rc(a,e,b,d)}else Rc(a,b,c||b,d);a.cm&&(a.cm.curOp.userSelChange=!0)}function Qc(a,b,c){var d={anchor:b,head:c};return $e(a,\"beforeSelectionChange\",a,d),a.cm&&$e(a.cm,\"beforeSelectionChange\",a.cm,d),d.anchor=Mc(a,d.anchor),d.head=Mc(a,d.head),d}function Rc(a,b,c,d,e){if(!e&&ef(a,\"beforeSelectionChange\")||a.cm&&ef(a.cm,\"beforeSelectionChange\")){var f=Qc(a,b,c);c=f.head,b=f.anchor}var g=a.sel;if(g.goalColumn=null,null==d&&(d=Ic(c,g.head)?-1:1),(e||!Hc(b,g.anchor))&&(b=Tc(a,b,d,\"push\"!=e)),(e||!Hc(c,g.head))&&(c=Tc(a,c,d,\"push\"!=e)),!Hc(g.anchor,b)||!Hc(g.head,c)){g.anchor=b,g.head=c;var h=Ic(c,b);g.from=h?c:b,g.to=h?b:c,a.cm&&(a.cm.curOp.updateInput=a.cm.curOp.selectionChanged=a.cm.curOp.cursorActivity=!0),bf(a,\"cursorActivity\",a)}}function Sc(a){Rc(a.doc,a.doc.sel.from,a.doc.sel.to,null,\"push\")}function Tc(a,b,c,d){var e=!1,f=b,g=c||1;a.cantEdit=!1;a:for(;;){var h=ye(a,f.line);if(h.markedSpans)for(var i=0;i<h.markedSpans.length;++i){var j=h.markedSpans[i],k=j.marker;if((null==j.from||(k.inclusiveLeft?j.from<=f.ch:j.from<f.ch))&&(null==j.to||(k.inclusiveRight?j.to>=f.ch:j.to>f.ch))){if(d&&($e(k,\"beforeCursorEnter\"),k.explicitlyCleared)){if(h.markedSpans){--i;continue}break}if(!k.atomic)continue;var l=k.find()[0>g?\"from\":\"to\"];if(Hc(l,f)&&(l.ch+=g,l.ch<0?l=l.line>a.first?Mc(a,Gc(l.line-1)):null:l.ch>h.text.length&&(l=l.line<a.first+a.size-1?Gc(l.line+1,0):null),!l)){if(e)return d?(a.cantEdit=!0,Gc(a.first,0)):Tc(a,b,c,!0);e=!0,l=b,g=-g}f=l;continue a}}return f}}function Uc(a){var b=Vc(a,a.doc.sel.head,null,a.options.cursorScrollMargin);if(a.state.focused){var c=a.display,d=Df(c.sizer),e=null;if(b.top+d.top<0?e=!0:b.bottom+d.top>(window.innerHeight||document.documentElement.clientHeight)&&(e=!1),null!=e&&!p){var f=zf(\"div\",\"\\u200b\",null,\"position: absolute; top: \"+(b.top-c.viewOffset)+\"px; height: \"+(b.bottom-b.top+gf)+\"px; left: \"+b.left+\"px; width: 2px;\");a.display.lineSpace.appendChild(f),f.scrollIntoView(e),a.display.lineSpace.removeChild(f)}}}function Vc(a,b,c,d){for(null==d&&(d=0);;){var e=!1,f=yb(a,b),g=c&&c!=b?yb(a,c):f,h=Xc(a,Math.min(f.left,g.left),Math.min(f.top,g.top)-d,Math.max(f.left,g.left),Math.max(f.bottom,g.bottom)+d),i=a.doc.scrollTop,j=a.doc.scrollLeft;if(null!=h.scrollTop&&(dc(a,h.scrollTop),Math.abs(a.doc.scrollTop-i)>1&&(e=!0)),null!=h.scrollLeft&&(ec(a,h.scrollLeft),Math.abs(a.doc.scrollLeft-j)>1&&(e=!0)),!e)return f}}function Wc(a,b,c,d,e){var f=Xc(a,b,c,d,e);null!=f.scrollTop&&dc(a,f.scrollTop),null!=f.scrollLeft&&ec(a,f.scrollLeft)}function Xc(a,b,c,d,e){var f=a.display,g=Db(a.display);0>c&&(c=0);var h=f.scroller.clientHeight-gf,i=f.scroller.scrollTop,j={},k=a.doc.height+jb(f),l=g>c,m=e>k-g;if(i>c)j.scrollTop=l?0:c;else if(e>i+h){var n=Math.min(c,(m?k:e)-h);n!=i&&(j.scrollTop=n)}var o=f.scroller.clientWidth-gf,p=f.scroller.scrollLeft;b+=f.gutters.offsetWidth,d+=f.gutters.offsetWidth;var q=f.gutters.offsetWidth,r=q+10>b;return p+q>b||r?(r&&(b=0),j.scrollLeft=Math.max(0,b-10-q)):d>o+p-3&&(j.scrollLeft=d+10-o),j}function Yc(a,b,c){a.curOp.updateScrollPos={scrollLeft:null==b?a.doc.scrollLeft:b,scrollTop:null==c?a.doc.scrollTop:c}}function Zc(a,b,c){var d=a.curOp.updateScrollPos||(a.curOp.updateScrollPos={scrollLeft:a.doc.scrollLeft,scrollTop:a.doc.scrollTop}),e=a.display.scroller;d.scrollTop=Math.max(0,Math.min(e.scrollHeight-e.clientHeight,d.scrollTop+c)),d.scrollLeft=Math.max(0,Math.min(e.scrollWidth-e.clientWidth,d.scrollLeft+b))}function $c(a,b,c,d){var f,e=a.doc;null==c&&(c=\"add\"),\"smart\"==c&&(a.doc.mode.indent?f=hb(a,b):c=\"prev\");var g=a.options.tabSize,h=ye(e,b),i=kf(h.text,null,g);h.stateAfter&&(h.stateAfter=null);var k,j=h.text.match(/^\\s*/)[0];if(d||/\\S/.test(h.text)){if(\"smart\"==c&&(k=a.doc.mode.indent(f,h.text.slice(j.length),h.text),k==hf)){if(!d)return;c=\"prev\"}}else k=0,c=\"not\";\"prev\"==c?k=b>e.first?kf(ye(e,b-1).text,null,g):0:\"add\"==c?k=i+a.options.indentUnit:\"subtract\"==c?k=i-a.options.indentUnit:\"number\"==typeof c&&(k=i+c),k=Math.max(0,k);var l=\"\",m=0;if(a.options.indentWithTabs)for(var n=Math.floor(k/g);n;--n)m+=g,l+=\"\t\";k>m&&(l+=mf(k-m)),l!=j?Fc(a.doc,l,Gc(b,0),Gc(b,j.length),\"+input\"):e.sel.head.line==b&&e.sel.head.ch<j.length&&Rc(e,Gc(b,j.length),Gc(b,j.length),1),h.stateAfter=null}function _c(a,b,c){var d=b,e=b,f=a.doc;return\"number\"==typeof b?e=ye(f,Lc(f,b)):d=Ce(b),null==d?null:c(e,d)?(Lb(a,d,d+1),e):null}function ad(a,b,c,d,e){function k(){var b=f+c;return b<a.first||b>=a.first+a.size?j=!1:(f=b,i=ye(a,b))}function l(a){var b=(e?Zf:$f)(i,g,c,!0);if(null==b){if(a||!k())return j=!1;g=e?(0>c?Sf:Rf)(i):0>c?i.text.length:0}else g=b;return!0}var f=b.line,g=b.ch,h=c,i=ye(a,f),j=!0;if(\"char\"==d)l();else if(\"column\"==d)l(!0);else if(\"word\"==d||\"group\"==d)for(var m=null,n=\"group\"==d,o=!0;!(0>c)||l(!o);o=!1){var p=i.text.charAt(g)||\"\\n\",q=vf(p)?\"w\":n&&\"\\n\"==p?\"n\":!n||/\\s/.test(p)?null:\"p\";if(!n||o||q||(q=\"s\"),m&&m!=q){0>c&&(c=1,l());break}if(q&&(m=q),c>0&&!l(!o))break}var r=Tc(a,Gc(f,g),h,!0);return j||(r.hitSide=!0),r}function bd(a,b,c,d){var g,e=a.doc,f=b.left;if(\"page\"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight);g=b.top+c*(h-(0>c?1.5:.5)*Db(a.display))}else\"line\"==d&&(g=c>0?b.bottom+3:b.top-3);for(;;){var i=Ab(a,f,g);if(!i.outside)break;if(0>c?0>=g:g>=e.height){i.hitSide=!0;break}g+=5*c}return i}function cd(a,b){var c=b.ch,d=b.ch;if(a){(b.xRel<0||d==a.length)&&c?--c:++d;for(var e=a.charAt(c),f=vf(e)?vf:/\\s/.test(e)?function(a){return/\\s/.test(a)}:function(a){return!/\\s/.test(a)&&!vf(a)};c>0&&f(a.charAt(c-1));)--c;for(;d<a.length&&f(a.charAt(d));)++d}return{from:Gc(b.line,c),to:Gc(b.line,d)}}function dd(a,b){Pc(a.doc,Gc(b,0),Mc(a.doc,Gc(b+1,0)))}function gd(a,b,c,d){z.defaults[a]=b,c&&(ed[a]=d?function(a,b,d){d!=hd&&c(a,b,d)}:c)}function nd(a,b){if(b===!0)return b;if(a.copyState)return a.copyState(b);var c={};for(var d in b){var e=b[d];e instanceof Array&&(e=e.concat([])),c[d]=e}return c}function od(a,b,c){return a.startState?a.startState(b,c):!0}function rd(a){return\"string\"==typeof a?qd[a]:a}function sd(a,b,c){function d(b){b=rd(b);var e=b[a];if(e===!1)return\"stop\";if(null!=e&&c(e))return!0;if(b.nofallthrough)return\"stop\";var f=b.fallthrough;if(null==f)return!1;if(\"[object Array]\"!=Object.prototype.toString.call(f))return d(f);for(var g=0,h=f.length;h>g;++g){var i=d(f[g]);if(i)return i}return!1}for(var e=0;e<b.length;++e){var f=d(b[e]);if(f)return\"stop\"!=f}}function td(a){var b=Nf[a.keyCode];return\"Ctrl\"==b||\"Alt\"==b||\"Shift\"==b||\"Mod\"==b}function ud(a,b){if(k&&34==a.keyCode&&a[\"char\"])return!1;var c=Nf[a.keyCode];return null==c||a.altGraphKey?!1:(a.altKey&&(c=\"Alt-\"+c),(v?a.metaKey:a.ctrlKey)&&(c=\"Ctrl-\"+c),(v?a.ctrlKey:a.metaKey)&&(c=\"Cmd-\"+c),!b&&a.shiftKey&&(c=\"Shift-\"+c),c)}function vd(a,b){this.pos=this.start=0,this.string=a,this.tabSize=b||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0}function wd(a,b){this.lines=[],this.type=b,this.doc=a}function yd(a,b,c,d,e){if(d&&d.shared)return Ad(a,b,c,d,e);if(a.cm&&!a.cm.curOp)return Ib(a.cm,yd)(a,b,c,d,e);var f=new wd(a,e);if(d&&rf(d,f),Ic(c,b)||Hc(b,c)&&f.clearWhenEmpty!==!1)return f;if(f.replacedWith&&(f.collapsed=!0,f.replacedWith=zf(\"span\",[f.replacedWith],\"CodeMirror-widget\"),d.handleMouseEvents||(f.replacedWith.ignoreEvents=!0)),f.collapsed){if(Qd(a,b.line,b,c,f)||b.line!=c.line&&Qd(a,c.line,b,c,f))throw new Error(\"Inserting collapsed marker partially overlapping an existing one\");y=!0}f.addToHistory&&Je(a,{from:b,to:c,origin:\"markText\"},{head:a.sel.head,anchor:a.sel.anchor},0/0);var i,g=b.line,h=a.cm;return a.iter(g,c.line+1,function(d){h&&f.collapsed&&!h.options.lineWrapping&&Rd(a,d)==h.display.maxLine&&(i=!0);var e={from:null,to:null,marker:f};g==b.line&&(e.from=b.ch),g==c.line&&(e.to=c.ch),f.collapsed&&g!=b.line&&Be(d,0),Dd(d,e),++g}),f.collapsed&&a.iter(b.line,c.line+1,function(b){Sd(a,b)&&Be(b,0)}),f.clearOnEnter&&Ye(f,\"beforeCursorEnter\",function(){f.clear()}),f.readOnly&&(x=!0,(a.history.done.length||a.history.undone.length)&&a.clearHistory()),f.collapsed&&(f.id=++xd,f.atomic=!0),h&&(i&&(h.curOp.updateMaxLine=!0),(f.className||f.title||f.startStyle||f.endStyle||f.collapsed)&&Lb(h,b.line,c.line+1),f.atomic&&Sc(h)),f}function zd(a,b){this.markers=a,this.primary=b;for(var c=0,d=this;c<a.length;++c)a[c].parent=this,Ye(a[c],\"clear\",function(){d.clear()})}function Ad(a,b,c,d,e){d=rf(d),d.shared=!1;var f=[yd(a,b,c,d,e)],g=f[0],h=d.replacedWith;return we(a,function(a){h&&(d.replacedWith=h.cloneNode(!0)),f.push(yd(a,Mc(a,b),Mc(a,c),d,e));for(var i=0;i<a.linked.length;++i)if(a.linked[i].isParent)return;g=nf(f)}),new zd(f,g)}function Bd(a,b){if(a)for(var c=0;c<a.length;++c){var d=a[c];if(d.marker==b)return d}}function Cd(a,b){for(var c,d=0;d<a.length;++d)a[d]!=b&&(c||(c=[])).push(a[d]);return c}function Dd(a,b){a.markedSpans=a.markedSpans?a.markedSpans.concat([b]):[b],b.marker.attachLine(a)}function Ed(a,b,c){if(a)for(var e,d=0;d<a.length;++d){var f=a[d],g=f.marker,h=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);if(h||f.from==b&&\"bookmark\"==g.type&&(!c||!f.marker.insertLeft)){var i=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);(e||(e=[])).push({from:f.from,to:i?null:f.to,marker:g})}}return e}function Fd(a,b,c){if(a)for(var e,d=0;d<a.length;++d){var f=a[d],g=f.marker,h=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);if(h||f.from==b&&\"bookmark\"==g.type&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);(e||(e=[])).push({from:i?null:f.from-b,to:null==f.to?null:f.to-b,marker:g})}}return e}function Gd(a,b){var c=Oc(a,b.from.line)&&ye(a,b.from.line).markedSpans,d=Oc(a,b.to.line)&&ye(a,b.to.line).markedSpans;if(!c&&!d)return null;var e=b.from.ch,f=b.to.ch,g=Hc(b.from,b.to),h=Ed(c,e,g),i=Fd(d,f,g),j=1==b.text.length,k=nf(b.text).length+(j?e:0);if(h)for(var l=0;l<h.length;++l){var m=h[l];if(null==m.to){var n=Bd(i,m.marker);n?j&&(m.to=null==n.to?null:n.to+k):m.to=e}}if(i)for(var l=0;l<i.length;++l){var m=i[l];if(null!=m.to&&(m.to+=k),null==m.from){var n=Bd(h,m.marker);n||(m.from=k,j&&(h||(h=[])).push(m))}else m.from+=k,j&&(h||(h=[])).push(m)}h&&(h=Hd(h)),i&&i!=h&&(i=Hd(i));var o=[h];if(!j){var q,p=b.text.length-2;if(p>0&&h)for(var l=0;l<h.length;++l)null==h[l].to&&(q||(q=[])).push({from:null,to:null,marker:h[l].marker});for(var l=0;p>l;++l)o.push(q);o.push(i)}return o}function Hd(a){for(var b=0;b<a.length;++b){var c=a[b];null!=c.from&&c.from==c.to&&c.marker.clearWhenEmpty!==!1&&a.splice(b--,1)}return a.length?a:null}function Id(a,b){var c=Le(a,b),d=Gd(a,b);if(!c)return d;if(!d)return c;for(var e=0;e<c.length;++e){var f=c[e],g=d[e];if(f&&g)a:for(var h=0;h<g.length;++h){for(var i=g[h],j=0;j<f.length;++j)if(f[j].marker==i.marker)continue a;f.push(i)}else g&&(c[e]=g)}return c}function Jd(a,b,c){var d=null;if(a.iter(b.line,c.line+1,function(a){if(a.markedSpans)for(var b=0;b<a.markedSpans.length;++b){var c=a.markedSpans[b].marker;!c.readOnly||d&&-1!=pf(d,c)||(d||(d=[])).push(c)}}),!d)return null;for(var e=[{from:b,to:c}],f=0;f<d.length;++f)for(var g=d[f],h=g.find(),i=0;i<e.length;++i){var j=e[i];if(!Ic(j.to,h.from)&&!Ic(h.to,j.from)){var k=[i,1];(Ic(j.from,h.from)||!g.inclusiveLeft&&Hc(j.from,h.from))&&k.push({from:j.from,to:h.from}),(Ic(h.to,j.to)||!g.inclusiveRight&&Hc(j.to,h.to))&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-1}}return e}function Kd(a){return a.inclusiveLeft?-1:0}function Ld(a){return a.inclusiveRight?1:0}function Md(a,b){var c=a.lines.length-b.lines.length;if(0!=c)return c;var d=a.find(),e=b.find(),f=Jc(d.from,e.from)||Kd(a)-Kd(b);if(f)return-f;var g=Jc(d.to,e.to)||Ld(a)-Ld(b);return g?g:b.id-a.id}function Nd(a,b){var d,c=y&&a.markedSpans;if(c)for(var e,f=0;f<c.length;++f)e=c[f],e.marker.collapsed&&null==(b?e.from:e.to)&&(!d||Md(d,e.marker)<0)&&(d=e.marker);return d}function Od(a){return Nd(a,!0)}function Pd(a){return Nd(a,!1)}function Qd(a,b,c,d,e){var f=ye(a,b),g=y&&f.markedSpans;if(g)for(var h=0;h<g.length;++h){var i=g[h];if(i.marker.collapsed){var j=i.marker.find(!0),k=Jc(j.from,c)||Kd(i.marker)-Kd(e),l=Jc(j.to,d)||Ld(i.marker)-Ld(e);if(!(k>=0&&0>=l||0>=k&&l>=0)&&(0>=k&&(Jc(j.to,c)||Ld(i.marker)-Kd(e))>0||k>=0&&(Jc(j.from,d)||Kd(i.marker)-Ld(e))<0))return!0}}}function Rd(a,b){for(var c;c=Od(b);)b=ye(a,c.find().from.line);return b}function Sd(a,b){var c=y&&b.markedSpans;if(c)for(var d,e=0;e<c.length;++e)if(d=c[e],d.marker.collapsed){if(null==d.from)return!0;if(!d.marker.replacedWith&&0==d.from&&d.marker.inclusiveLeft&&Td(a,b,d))return!0}}function Td(a,b,c){if(null==c.to){var d=c.marker.find().to,e=ye(a,d.line);return Td(a,e,Bd(e.markedSpans,c.marker))}if(c.marker.inclusiveRight&&c.to==b.text.length)return!0;for(var f,g=0;g<b.markedSpans.length;++g)if(f=b.markedSpans[g],f.marker.collapsed&&!f.marker.replacedWith&&f.from==c.to&&(null==f.to||f.to!=c.from)&&(f.marker.inclusiveLeft||c.marker.inclusiveRight)&&Td(a,b,f))return!0}function Ud(a){var b=a.markedSpans;if(b){for(var c=0;c<b.length;++c)b[c].marker.detachLine(a);a.markedSpans=null}}function Vd(a,b){if(b){for(var c=0;c<b.length;++c)b[c].marker.attachLine(a);a.markedSpans=b}}function Xd(a){return function(){var b=!this.cm.curOp;b&&Gb(this.cm);try{var c=a.apply(this,arguments)}finally{b&&Hb(this.cm)}return c}}function Yd(a){return null!=a.height?a.height:(a.node.parentNode&&1==a.node.parentNode.nodeType||Bf(a.cm.display.measure,zf(\"div\",[a.node],null,\"position: relative\")),a.height=a.node.offsetHeight)}function Zd(a,b,c,d){var e=new Wd(a,c,d);return e.noHScroll&&(a.display.alignWidgets=!0),_c(a,b,function(b){var c=b.widgets||(b.widgets=[]);if(null==e.insertAt?c.push(e):c.splice(Math.min(c.length-1,Math.max(0,e.insertAt)),0,e),e.line=b,!Sd(a.doc,b)||e.showIfHidden){var d=Ee(a,b)<a.doc.scrollTop;Be(b,b.height+Yd(e)),d&&Zc(a,0,e.height),a.curOp.forceUpdate=!0}return!0}),e}function _d(a,b,c,d){a.text=b,a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null),null!=a.order&&(a.order=null),Ud(a),Vd(a,c);var e=d?d(a):1;e!=a.height&&Be(a,e)}function ae(a){a.parent=null,Ud(a)}function be(a,b,c,d,e,f){var g=c.flattenSpans;null==g&&(g=a.options.flattenSpans);var k,h=0,i=null,j=new vd(b,a.options.tabSize);for(\"\"==b&&c.blankLine&&c.blankLine(d);!j.eol();){if(j.pos>a.options.maxHighlightLength?(g=!1,f&&ee(a,b,d,j.pos),j.pos=b.length,k=null):k=c.token(j,d),a.options.addModeClass){var l=z.innerMode(c,d).mode.name;l&&(k=\"m-\"+(k?l+\" \"+k:l))}g&&i==k||(h<j.start&&e(j.start,i),h=j.start,i=k),j.start=j.pos}for(;h<j.pos;){var m=Math.min(j.pos,h+5e4);e(m,i),h=m}}function ce(a,b,c,d){var e=[a.state.modeGen];be(a,b.text,a.doc.mode,c,function(a,b){e.push(a,b)},d);for(var f=0;f<a.state.overlays.length;++f){var g=a.state.overlays[f],h=1,i=0;be(a,b.text,g.mode,!0,function(a,b){for(var c=h;a>i;){var d=e[h];d>a&&e.splice(h,1,a,e[h+1],d),h+=2,i=Math.min(a,d)}if(b)if(g.opaque)e.splice(c,h-c,a,b),h=c+2;else for(;h>c;c+=2){var f=e[c+1];e[c+1]=f?f+\" \"+b:b}})}return e}function de(a,b){return b.styles&&b.styles[0]==a.state.modeGen||(b.styles=ce(a,b,b.stateAfter=hb(a,Ce(b)))),b.styles}function ee(a,b,c,d){var e=a.doc.mode,f=new vd(b,a.options.tabSize);for(f.start=f.pos=d||0,\"\"==b&&e.blankLine&&e.blankLine(c);!f.eol()&&f.pos<=a.options.maxHighlightLength;)e.token(f,c),f.start=f.pos}function he(a,b){if(!a)return null;for(;;){var c=a.match(/(?:^|\\s+)line-(background-)?(\\S+)/);if(!c)break;a=a.slice(0,c.index)+a.slice(c.index+c[0].length);var d=c[1]?\"bgClass\":\"textClass\";null==b[d]?b[d]=c[2]:new RegExp(\"(?:^|s)\"+c[2]+\"(?:$|s)\").test(b[d])||(b[d]+=\" \"+c[2])}if(/^\\s*$/.test(a))return null;var e=b.cm.options.addModeClass?ge:fe;return e[a]||(e[a]=a.replace(/\\S+/g,\"cm-$&\"))}function ie(a,b,c,d){for(var e,f=b,i=!0;e=Od(f);)f=ye(a.doc,e.find().from.line);var j={pre:zf(\"pre\"),col:0,pos:0,measure:null,measuredSomething:!1,cm:a,copyWidgets:d};do{f.text&&(i=!1),j.measure=f==b&&c,j.pos=0,j.addToken=j.measure?le:ke,(g||h)&&a.getOption(\"lineWrapping\")&&(j.addToken=me(j.addToken));var k=oe(f,j,de(a,f));c&&f==b&&!j.measuredSomething&&(c[0]=j.pre.appendChild(Jf(a.display.measure)),j.measuredSomething=!0),k&&(f=ye(a.doc,k.to.line))}while(k);!c||j.measuredSomething||c[0]||(c[0]=j.pre.appendChild(i?zf(\"span\",\"\\xa0\"):Jf(a.display.measure))),j.pre.firstChild||Sd(a.doc,b)||j.pre.appendChild(document.createTextNode(\"\\xa0\"));var l;if(c&&g&&(l=Fe(f))){var m=l.length-1;l[m].from==l[m].to&&--m;var n=l[m],o=l[m-1];if(n.from+1==n.to&&o&&n.level<o.level){var p=c[j.pos-1];p&&p.parentNode.insertBefore(p.measureRight=Jf(a.display.measure),p.nextSibling)}}var q=j.textClass?j.textClass+\" \"+(b.textClass||\"\"):b.textClass;return q&&(j.pre.className=q),$e(a,\"renderLine\",a,b,j.pre),j}function je(a){var b=zf(\"span\",\"\\u2022\",\"cm-invalidchar\");return b.title=\"\\\\u\"+a.charCodeAt(0).toString(16),b}function ke(a,b,c,d,e,f){if(b){var g=a.cm.options.specialChars;if(g.test(b))for(var h=document.createDocumentFragment(),i=0;;){g.lastIndex=i;var j=g.exec(b),k=j?j.index-i:b.length-i;if(k&&(h.appendChild(document.createTextNode(b.slice(i,i+k))),a.col+=k),!j)break;if(i+=k+1,\"\t\"==j[0]){var l=a.cm.options.tabSize,m=l-a.col%l;h.appendChild(zf(\"span\",mf(m),\"cm-tab\")),a.col+=m}else{var n=a.cm.options.specialCharPlaceholder(j[0]);h.appendChild(n),a.col+=1}}else{a.col+=b.length;var h=document.createTextNode(b)}if(c||d||e||a.measure){var o=c||\"\";d&&(o+=d),e&&(o+=e);var n=zf(\"span\",[h],o);return f&&(n.title=f),a.pre.appendChild(n)}a.pre.appendChild(h)\n}}function le(a,c,d,e,f){for(var g=a.cm.options.lineWrapping,h=0;h<c.length;++h){for(var i=0==h,j=h+1;j<c.length&&yf(c.charAt(j));)++j;var k=c.slice(h,j);h=j-1,h&&g&&Ff(c,h)&&a.pre.appendChild(zf(\"wbr\"));var l=a.measure[a.pos],m=a.measure[a.pos]=ke(a,k,d,i&&e,h==c.length-1&&f);l&&(m.leftSide=l.leftSide||l),b&&g&&\" \"==k&&h&&!/\\s/.test(c.charAt(h-1))&&h<c.length-1&&!/\\s/.test(c.charAt(h+1))&&(m.style.whiteSpace=\"normal\"),a.pos+=k.length}c.length&&(a.measuredSomething=!0)}function me(a){function b(a){for(var b=\" \",c=0;c<a.length-2;++c)b+=c%2?\" \":\"\\xa0\";return b+=\" \"}return function(c,d,e,f,g,h){return a(c,d.replace(/ {3,}/g,b),e,f,g,h)}}function ne(a,b,c,d){var e=!d&&c.replacedWith;if(e&&(a.copyWidgets&&(e=e.cloneNode(!0)),a.pre.appendChild(e),a.measure)){if(b)a.measure[a.pos]=e;else{var f=Jf(a.cm.display.measure);if(\"bookmark\"!=c.type||c.insertLeft){if(a.measure[a.pos])return;a.measure[a.pos]=a.pre.insertBefore(f,e)}else a.measure[a.pos]=a.pre.appendChild(f)}a.measuredSomething=!0}a.pos+=b}function oe(a,b,c){var d=a.markedSpans,e=a.text,f=0;if(d)for(var k,m,n,o,p,q,h=e.length,i=0,g=1,j=\"\",l=0;;){if(l==i){m=n=o=p=\"\",q=null,l=1/0;for(var r=[],s=0;s<d.length;++s){var t=d[s],u=t.marker;t.from<=i&&(null==t.to||t.to>i)?(null!=t.to&&l>t.to&&(l=t.to,n=\"\"),u.className&&(m+=\" \"+u.className),u.startStyle&&t.from==i&&(o+=\" \"+u.startStyle),u.endStyle&&t.to==l&&(n+=\" \"+u.endStyle),u.title&&!p&&(p=u.title),u.collapsed&&(!q||Md(q.marker,u)<0)&&(q=t)):t.from>i&&l>t.from&&(l=t.from),\"bookmark\"==u.type&&t.from==i&&u.replacedWith&&r.push(u)}if(q&&(q.from||0)==i&&(ne(b,(null==q.to?h:q.to)-i,q.marker,null==q.from),null==q.to))return q.marker.find();if(!q&&r.length)for(var s=0;s<r.length;++s)ne(b,0,r[s])}if(i>=h)break;for(var v=Math.min(h,l);;){if(j){var w=i+j.length;if(!q){var x=w>v?j.slice(0,v-i):j;b.addToken(b,x,k?k+m:m,o,i+x.length==l?n:\"\",p)}if(w>=v){j=j.slice(v-i),i=v;break}i=w,o=\"\"}j=e.slice(f,f=c[g++]),k=he(c[g++],b)}}else for(var g=1;g<c.length;g+=2)b.addToken(b,e.slice(f,f=c[g]),he(c[g+1],b))}function pe(a,b,c,d,e){function f(a){return c?c[a]:null}function g(a,c,d){_d(a,c,d,e),bf(a,\"change\",a,b)}var h=b.from,i=b.to,j=b.text,k=ye(a,h.line),l=ye(a,i.line),m=nf(j),n=f(j.length-1),o=i.line-h.line;if(0!=h.ch||0!=i.ch||\"\"!=m||a.cm&&!a.cm.options.wholeLineUpdateBefore)if(k==l)if(1==j.length)g(k,k.text.slice(0,h.ch)+m+k.text.slice(i.ch),n);else{for(var r=[],p=1,q=j.length-1;q>p;++p)r.push(new $d(j[p],f(p),e));r.push(new $d(m+k.text.slice(i.ch),n,e)),g(k,k.text.slice(0,h.ch)+j[0],f(0)),a.insert(h.line+1,r)}else if(1==j.length)g(k,k.text.slice(0,h.ch)+j[0]+l.text.slice(i.ch),f(0)),a.remove(h.line+1,o);else{g(k,k.text.slice(0,h.ch)+j[0],f(0)),g(l,m+l.text.slice(i.ch),n);for(var p=1,q=j.length-1,r=[];q>p;++p)r.push(new $d(j[p],f(p),e));o>1&&a.remove(h.line+1,o-1),a.insert(h.line+1,r)}else{for(var p=0,q=j.length-1,r=[];q>p;++p)r.push(new $d(j[p],f(p),e));g(l,l.text,n),o&&a.remove(h.line,o),r.length&&a.insert(h.line,r)}bf(a,\"change\",a,b),Rc(a,d.anchor,d.head,null,!0)}function qe(a){this.lines=a,this.parent=null;for(var b=0,c=a.length,d=0;c>b;++b)a[b].parent=this,d+=a[b].height;this.height=d}function re(a){this.children=a;for(var b=0,c=0,d=0,e=a.length;e>d;++d){var f=a[d];b+=f.chunkSize(),c+=f.height,f.parent=this}this.size=b,this.height=c,this.parent=null}function we(a,b,c){function d(a,e,f){if(a.linked)for(var g=0;g<a.linked.length;++g){var h=a.linked[g];if(h.doc!=e){var i=f&&h.sharedHist;(!c||i)&&(b(h.doc,i),d(h.doc,a,i))}}}d(a,null,!0)}function xe(a,b){if(b.cm)throw new Error(\"This document is already in use.\");a.doc=b,b.cm=a,F(a),B(a),a.options.lineWrapping||L(a),a.options.mode=b.modeOption,Lb(a)}function ye(a,b){for(b-=a.first;!a.lines;)for(var c=0;;++c){var d=a.children[c],e=d.chunkSize();if(e>b){a=d;break}b-=e}return a.lines[b]}function ze(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line+1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function Ae(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function Be(a,b){for(var c=b-a.height,d=a;d;d=d.parent)d.height+=c}function Ce(a){if(null==a.parent)return null;for(var b=a.parent,c=pf(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first}function De(a,b){var c=a.first;a:do{for(var d=0,e=a.children.length;e>d;++d){var f=a.children[d],g=f.height;if(g>b){a=f;continue a}b-=g,c+=f.chunkSize()}return c}while(!a.lines);for(var d=0,e=a.lines.length;e>d;++d){var h=a.lines[d],i=h.height;if(i>b)break;b-=i}return c+d}function Ee(a,b){b=Rd(a.doc,b);for(var c=0,d=b.parent,e=0;e<d.lines.length;++e){var f=d.lines[e];if(f==b)break;c+=f.height}for(var g=d.parent;g;d=g,g=d.parent)for(var e=0;e<g.children.length;++e){var h=g.children[e];if(h==d)break;c+=h.height}return c}function Fe(a){var b=a.order;return null==b&&(b=a.order=_f(a.text)),b}function Ge(a){return{done:[],undone:[],undoDepth:1/0,lastTime:0,lastOp:null,lastOrigin:null,generation:a||1,maxGeneration:a||1}}function He(a,b,c,d){var e=b[\"spans_\"+a.id],f=0;a.iter(Math.max(a.first,c),Math.min(a.first+a.size,d),function(c){c.markedSpans&&((e||(e=b[\"spans_\"+a.id]={}))[f]=c.markedSpans),++f})}function Ie(a,b){var c={line:b.from.line,ch:b.from.ch},d={from:c,to:vc(b),text:ze(a,b.from,b.to)};return He(a,d,b.from.line,b.to.line+1),we(a,function(a){He(a,d,b.from.line,b.to.line+1)},!0),d}function Je(a,b,c,d){var e=a.history;e.undone.length=0;var f=+new Date,g=nf(e.done);if(g&&(e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&(\"+\"==b.origin.charAt(0)&&a.cm&&e.lastTime>f-a.cm.options.historyEventDelay||\"*\"==b.origin.charAt(0)))){var h=nf(g.changes);Hc(b.from,b.to)&&Hc(b.from,h.to)?h.to=vc(b):g.changes.push(Ie(a,b)),g.anchorAfter=c.anchor,g.headAfter=c.head}else for(g={changes:[Ie(a,b)],generation:e.generation,anchorBefore:a.sel.anchor,headBefore:a.sel.head,anchorAfter:c.anchor,headAfter:c.head},e.done.push(g);e.done.length>e.undoDepth;)e.done.shift();e.generation=++e.maxGeneration,e.lastTime=f,e.lastOp=d,e.lastOrigin=b.origin,h||$e(a,\"historyAdded\")}function Ke(a){if(!a)return null;for(var c,b=0;b<a.length;++b)a[b].marker.explicitlyCleared?c||(c=a.slice(0,b)):c&&c.push(a[b]);return c?c.length?c:null:a}function Le(a,b){var c=b[\"spans_\"+a.id];if(!c)return null;for(var d=0,e=[];d<b.text.length;++d)e.push(Ke(c[d]));return e}function Me(a,b){for(var c=0,d=[];c<a.length;++c){var e=a[c],f=e.changes,g=[];d.push({changes:g,anchorBefore:e.anchorBefore,headBefore:e.headBefore,anchorAfter:e.anchorAfter,headAfter:e.headAfter});for(var h=0;h<f.length;++h){var j,i=f[h];if(g.push({from:i.from,to:i.to,text:i.text}),b)for(var k in i)(j=k.match(/^spans_(\\d+)$/))&&pf(b,Number(j[1]))>-1&&(nf(g)[k]=i[k],delete i[k])}}return d}function Ne(a,b,c,d){c<a.line?a.line+=d:b<a.line&&(a.line=b,a.ch=0)}function Oe(a,b,c,d){for(var e=0;e<a.length;++e){for(var f=a[e],g=!0,h=0;h<f.changes.length;++h){var i=f.changes[h];if(f.copied||(i.from=Kc(i.from),i.to=Kc(i.to)),c<i.from.line)i.from.line+=d,i.to.line+=d;else if(b<=i.to.line){g=!1;break}}f.copied||(f.anchorBefore=Kc(f.anchorBefore),f.headBefore=Kc(f.headBefore),f.anchorAfter=Kc(f.anchorAfter),f.readAfter=Kc(f.headAfter),f.copied=!0),g?(Ne(f.anchorBefore),Ne(f.headBefore),Ne(f.anchorAfter),Ne(f.headAfter)):(a.splice(0,e+1),e=0)}}function Pe(a,b){var c=b.from.line,d=b.to.line,e=b.text.length-(d-c)-1;Oe(a.done,c,d,e),Oe(a.undone,c,d,e)}function Qe(){Ve(this)}function Re(a){return a.stop||(a.stop=Qe),a}function Se(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function Te(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0}function Ue(a){return null!=a.defaultPrevented?a.defaultPrevented:0==a.returnValue}function Ve(a){Se(a),Te(a)}function We(a){return a.target||a.srcElement}function Xe(a){var b=a.which;return null==b&&(1&a.button?b=1:2&a.button?b=3:4&a.button&&(b=2)),s&&a.ctrlKey&&1==b&&(b=3),b}function Ye(a,b,c){if(a.addEventListener)a.addEventListener(b,c,!1);else if(a.attachEvent)a.attachEvent(\"on\"+b,c);else{var d=a._handlers||(a._handlers={}),e=d[b]||(d[b]=[]);e.push(c)}}function Ze(a,b,c){if(a.removeEventListener)a.removeEventListener(b,c,!1);else if(a.detachEvent)a.detachEvent(\"on\"+b,c);else{var d=a._handlers&&a._handlers[b];if(!d)return;for(var e=0;e<d.length;++e)if(d[e]==c){d.splice(e,1);break}}}function $e(a,b){var c=a._handlers&&a._handlers[b];if(c)for(var d=Array.prototype.slice.call(arguments,2),e=0;e<c.length;++e)c[e].apply(null,d)}function bf(a,b){function e(a){return function(){a.apply(null,d)}}var c=a._handlers&&a._handlers[b];if(c){var d=Array.prototype.slice.call(arguments,2);_e||(++af,_e=[],setTimeout(df,0));for(var f=0;f<c.length;++f)_e.push(e(c[f]))}}function cf(a,b,c){return $e(a,c||b.type,a,b),Ue(b)||b.codemirrorIgnore}function df(){--af;var a=_e;_e=null;for(var b=0;b<a.length;++b)a[b]()}function ef(a,b){var c=a._handlers&&a._handlers[b];return c&&c.length>0}function ff(a){a.prototype.on=function(a,b){Ye(this,a,b)},a.prototype.off=function(a,b){Ze(this,a,b)}}function jf(){this.id=null}function kf(a,b,c,d,e){null==b&&(b=a.search(/[^\\s\\u00a0]/),-1==b&&(b=a.length));for(var f=d||0,g=e||0;b>f;++f)\"\t\"==a.charAt(f)?g+=c-g%c:++g;return g}function mf(a){for(;lf.length<=a;)lf.push(nf(lf)+\" \");return lf[a]}function nf(a){return a[a.length-1]}function of(a){if(q)a.selectionStart=0,a.selectionEnd=a.value.length;else try{a.select()}catch(b){}}function pf(a,b){if(a.indexOf)return a.indexOf(b);for(var c=0,d=a.length;d>c;++c)if(a[c]==b)return c;return-1}function qf(a,b){function c(){}c.prototype=a;var d=new c;return b&&rf(b,d),d}function rf(a,b){b||(b={});for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function sf(a){for(var b=[],c=0;a>c;++c)b.push(void 0);return b}function tf(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}}function vf(a){return/\\w/.test(a)||a>\"\\x80\"&&(a.toUpperCase()!=a.toLowerCase()||uf.test(a))}function wf(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function yf(a){return a.charCodeAt(0)>=768&&xf.test(a)}function zf(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),\"string\"==typeof b)Cf(e,b);else if(b)for(var f=0;f<b.length;++f)e.appendChild(b[f]);return e}function Af(a){for(var b=a.childNodes.length;b>0;--b)a.removeChild(a.firstChild);return a}function Bf(a,b){return Af(a).appendChild(b)}function Cf(a,b){d?(a.innerHTML=\"\",a.appendChild(document.createTextNode(b))):a.textContent=b}function Df(a){return a.getBoundingClientRect()}function Ff(){return!1}function Hf(a){if(null!=Gf)return Gf;var b=zf(\"div\",null,null,\"width: 50px; height: 50px; overflow-x: scroll\");return Bf(a,b),b.offsetWidth&&(Gf=b.offsetHeight-b.clientHeight),Gf||0}function Jf(a){if(null==If){var b=zf(\"span\",\"\\u200b\");Bf(a,zf(\"span\",[b,document.createTextNode(\"x\")])),0!=a.firstChild.offsetHeight&&(If=b.offsetWidth<=1&&b.offsetHeight>2&&!c)}return If?zf(\"span\",\"\\u200b\"):zf(\"span\",\"\\xa0\",null,\"display: inline-block; width: 1px; margin-right: -1px\")}function Of(a,b,c,d){if(!a)return d(b,c,\"ltr\");for(var e=!1,f=0;f<a.length;++f){var g=a[f];(g.from<c&&g.to>b||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?\"rtl\":\"ltr\"),e=!0)}e||d(b,c,\"ltr\")}function Pf(a){return a.level%2?a.to:a.from}function Qf(a){return a.level%2?a.from:a.to}function Rf(a){var b=Fe(a);return b?Pf(b[0]):0}function Sf(a){var b=Fe(a);return b?Qf(nf(b)):a.text.length}function Tf(a,b){var c=ye(a.doc,b),d=Rd(a.doc,c);d!=c&&(b=Ce(d));var e=Fe(d),f=e?e[0].level%2?Sf(d):Rf(d):0;return Gc(b,f)}function Uf(a,b){for(var c,d;c=Pd(d=ye(a.doc,b));)b=c.find().to.line;var e=Fe(d),f=e?e[0].level%2?Rf(d):Sf(d):d.text.length;return Gc(b,f)}function Vf(a,b,c){var d=a[0].level;return b==d?!0:c==d?!1:c>b}function Xf(a,b){Wf=null;for(var d,c=0;c<a.length;++c){var e=a[c];if(e.from<b&&e.to>b)return c;if(e.from==b||e.to==b){if(null!=d)return Vf(a,e.level,a[d].level)?(e.from!=e.to&&(Wf=d),c):(e.from!=e.to&&(Wf=c),d);d=c}}return d}function Yf(a,b,c,d){if(!d)return b+c;do b+=c;while(b>0&&yf(a.text.charAt(b)));return b}function Zf(a,b,c,d){var e=Fe(a);if(!e)return $f(a,b,c,d);for(var f=Xf(e,b),g=e[f],h=Yf(a,b,g.level%2?-c:c,d);;){if(h>g.from&&h<g.to)return h;if(h==g.from||h==g.to)return Xf(e,h)==f?h:(g=e[f+=c],c>0==g.level%2?g.to:g.from);if(g=e[f+=c],!g)return null;h=c>0==g.level%2?Yf(a,g.to,-1,d):Yf(a,g.from,1,d)}}function $f(a,b,c,d){var e=b+c;if(d)for(;e>0&&yf(a.text.charAt(e));)e+=c;return 0>e||e>a.text.length?null:e}var a=/gecko\\/\\d/i.test(navigator.userAgent),b=/MSIE \\d/.test(navigator.userAgent),c=b&&(null==document.documentMode||document.documentMode<8),d=b&&(null==document.documentMode||document.documentMode<9),e=b&&(null==document.documentMode||document.documentMode<10),f=/Trident\\/([7-9]|\\d{2,})\\./.test(navigator.userAgent),g=b||f,h=/WebKit\\//.test(navigator.userAgent),i=h&&/Qt\\/\\d+\\.\\d+/.test(navigator.userAgent),j=/Chrome\\//.test(navigator.userAgent),k=/Opera\\//.test(navigator.userAgent),l=/Apple Computer/.test(navigator.vendor),m=/KHTML\\//.test(navigator.userAgent),n=/Mac OS X 1\\d\\D([7-9]|\\d\\d)\\D/.test(navigator.userAgent),o=/Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(navigator.userAgent),p=/PhantomJS/.test(navigator.userAgent),q=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\\/\\w+/.test(navigator.userAgent),r=q||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent),s=q||/Mac/.test(navigator.platform),t=/win/i.test(navigator.platform),u=k&&navigator.userAgent.match(/Version\\/(\\d*\\.\\d*)/);u&&(u=Number(u[1])),u&&u>=15&&(k=!1,h=!0);var Cb,Wb,Xb,v=s&&(i||k&&(null==u||12.11>u)),w=a||g&&!d,x=!1,y=!1,Fb=0,ac=0,fc=0,gc=null;g?gc=-.53:a?gc=15:j?gc=-.7:l&&(gc=-1/3);var kc,tc,oc=null,vc=z.changeEnd=function(a){return a.text?Gc(a.from.line+a.text.length-1,nf(a.text).length+(1==a.text.length?a.from.ch:0)):a.to};z.Pos=Gc,z.prototype={constructor:z,focus:function(){window.focus(),Qb(this),Nb(this)},setOption:function(a,b){var c=this.options,d=c[a];(c[a]!=b||\"mode\"==a)&&(c[a]=b,ed.hasOwnProperty(a)&&Ib(this,ed[a])(this,b,d))},getOption:function(a){return this.options[a]},getDoc:function(){return this.doc},addKeyMap:function(a,b){this.state.keyMaps[b?\"push\":\"unshift\"](a)},removeKeyMap:function(a){for(var b=this.state.keyMaps,c=0;c<b.length;++c)if(b[c]==a||\"string\"!=typeof b[c]&&b[c].name==a)return b.splice(c,1),!0},addOverlay:Ib(null,function(a,b){var c=a.token?a:z.getMode(this.options,a);if(c.startState)throw new Error(\"Overlays may not be stateful.\");this.state.overlays.push({mode:c,modeSpec:a,opaque:b&&b.opaque}),this.state.modeGen++,Lb(this)}),removeOverlay:Ib(null,function(a){for(var b=this.state.overlays,c=0;c<b.length;++c){var d=b[c].modeSpec;if(d==a||\"string\"==typeof a&&d.name==a)return b.splice(c,1),this.state.modeGen++,Lb(this),void 0}}),indentLine:Ib(null,function(a,b,c){\"string\"!=typeof b&&\"number\"!=typeof b&&(b=null==b?this.options.smartIndent?\"smart\":\"prev\":b?\"add\":\"subtract\"),Oc(this.doc,a)&&$c(this,a,b,c)}),indentSelection:Ib(null,function(a){var b=this.doc.sel;if(Hc(b.from,b.to))return $c(this,b.from.line,a,!0);for(var c=b.to.line-(b.to.ch?0:1),d=b.from.line;c>=d;++d)$c(this,d,a)}),getTokenAt:function(a,b){var c=this.doc;a=Mc(c,a);for(var d=hb(this,a.line,b),e=this.doc.mode,f=ye(c,a.line),g=new vd(f.text,this.options.tabSize);g.pos<a.ch&&!g.eol();){g.start=g.pos;var h=e.token(g,d)}return{start:g.start,end:g.pos,string:g.current(),className:h||null,type:h||null,state:d}},getTokenTypeAt:function(a){a=Mc(this.doc,a);var b=de(this,ye(this.doc,a.line)),c=0,d=(b.length-1)/2,e=a.ch;if(0==e)return b[2];for(;;){var f=c+d>>1;if((f?b[2*f-1]:0)>=e)d=f;else{if(!(b[2*f+1]<e))return b[2*f+2];c=f+1}}},getModeAt:function(a){var b=this.doc.mode;return b.innerMode?z.innerMode(b,this.getTokenAt(a).state).mode:b},getHelper:function(a,b){return this.getHelpers(a,b)[0]},getHelpers:function(a,b){var c=[];if(!md.hasOwnProperty(b))return md;var d=md[b],e=this.getModeAt(a);if(\"string\"==typeof e[b])d[e[b]]&&c.push(d[e[b]]);else if(e[b])for(var f=0;f<e[b].length;f++){var g=d[e[b][f]];g&&c.push(g)}else e.helperType&&d[e.helperType]?c.push(d[e.helperType]):d[e.name]&&c.push(d[e.name]);for(var f=0;f<d._global.length;f++){var h=d._global[f];h.pred(e,this)&&-1==pf(c,h.val)&&c.push(h.val)}return c},getStateAfter:function(a,b){var c=this.doc;return a=Lc(c,null==a?c.first+c.size-1:a),hb(this,a+1,b)},cursorCoords:function(a,b){var c,d=this.doc.sel;return c=null==a?d.head:\"object\"==typeof a?Mc(this.doc,a):a?d.from:d.to,yb(this,c,b||\"page\")},charCoords:function(a,b){return xb(this,Mc(this.doc,a),b||\"page\")},coordsChar:function(a,b){return a=wb(this,a,b||\"page\"),Ab(this,a.left,a.top)},lineAtHeight:function(a,b){return a=wb(this,{top:a,left:0},b||\"page\").top,De(this.doc,a+this.display.viewOffset)},heightAtLine:function(a,b){var c=!1,d=this.doc.first+this.doc.size-1;a<this.doc.first?a=this.doc.first:a>d&&(a=d,c=!0);var e=ye(this.doc,a);return vb(this,ye(this.doc,a),{top:0,left:0},b||\"page\").top+(c?e.height:0)},defaultTextHeight:function(){return Db(this.display)},defaultCharWidth:function(){return Eb(this.display)},setGutterMarker:Ib(null,function(a,b,c){return _c(this,a,function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&wf(d)&&(a.gutterMarkers=null),!0})}),clearGutter:Ib(null,function(a){var b=this,c=b.doc,d=c.first;c.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&(c.gutterMarkers[a]=null,Lb(b,d,d+1),wf(c.gutterMarkers)&&(c.gutterMarkers=null)),++d})}),addLineClass:Ib(null,function(a,b,c){return _c(this,a,function(a){var d=\"text\"==b?\"textClass\":\"background\"==b?\"bgClass\":\"wrapClass\";if(a[d]){if(new RegExp(\"(?:^|\\\\s)\"+c+\"(?:$|\\\\s)\").test(a[d]))return!1;a[d]+=\" \"+c}else a[d]=c;return!0})}),removeLineClass:Ib(null,function(a,b,c){return _c(this,a,function(a){var d=\"text\"==b?\"textClass\":\"background\"==b?\"bgClass\":\"wrapClass\",e=a[d];if(!e)return!1;if(null==c)a[d]=null;else{var f=e.match(new RegExp(\"(?:^|\\\\s+)\"+c+\"(?:$|\\\\s+)\"));if(!f)return!1;var g=f.index+f[0].length;a[d]=e.slice(0,f.index)+(f.index&&g!=e.length?\" \":\"\")+e.slice(g)||null}return!0})}),addLineWidget:Ib(null,function(a,b,c){return Zd(this,a,b,c)}),removeLineWidget:function(a){a.clear()},lineInfo:function(a){if(\"number\"==typeof a){if(!Oc(this.doc,a))return null;var b=a;if(a=ye(this.doc,a),!a)return null}else{var b=Ce(a);if(null==b)return null}return{line:b,handle:a,text:a.text,gutterMarkers:a.gutterMarkers,textClass:a.textClass,bgClass:a.bgClass,wrapClass:a.wrapClass,widgets:a.widgets}},getViewport:function(){return{from:this.display.showingFrom,to:this.display.showingTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=yb(this,Mc(this.doc,a));var g=a.bottom,h=a.left;if(b.style.position=\"absolute\",f.sizer.appendChild(b),\"over\"==d)g=a.top;else if(\"above\"==d||\"near\"==d){var i=Math.max(f.wrapper.clientHeight,this.doc.height),j=Math.max(f.sizer.clientWidth,f.lineSpace.clientWidth);(\"above\"==d||a.bottom+b.offsetHeight>i)&&a.top>b.offsetHeight?g=a.top-b.offsetHeight:a.bottom+b.offsetHeight<=i&&(g=a.bottom),h+b.offsetWidth>j&&(h=j-b.offsetWidth)}b.style.top=g+\"px\",b.style.left=b.style.right=\"\",\"right\"==e?(h=f.sizer.clientWidth-b.offsetWidth,b.style.right=\"0px\"):(\"left\"==e?h=0:\"middle\"==e&&(h=(f.sizer.clientWidth-b.offsetWidth)/2),b.style.left=h+\"px\"),c&&Wc(this,h,g,h+b.offsetWidth,g+b.offsetHeight)},triggerOnKeyDown:Ib(null,pc),triggerOnKeyPress:Ib(null,qc),triggerOnKeyUp:Ib(null,nc),execCommand:function(a){return pd.hasOwnProperty(a)?pd[a](this):void 0},findPosH:function(a,b,c,d){var e=1;0>b&&(e=-1,b=-b);for(var f=0,g=Mc(this.doc,a);b>f&&(g=ad(this.doc,g,e,c,d),!g.hitSide);++f);return g},moveH:Ib(null,function(a,b){var d,c=this.doc.sel;d=c.shift||c.extend||Hc(c.from,c.to)?ad(this.doc,c.head,a,b,this.options.rtlMoveVisually):0>a?c.from:c.to,Pc(this.doc,d,d,a)}),deleteH:Ib(null,function(a,b){var c=this.doc.sel;Hc(c.from,c.to)?Fc(this.doc,\"\",c.from,ad(this.doc,c.head,a,b,!1),\"+delete\"):Fc(this.doc,\"\",c.from,c.to,\"+delete\"),this.curOp.userSelChange=!0}),findPosV:function(a,b,c,d){var e=1,f=d;0>b&&(e=-1,b=-b);for(var g=0,h=Mc(this.doc,a);b>g;++g){var i=yb(this,h,\"div\");if(null==f?f=i.left:i.left=f,h=bd(this,i,e,c),h.hitSide)break}return h},moveV:Ib(null,function(a,b){var d,e,c=this.doc.sel;if(c.shift||c.extend||Hc(c.from,c.to)){var f=yb(this,c.head,\"div\");null!=c.goalColumn&&(f.left=c.goalColumn),d=bd(this,f,a,b),\"page\"==b&&Zc(this,0,xb(this,d,\"div\").top-f.top),e=f.left}else d=0>a?c.from:c.to;Pc(this.doc,d,d,a),null!=e&&(c.goalColumn=e)}),toggleOverwrite:function(a){(null==a||a!=this.state.overwrite)&&((this.state.overwrite=!this.state.overwrite)?this.display.cursor.className+=\" CodeMirror-overwrite\":this.display.cursor.className=this.display.cursor.className.replace(\" CodeMirror-overwrite\",\"\"),$e(this,\"overwriteToggle\",this,this.state.overwrite))},hasFocus:function(){return document.activeElement==this.display.input},scrollTo:Ib(null,function(a,b){Yc(this,a,b)}),getScrollInfo:function(){var a=this.display.scroller,b=gf;return{left:a.scrollLeft,top:a.scrollTop,height:a.scrollHeight-b,width:a.scrollWidth-b,clientHeight:a.clientHeight-b,clientWidth:a.clientWidth-b}},scrollIntoView:Ib(null,function(a,b){null==a?a={from:this.doc.sel.head,to:null}:\"number\"==typeof a?a={from:Gc(a,0),to:null}:null==a.from&&(a={from:a,to:null}),a.to||(a.to=a.from),b||(b=0);var c=a;null!=a.from.line&&(this.curOp.scrollToPos={from:a.from,to:a.to,margin:b},c={from:yb(this,a.from),to:yb(this,a.to)});var d=Xc(this,Math.min(c.from.left,c.to.left),Math.min(c.from.top,c.to.top)-b,Math.max(c.from.right,c.to.right),Math.max(c.from.bottom,c.to.bottom)+b);Yc(this,d.scrollLeft,d.scrollTop)}),setSize:Ib(null,function(a,b){function c(a){return\"number\"==typeof a||/^\\d+$/.test(String(a))?a+\"px\":a}null!=a&&(this.display.wrapper.style.width=c(a)),null!=b&&(this.display.wrapper.style.height=c(b)),this.options.lineWrapping&&(this.display.measureLineCache.length=this.display.measureLineCachePos=0),this.curOp.forceUpdate=!0,$e(this,\"refresh\",this)}),operation:function(a){return Kb(this,a)},refresh:Ib(null,function(){var a=this.display.cachedTextHeight;sb(this),Yc(this,this.doc.scrollLeft,this.doc.scrollTop),Lb(this),(null==a||Math.abs(a-Db(this.display))>.5)&&F(this),$e(this,\"refresh\",this)}),swapDoc:Ib(null,function(a){var b=this.doc;return b.cm=null,xe(this,a),sb(this),Pb(this,!0),Yc(this,a.scrollLeft,a.scrollTop),bf(this,\"swapDoc\",this,b),b}),getInputField:function(){return this.display.input},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},ff(z);var ed=z.optionHandlers={},fd=z.defaults={},hd=z.Init={toString:function(){return\"CodeMirror.Init\"}};gd(\"value\",\"\",function(a,b){a.setValue(b)},!0),gd(\"mode\",null,function(a,b){a.doc.modeOption=b,B(a)},!0),gd(\"indentUnit\",2,B,!0),gd(\"indentWithTabs\",!1),gd(\"smartIndent\",!0),gd(\"tabSize\",4,function(a){C(a),sb(a),Lb(a)},!0),gd(\"specialChars\",/[\\t\\u0000-\\u0019\\u00ad\\u200b\\u2028\\u2029\\ufeff]/g,function(a,b){a.options.specialChars=new RegExp(b.source+(b.test(\"\t\")?\"\":\"|\t\"),\"g\"),a.refresh()},!0),gd(\"specialCharPlaceholder\",je,function(a){a.refresh()},!0),gd(\"electricChars\",!0),gd(\"rtlMoveVisually\",!t),gd(\"wholeLineUpdateBefore\",!0),gd(\"theme\",\"default\",function(a){H(a),I(a)},!0),gd(\"keyMap\",\"default\",G),gd(\"extraKeys\",null),gd(\"onKeyEvent\",null),gd(\"onDragEvent\",null),gd(\"lineWrapping\",!1,D,!0),gd(\"gutters\",[],function(a){M(a.options),I(a)},!0),gd(\"fixedGutter\",!0,function(a,b){a.display.gutters.style.left=b?S(a.display)+\"px\":\"0\",a.refresh()},!0),gd(\"coverGutterNextToScrollbar\",!1,N,!0),gd(\"lineNumbers\",!1,function(a){M(a.options),I(a)},!0),gd(\"firstLineNumber\",1,I,!0),gd(\"lineNumberFormatter\",function(a){return a},I,!0),gd(\"showCursorWhenSelecting\",!1,ab,!0),gd(\"resetSelectionOnContextMenu\",!0),gd(\"readOnly\",!1,function(a,b){\"nocursor\"==b?(sc(a),a.display.input.blur(),a.display.disabled=!0):(a.display.disabled=!1,b||Pb(a,!0))}),gd(\"disableInput\",!1,function(a,b){b||Pb(a,!0)},!0),gd(\"dragDrop\",!0),gd(\"cursorBlinkRate\",530),gd(\"cursorScrollMargin\",0),gd(\"cursorHeight\",1),gd(\"workTime\",100),gd(\"workDelay\",100),gd(\"flattenSpans\",!0,C,!0),gd(\"addModeClass\",!1,C,!0),gd(\"pollInterval\",100),gd(\"undoDepth\",40,function(a,b){a.doc.history.undoDepth=b}),gd(\"historyEventDelay\",500),gd(\"viewportMargin\",10,function(a){a.refresh()},!0),gd(\"maxHighlightLength\",1e4,C,!0),gd(\"crudeMeasuringFrom\",1e4),gd(\"moveInputWithCursor\",!0,function(a,b){b||(a.display.inputDiv.style.top=a.display.inputDiv.style.left=0)}),gd(\"tabindex\",null,function(a,b){a.display.input.tabIndex=b||\"\"}),gd(\"autofocus\",null);var id=z.modes={},jd=z.mimeModes={};z.defineMode=function(a,b){if(z.defaults.mode||\"null\"==a||(z.defaults.mode=a),arguments.length>2){b.dependencies=[];for(var c=2;c<arguments.length;++c)b.dependencies.push(arguments[c])}id[a]=b},z.defineMIME=function(a,b){jd[a]=b},z.resolveMode=function(a){if(\"string\"==typeof a&&jd.hasOwnProperty(a))a=jd[a];else if(a&&\"string\"==typeof a.name&&jd.hasOwnProperty(a.name)){var b=jd[a.name];\"string\"==typeof b&&(b={name:b}),a=qf(b,a),a.name=b.name}else if(\"string\"==typeof a&&/^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(a))return z.resolveMode(\"application/xml\");return\"string\"==typeof a?{name:a}:a||{name:\"null\"}},z.getMode=function(a,b){var b=z.resolveMode(b),c=id[b.name];if(!c)return z.getMode(a,\"text/plain\");var d=c(a,b);if(kd.hasOwnProperty(b.name)){var e=kd[b.name];for(var f in e)e.hasOwnProperty(f)&&(d.hasOwnProperty(f)&&(d[\"_\"+f]=d[f]),d[f]=e[f])}if(d.name=b.name,b.helperType&&(d.helperType=b.helperType),b.modeProps)for(var f in b.modeProps)d[f]=b.modeProps[f];return d},z.defineMode(\"null\",function(){return{token:function(a){a.skipToEnd()}}}),z.defineMIME(\"text/plain\",\"null\");var kd=z.modeExtensions={};z.extendMode=function(a,b){var c=kd.hasOwnProperty(a)?kd[a]:kd[a]={};rf(b,c)},z.defineExtension=function(a,b){z.prototype[a]=b},z.defineDocExtension=function(a,b){te.prototype[a]=b},z.defineOption=gd;var ld=[];z.defineInitHook=function(a){ld.push(a)};var md=z.helpers={};z.registerHelper=function(a,b,c){md.hasOwnProperty(a)||(md[a]=z[a]={_global:[]}),md[a][b]=c},z.registerGlobalHelper=function(a,b,c,d){z.registerHelper(a,b,d),md[a]._global.push({pred:c,val:d})},z.isWordChar=vf,z.copyState=nd,z.startState=od,z.innerMode=function(a,b){for(;a.innerMode;){var c=a.innerMode(b);if(!c||c.mode==a)break;b=c.state,a=c.mode}return c||{mode:a,state:b}};var pd=z.commands={selectAll:function(a){a.setSelection(Gc(a.firstLine(),0),Gc(a.lastLine()))},killLine:function(a){var b=a.getCursor(!0),c=a.getCursor(!1),d=!Hc(b,c);d||a.getLine(b.line).length!=b.ch?a.replaceRange(\"\",b,d?c:Gc(b.line),\"+delete\"):a.replaceRange(\"\",b,Gc(b.line+1,0),\"+delete\")},deleteLine:function(a){var b=a.getCursor().line;a.replaceRange(\"\",Gc(b,0),Gc(b+1,0),\"+delete\")},delLineLeft:function(a){var b=a.getCursor();a.replaceRange(\"\",Gc(b.line,0),b,\"+delete\")},undo:function(a){a.undo()},redo:function(a){a.redo()},goDocStart:function(a){a.extendSelection(Gc(a.firstLine(),0))},goDocEnd:function(a){a.extendSelection(Gc(a.lastLine()))},goLineStart:function(a){a.extendSelection(Tf(a,a.getCursor().line))},goLineStartSmart:function(a){var b=a.getCursor(),c=Tf(a,b.line),d=a.getLineHandle(c.line),e=Fe(d);if(e&&0!=e[0].level)a.extendSelection(c);else{var f=Math.max(0,d.text.search(/\\S/)),g=b.line==c.line&&b.ch<=f&&b.ch;a.extendSelection(Gc(c.line,g?0:f))}},goLineEnd:function(a){a.extendSelection(Uf(a,a.getCursor().line))},goLineRight:function(a){var b=a.charCoords(a.getCursor(),\"div\").top+5;a.extendSelection(a.coordsChar({left:a.display.lineDiv.offsetWidth+100,top:b},\"div\"))},goLineLeft:function(a){var b=a.charCoords(a.getCursor(),\"div\").top+5;a.extendSelection(a.coordsChar({left:0,top:b},\"div\"))},goLineUp:function(a){a.moveV(-1,\"line\")},goLineDown:function(a){a.moveV(1,\"line\")},goPageUp:function(a){a.moveV(-1,\"page\")},goPageDown:function(a){a.moveV(1,\"page\")},goCharLeft:function(a){a.moveH(-1,\"char\")},goCharRight:function(a){a.moveH(1,\"char\")},goColumnLeft:function(a){a.moveH(-1,\"column\")},goColumnRight:function(a){a.moveH(1,\"column\")},goWordLeft:function(a){a.moveH(-1,\"word\")},goGroupRight:function(a){a.moveH(1,\"group\")},goGroupLeft:function(a){a.moveH(-1,\"group\")},goWordRight:function(a){a.moveH(1,\"word\")},delCharBefore:function(a){a.deleteH(-1,\"char\")},delCharAfter:function(a){a.deleteH(1,\"char\")},delWordBefore:function(a){a.deleteH(-1,\"word\")},delWordAfter:function(a){a.deleteH(1,\"word\")},delGroupBefore:function(a){a.deleteH(-1,\"group\")},delGroupAfter:function(a){a.deleteH(1,\"group\")},indentAuto:function(a){a.indentSelection(\"smart\")},indentMore:function(a){a.indentSelection(\"add\")},indentLess:function(a){a.indentSelection(\"subtract\")},insertTab:function(a){a.replaceSelection(\"\t\",\"end\",\"+input\")},defaultTab:function(a){a.somethingSelected()?a.indentSelection(\"add\"):a.replaceSelection(\"\t\",\"end\",\"+input\")},transposeChars:function(a){var b=a.getCursor(),c=a.getLine(b.line);b.ch>0&&b.ch<c.length-1&&a.replaceRange(c.charAt(b.ch)+c.charAt(b.ch-1),Gc(b.line,b.ch-1),Gc(b.line,b.ch+1))},newlineAndIndent:function(a){Ib(a,function(){a.replaceSelection(\"\\n\",\"end\",\"+input\"),a.indentLine(a.getCursor().line,null,!0)})()},toggleOverwrite:function(a){a.toggleOverwrite()}},qd=z.keyMap={};qd.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\"},qd.pcDefault={\"Ctrl-A\":\"selectAll\",\"Ctrl-D\":\"deleteLine\",\"Ctrl-Z\":\"undo\",\"Shift-Ctrl-Z\":\"redo\",\"Ctrl-Y\":\"redo\",\"Ctrl-Home\":\"goDocStart\",\"Ctrl-Up\":\"goDocStart\",\"Ctrl-End\":\"goDocEnd\",\"Ctrl-Down\":\"goDocEnd\",\"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\",fallthrough:\"basic\"},qd.macDefault={\"Cmd-A\":\"selectAll\",\"Cmd-D\":\"deleteLine\",\"Cmd-Z\":\"undo\",\"Shift-Cmd-Z\":\"redo\",\"Cmd-Y\":\"redo\",\"Cmd-Up\":\"goDocStart\",\"Cmd-End\":\"goDocEnd\",\"Cmd-Down\":\"goDocEnd\",\"Alt-Left\":\"goGroupLeft\",\"Alt-Right\":\"goGroupRight\",\"Cmd-Left\":\"goLineStart\",\"Cmd-Right\":\"goLineEnd\",\"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\":\"delLineLeft\",fallthrough:[\"basic\",\"emacsy\"]},qd[\"default\"]=s?qd.macDefault:qd.pcDefault,qd.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\"},z.lookupKey=sd,z.isModifierKey=td,z.keyName=ud,z.fromTextArea=function(a,b){function e(){a.value=i.getValue()}if(b||(b={}),b.value=a.value,!b.tabindex&&a.tabindex&&(b.tabindex=a.tabindex),!b.placeholder&&a.placeholder&&(b.placeholder=a.placeholder),null==b.autofocus){var c=document.body;try{c=document.activeElement}catch(d){}b.autofocus=c==a||null!=a.getAttribute(\"autofocus\")&&c==document.body}if(a.form&&(Ye(a.form,\"submit\",e),!b.leaveSubmitMethodAlone)){var f=a.form,g=f.submit;try{var h=f.submit=function(){e(),f.submit=g,f.submit(),f.submit=h}}catch(d){}}a.style.display=\"none\";var i=z(function(b){a.parentNode.insertBefore(b,a.nextSibling)},b);return i.save=e,i.getTextArea=function(){return a},i.toTextArea=function(){e(),a.parentNode.removeChild(i.getWrapperElement()),a.style.display=\"\",a.form&&(Ze(a.form,\"submit\",e),\"function\"==typeof a.form.submit&&(a.form.submit=g))},i},vd.prototype={eol:function(){return this.pos>=this.string.length\n},sol:function(){return this.pos==this.lineStart},peek:function(){return this.string.charAt(this.pos)||void 0},next:function(){return this.pos<this.string.length?this.string.charAt(this.pos++):void 0},eat:function(a){var b=this.string.charAt(this.pos);if(\"string\"==typeof a)var c=b==a;else var c=b&&(a.test?a.test(b):a(b));return c?(++this.pos,b):void 0},eatWhile:function(a){for(var b=this.pos;this.eat(a););return this.pos>b},eatSpace:function(){for(var a=this.pos;/[\\s\\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>a},skipToEnd:function(){this.pos=this.string.length},skipTo:function(a){var b=this.string.indexOf(a,this.pos);return b>-1?(this.pos=b,!0):void 0},backUp:function(a){this.pos-=a},column:function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=kf(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?kf(this.string,this.lineStart,this.tabSize):0)},indentation:function(){return kf(this.string,null,this.tabSize)-(this.lineStart?kf(this.string,this.lineStart,this.tabSize):0)},match:function(a,b,c){if(\"string\"!=typeof a){var f=this.string.slice(this.pos).match(a);return f&&f.index>0?null:(f&&b!==!1&&(this.pos+=f[0].length),f)}var d=function(a){return c?a.toLowerCase():a},e=this.string.substr(this.pos,a.length);return d(e)==d(a)?(b!==!1&&(this.pos+=a.length),!0):void 0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(a,b){this.lineStart+=a;try{return b()}finally{this.lineStart-=a}}},z.StringStream=vd,z.TextMarker=wd,ff(wd),wd.prototype.clear=function(){if(!this.explicitlyCleared){var a=this.doc.cm,b=a&&!a.curOp;if(b&&Gb(a),ef(this,\"clear\")){var c=this.find();c&&bf(this,\"clear\",c.from,c.to)}for(var d=null,e=null,f=0;f<this.lines.length;++f){var g=this.lines[f],h=Bd(g.markedSpans,this);null!=h.to&&(e=Ce(g)),g.markedSpans=Cd(g.markedSpans,h),null!=h.from?d=Ce(g):this.collapsed&&!Sd(this.doc,g)&&a&&Be(g,Db(a.display))}if(a&&this.collapsed&&!a.options.lineWrapping)for(var f=0;f<this.lines.length;++f){var i=Rd(a.doc,this.lines[f]),j=K(a.doc,i);j>a.display.maxLineLength&&(a.display.maxLine=i,a.display.maxLineLength=j,a.display.maxLineChanged=!0)}null!=d&&a&&Lb(a,d,e+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,a&&Sc(a)),b&&Hb(a)}},wd.prototype.find=function(a){for(var b,c,d=0;d<this.lines.length;++d){var e=this.lines[d],f=Bd(e.markedSpans,this);if(null!=f.from||null!=f.to){var g=Ce(e);null!=f.from&&(b=Gc(g,f.from)),null!=f.to&&(c=Gc(g,f.to))}}return\"bookmark\"!=this.type||a?b&&{from:b,to:c}:b},wd.prototype.changed=function(){var a=this.find(),b=this.doc.cm;if(a&&b){\"bookmark\"!=this.type&&(a=a.from);var c=ye(this.doc,a.line);if(nb(b,c),a.line>=b.display.showingFrom&&a.line<b.display.showingTo){for(var d=b.display.lineDiv.firstChild;d;d=d.nextSibling)if(d.lineObj==c){d.offsetHeight!=c.height&&Be(c,d.offsetHeight);break}Kb(b,function(){b.curOp.selectionChanged=b.curOp.forceUpdate=b.curOp.updateMaxLine=!0})}}},wd.prototype.attachLine=function(a){if(!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;b.maybeHiddenMarkers&&-1!=pf(b.maybeHiddenMarkers,this)||(b.maybeUnhiddenMarkers||(b.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(a)},wd.prototype.detachLine=function(a){if(this.lines.splice(pf(this.lines,a),1),!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;(b.maybeHiddenMarkers||(b.maybeHiddenMarkers=[])).push(this)}};var xd=0;z.SharedTextMarker=zd,ff(zd),zd.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var a=0;a<this.markers.length;++a)this.markers[a].clear();bf(this,\"clear\")}},zd.prototype.find=function(){return this.primary.find()};var Wd=z.LineWidget=function(a,b,c){if(c)for(var d in c)c.hasOwnProperty(d)&&(this[d]=c[d]);this.cm=a,this.node=b};ff(Wd),Wd.prototype.clear=Xd(function(){var a=this.line.widgets,b=Ce(this.line);if(null!=b&&a){for(var c=0;c<a.length;++c)a[c]==this&&a.splice(c--,1);a.length||(this.line.widgets=null);var d=Ee(this.cm,this.line)<this.cm.doc.scrollTop;Be(this.line,Math.max(0,this.line.height-Yd(this))),d&&Zc(this.cm,0,-this.height),Lb(this.cm,b,b+1)}}),Wd.prototype.changed=Xd(function(){var a=this.height;this.height=null;var b=Yd(this)-a;if(b){Be(this.line,this.line.height+b);var c=Ce(this.line);Lb(this.cm,c,c+1)}});var $d=z.Line=function(a,b,c){this.text=a,Vd(this,b),this.height=c?c(this):1};ff($d),$d.prototype.lineNo=function(){return Ce(this)};var fe={},ge={};qe.prototype={chunkSize:function(){return this.lines.length},removeInner:function(a,b){for(var c=a,d=a+b;d>c;++c){var e=this.lines[c];this.height-=e.height,ae(e),bf(e,\"delete\")}this.lines.splice(a,b)},collapse:function(a){a.splice.apply(a,[a.length,0].concat(this.lines))},insertInner:function(a,b,c){this.height+=c,this.lines=this.lines.slice(0,a).concat(b).concat(this.lines.slice(a));for(var d=0,e=b.length;e>d;++d)b[d].parent=this},iterN:function(a,b,c){for(var d=a+b;d>a;++a)if(c(this.lines[a]))return!0}},re.prototype={chunkSize:function(){return this.size},removeInner:function(a,b){this.size-=b;for(var c=0;c<this.children.length;++c){var d=this.children[c],e=d.chunkSize();if(e>a){var f=Math.min(b,e-a),g=d.height;if(d.removeInner(a,f),this.height-=g-d.height,e==f&&(this.children.splice(c--,1),d.parent=null),0==(b-=f))break;a=0}else a-=e}if(this.size-b<25){var h=[];this.collapse(h),this.children=[new qe(h)],this.children[0].parent=this}},collapse:function(a){for(var b=0,c=this.children.length;c>b;++b)this.children[b].collapse(a)},insertInner:function(a,b,c){this.size+=b.length,this.height+=c;for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>=a){if(f.insertInner(a,b,c),f.lines&&f.lines.length>50){for(;f.lines.length>50;){var h=f.lines.splice(f.lines.length-25,25),i=new qe(h);f.height-=i.height,this.children.splice(d+1,0,i),i.parent=this}this.maybeSpill()}break}a-=g}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new re(b);if(a.parent){a.size-=c.size,a.height-=c.height;var e=pf(a.parent.children,a);a.parent.children.splice(e+1,0,c)}else{var d=new re(a.children);d.parent=a,a.children=[d,c],a=d}c.parent=a.parent}while(a.children.length>10);a.parent.maybeSpill()}},iterN:function(a,b,c){for(var d=0,e=this.children.length;e>d;++d){var f=this.children[d],g=f.chunkSize();if(g>a){var h=Math.min(b,g-a);if(f.iterN(a,h,c))return!0;if(0==(b-=h))break;a=0}else a-=g}}};var se=0,te=z.Doc=function(a,b,c){if(!(this instanceof te))return new te(a,b,c);null==c&&(c=0),re.call(this,[new qe([new $d(\"\",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.history=Ge(),this.cleanGeneration=1,this.frontier=c;var d=Gc(c,0);this.sel={from:d,to:d,head:d,anchor:d,shift:!1,extend:!1,goalColumn:null},this.id=++se,this.modeOption=b,\"string\"==typeof a&&(a=Kf(a)),pe(this,{from:d,to:d,text:a},null,{head:d,anchor:d})};te.prototype=qf(re.prototype,{constructor:te,iter:function(a,b,c){c?this.iterN(a-this.first,b-a,c):this.iterN(this.first,this.first+this.size,a)},insert:function(a,b){for(var c=0,d=0,e=b.length;e>d;++d)c+=b[d].height;this.insertInner(a-this.first,b,c)},remove:function(a,b){this.removeInner(a-this.first,b)},getValue:function(a){var b=Ae(this,this.first,this.first+this.size);return a===!1?b:b.join(a||\"\\n\")},setValue:function(a){var b=Gc(this.first,0),c=this.first+this.size-1;zc(this,{from:b,to:Gc(c,ye(this,c).text.length),text:Kf(a),origin:\"setValue\"},{head:b,anchor:b},!0)},replaceRange:function(a,b,c,d){b=Mc(this,b),c=c?Mc(this,c):b,Fc(this,a,b,c,d)},getRange:function(a,b,c){var d=ze(this,Mc(this,a),Mc(this,b));return c===!1?d:d.join(c||\"\\n\")},getLine:function(a){var b=this.getLineHandle(a);return b&&b.text},setLine:function(a,b){Oc(this,a)&&Fc(this,b,Gc(a,0),Mc(this,Gc(a)))},removeLine:function(a){a?Fc(this,\"\",Mc(this,Gc(a-1)),Mc(this,Gc(a))):Fc(this,\"\",Gc(0,0),Mc(this,Gc(1,0)))},getLineHandle:function(a){return Oc(this,a)?ye(this,a):void 0},getLineNumber:function(a){return Ce(a)},getLineHandleVisualStart:function(a){return\"number\"==typeof a&&(a=ye(this,a)),Rd(this,a)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(a){return Mc(this,a)},getCursor:function(a){var c,b=this.sel;return c=null==a||\"head\"==a?b.head:\"anchor\"==a?b.anchor:\"end\"==a||a===!1?b.to:b.from,Kc(c)},somethingSelected:function(){return!Hc(this.sel.head,this.sel.anchor)},setCursor:Jb(function(a,b,c){var d=Mc(this,\"number\"==typeof a?Gc(a,b||0):a);c?Pc(this,d):Rc(this,d,d)}),setSelection:Jb(function(a,b,c){Rc(this,Mc(this,a),Mc(this,b||a),c)}),extendSelection:Jb(function(a,b,c){Pc(this,Mc(this,a),b&&Mc(this,b),c)}),getSelection:function(a){return this.getRange(this.sel.from,this.sel.to,a)},replaceSelection:function(a,b,c){zc(this,{from:this.sel.from,to:this.sel.to,text:Kf(a),origin:c},b||\"around\")},undo:Jb(function(){Bc(this,\"undo\")}),redo:Jb(function(){Bc(this,\"redo\")}),setExtending:function(a){this.sel.extend=a},historySize:function(){var a=this.history;return{undo:a.done.length,redo:a.undone.length}},clearHistory:function(){this.history=Ge(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(a){return a&&(this.history.lastOp=this.history.lastOrigin=null),this.history.generation},isClean:function(a){return this.history.generation==(a||this.cleanGeneration)},getHistory:function(){return{done:Me(this.history.done),undone:Me(this.history.undone)}},setHistory:function(a){var b=this.history=Ge(this.history.maxGeneration);b.done=a.done.slice(0),b.undone=a.undone.slice(0)},markText:function(a,b,c){return yd(this,Mc(this,a),Mc(this,b),c,\"range\")},setBookmark:function(a,b){var c={replacedWith:b&&(null==b.nodeType?b.widget:b),insertLeft:b&&b.insertLeft,clearWhenEmpty:!1};return a=Mc(this,a),yd(this,a,a,c,\"bookmark\")},findMarksAt:function(a){a=Mc(this,a);var b=[],c=ye(this,a.line).markedSpans;if(c)for(var d=0;d<c.length;++d){var e=c[d];(null==e.from||e.from<=a.ch)&&(null==e.to||e.to>=a.ch)&&b.push(e.marker.parent||e.marker)}return b},findMarks:function(a,b){a=Mc(this,a),b=Mc(this,b);var c=[],d=a.line;return this.iter(a.line,b.line+1,function(e){var f=e.markedSpans;if(f)for(var g=0;g<f.length;g++){var h=f[g];d==a.line&&a.ch>h.to||null==h.from&&d!=a.line||d==b.line&&h.from>b.ch||c.push(h.marker.parent||h.marker)}++d}),c},getAllMarks:function(){var a=[];return this.iter(function(b){var c=b.markedSpans;if(c)for(var d=0;d<c.length;++d)null!=c[d].from&&a.push(c[d].marker)}),a},posFromIndex:function(a){var b,c=this.first;return this.iter(function(d){var e=d.text.length+1;return e>a?(b=a,!0):(a-=e,++c,void 0)}),Mc(this,Gc(c,b))},indexFromPos:function(a){a=Mc(this,a);var b=a.ch;return a.line<this.first||a.ch<0?0:(this.iter(this.first,a.line,function(a){b+=a.text.length+1}),b)},copy:function(a){var b=new te(Ae(this,this.first,this.first+this.size),this.modeOption,this.first);return b.scrollTop=this.scrollTop,b.scrollLeft=this.scrollLeft,b.sel={from:this.sel.from,to:this.sel.to,head:this.sel.head,anchor:this.sel.anchor,shift:this.sel.shift,extend:!1,goalColumn:this.sel.goalColumn},a&&(b.history.undoDepth=this.history.undoDepth,b.setHistory(this.getHistory())),b},linkedDoc:function(a){a||(a={});var b=this.first,c=this.first+this.size;null!=a.from&&a.from>b&&(b=a.from),null!=a.to&&a.to<c&&(c=a.to);var d=new te(Ae(this,b,c),a.mode||this.modeOption,b);return a.sharedHist&&(d.history=this.history),(this.linked||(this.linked=[])).push({doc:d,sharedHist:a.sharedHist}),d.linked=[{doc:this,isParent:!0,sharedHist:a.sharedHist}],d},unlinkDoc:function(a){if(a instanceof z&&(a=a.doc),this.linked)for(var b=0;b<this.linked.length;++b){var c=this.linked[b];if(c.doc==a){this.linked.splice(b,1),a.unlinkDoc(this);break}}if(a.history==this.history){var d=[a.id];we(a,function(a){d.push(a.id)},!0),a.history=Ge(),a.history.done=Me(this.history.done,d),a.history.undone=Me(this.history.undone,d)}},iterLinkedDocs:function(a){we(this,a)},getMode:function(){return this.mode},getEditor:function(){return this.cm}}),te.prototype.eachLine=te.prototype.iter;var ue=\"iter insert remove copy getEditor\".split(\" \");for(var ve in te.prototype)te.prototype.hasOwnProperty(ve)&&pf(ue,ve)<0&&(z.prototype[ve]=function(a){return function(){return a.apply(this.doc,arguments)}}(te.prototype[ve]));ff(te),z.e_stop=Ve,z.e_preventDefault=Se,z.e_stopPropagation=Te;var _e,af=0;z.on=Ye,z.off=Ze,z.signal=$e;var gf=30,hf=z.Pass={toString:function(){return\"CodeMirror.Pass\"}};jf.prototype={set:function(a,b){clearTimeout(this.id),this.id=setTimeout(b,a)}},z.countColumn=kf;var lf=[\"\"],uf=/[\\u00df\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/,xf=/[\\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]/;z.replaceGetRect=function(a){Df=a};var Ef=function(){if(d)return!1;var a=zf(\"div\");return\"draggable\"in a||\"dragDrop\"in a}();a?Ff=function(a,b){return 36==a.charCodeAt(b-1)&&39==a.charCodeAt(b)}:l&&!/Version\\/([6-9]|\\d\\d)\\b/.test(navigator.userAgent)?Ff=function(a,b){return/\\-[^ \\-?]|\\?[^ !\\'\\\"\\),.\\-\\/:;\\?\\]\\}]/.test(a.slice(b-1,b+1))}:h&&/Chrome\\/(?:29|[3-9]\\d|\\d\\d\\d)\\./.test(navigator.userAgent)?Ff=function(a,b){var c=a.charCodeAt(b-1);return c>=8208&&8212>=c}:h&&(Ff=function(a,b){if(b>1&&45==a.charCodeAt(b-1)){if(/\\w/.test(a.charAt(b-2))&&/[^\\-?\\.]/.test(a.charAt(b)))return!0;if(b>2&&/[\\d\\.,]/.test(a.charAt(b-2))&&/[\\d\\.,]/.test(a.charAt(b)))return!1}return/[~!#%&*)=+}\\]\\\\|\\\"\\.>,:;][({[<]|-[^\\-?\\.\\u2010-\\u201f\\u2026]|\\?[\\w~`@#$%\\^&*(_=+{[|><]|\\u2026[\\w~`@#$%\\^&*(_=+{[><]/.test(a.slice(b-1,b+1))});var Gf,If,Kf=3!=\"\\n\\nb\".split(/\\n/).length?function(a){for(var b=0,c=[],d=a.length;d>=b;){var e=a.indexOf(\"\\n\",b);-1==e&&(e=a.length);var f=a.slice(b,\"\\r\"==a.charAt(e-1)?e-1:e),g=f.indexOf(\"\\r\");-1!=g?(c.push(f.slice(0,g)),b+=g+1):(c.push(f),b=e+1)}return c}:function(a){return a.split(/\\r\\n?|\\n/)};z.splitLines=Kf;var Lf=window.getSelection?function(a){try{return a.selectionStart!=a.selectionEnd}catch(b){return!1}}:function(a){try{var b=a.ownerDocument.selection.createRange()}catch(c){}return b&&b.parentElement()==a?0!=b.compareEndPoints(\"StartToEnd\",b):!1},Mf=function(){var a=zf(\"div\");return\"oncopy\"in a?!0:(a.setAttribute(\"oncopy\",\"return;\"),\"function\"==typeof a.oncopy)}(),Nf={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\",107:\"=\",109:\"-\",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\"};z.keyNames=Nf,function(){for(var a=0;10>a;a++)Nf[a+48]=Nf[a+96]=String(a);for(var a=65;90>=a;a++)Nf[a]=String.fromCharCode(a);for(var a=1;12>=a;a++)Nf[a+111]=Nf[a+63235]=\"F\"+a}();var Wf,_f=function(){function c(c){return 255>=c?a.charAt(c):c>=1424&&1524>=c?\"R\":c>=1536&&1791>=c?b.charAt(c-1536):c>=1792&&2220>=c?\"r\":\"L\"}var a=\"bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL\",b=\"rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr\",d=/[\\u0590-\\u05f4\\u0600-\\u06ff\\u0700-\\u08ac]/,e=/[stwN]/,f=/[LRr]/,g=/[Lb1n]/,h=/[1n]/,i=\"L\";return function(a){if(!d.test(a))return!1;for(var l,b=a.length,j=[],k=0;b>k;++k)j.push(l=c(a.charCodeAt(k)));for(var k=0,m=i;b>k;++k){var l=j[k];\"m\"==l?j[k]=m:m=l}for(var k=0,n=i;b>k;++k){var l=j[k];\"1\"==l&&\"r\"==n?j[k]=\"n\":f.test(l)&&(n=l,\"r\"==l&&(j[k]=\"R\"))}for(var k=1,m=j[0];b-1>k;++k){var l=j[k];\"+\"==l&&\"1\"==m&&\"1\"==j[k+1]?j[k]=\"1\":\",\"!=l||m!=j[k+1]||\"1\"!=m&&\"n\"!=m||(j[k]=m),m=l}for(var k=0;b>k;++k){var l=j[k];if(\",\"==l)j[k]=\"N\";else if(\"%\"==l){for(var o=k+1;b>o&&\"%\"==j[o];++o);for(var p=k&&\"!\"==j[k-1]||b>o&&\"1\"==j[o]?\"1\":\"N\",q=k;o>q;++q)j[q]=p;k=o-1}}for(var k=0,n=i;b>k;++k){var l=j[k];\"L\"==n&&\"1\"==l?j[k]=\"L\":f.test(l)&&(n=l)}for(var k=0;b>k;++k)if(e.test(j[k])){for(var o=k+1;b>o&&e.test(j[o]);++o);for(var r=\"L\"==(k?j[k-1]:i),s=\"L\"==(b>o?j[o]:i),p=r||s?\"L\":\"R\",q=k;o>q;++q)j[q]=p;k=o-1}for(var u,t=[],k=0;b>k;)if(g.test(j[k])){var v=k;for(++k;b>k&&g.test(j[k]);++k);t.push({from:v,to:k,level:0})}else{var w=k,x=t.length;for(++k;b>k&&\"L\"!=j[k];++k);for(var q=w;k>q;)if(h.test(j[q])){q>w&&t.splice(x,0,{from:w,to:q,level:1});var y=q;for(++q;k>q&&h.test(j[q]);++q);t.splice(x,0,{from:y,to:q,level:2}),w=q}else++q;k>w&&t.splice(x,0,{from:w,to:k,level:1})}return 1==t[0].level&&(u=a.match(/^\\s+/))&&(t[0].from=u[0].length,t.unshift({from:0,to:u[0].length,level:0})),1==nf(t).level&&(u=a.match(/\\s+$/))&&(nf(t).to-=u[0].length,t.push({from:b-u[0].length,to:b,level:0})),t[0].level!=nf(t).level&&t.push({from:b,to:b,level:t[0].level}),t}}();return z.version=\"3.22.0\",z}(),CodeMirror.defineMode(\"javascript\",function(a,b){function k(a){for(var c,b=!1,d=!1;null!=(c=a.next());){if(!b){if(\"/\"==c&&!d)return;\"[\"==c?d=!0:d&&\"]\"==c&&(d=!1)}b=!b&&\"\\\\\"==c}}function n(a,b,c){return l=a,m=c,b}function o(a,b){var c=a.next();if('\"'==c||\"'\"==c)return b.tokenize=p(c),b.tokenize(a,b);if(\".\"==c&&a.match(/^\\d+(?:[eE][+\\-]?\\d+)?/))return n(\"number\",\"number\");if(\".\"==c&&a.match(\"..\"))return n(\"spread\",\"meta\");if(/[\\[\\]{}\\(\\),;\\:\\.]/.test(c))return n(c);if(\"=\"==c&&a.eat(\">\"))return n(\"=>\",\"operator\");if(\"0\"==c&&a.eat(/x/i))return a.eatWhile(/[\\da-f]/i),n(\"number\",\"number\");if(/\\d/.test(c))return a.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/),n(\"number\",\"number\");if(\"/\"==c)return a.eat(\"*\")?(b.tokenize=q,q(a,b)):a.eat(\"/\")?(a.skipToEnd(),n(\"comment\",\"comment\")):\"operator\"==b.lastType||\"keyword c\"==b.lastType||\"sof\"==b.lastType||/^[\\[{}\\(,;:]$/.test(b.lastType)?(k(a),a.eatWhile(/[gimy]/),n(\"regexp\",\"string-2\")):(a.eatWhile(i),n(\"operator\",\"operator\",a.current()));if(\"`\"==c)return b.tokenize=r,r(a,b);if(\"#\"==c)return a.skipToEnd(),n(\"error\",\"error\");if(i.test(c))return a.eatWhile(i),n(\"operator\",\"operator\",a.current());a.eatWhile(/[\\w\\$_]/);var d=a.current(),e=h.propertyIsEnumerable(d)&&h[d];return e&&\".\"!=b.lastType?n(e.type,e.style,d):n(\"variable\",\"variable\",d)}function p(a){return function(b,c){var f,d=!1;if(e&&\"@\"==b.peek()&&b.match(j))return c.tokenize=o,n(\"jsonld-keyword\",\"meta\");for(;null!=(f=b.next())&&(f!=a||d);)d=!d&&\"\\\\\"==f;return d||(c.tokenize=o),n(\"string\",\"string\")}}function q(a,b){for(var d,c=!1;d=a.next();){if(\"/\"==d&&c){b.tokenize=o;break}c=\"*\"==d}return n(\"comment\",\"comment\")}function r(a,b){for(var d,c=!1;null!=(d=a.next());){if(!c&&(\"`\"==d||\"$\"==d&&a.eat(\"{\"))){b.tokenize=o;break}c=!c&&\"\\\\\"==d}return n(\"quasi\",\"string-2\",a.current())}function t(a,b){b.fatArrowAt&&(b.fatArrowAt=null);var c=a.string.indexOf(\"=>\",a.start);if(!(0>c)){for(var d=0,e=!1,f=c-1;f>=0;--f){var g=a.string.charAt(f),h=s.indexOf(g);if(h>=0&&3>h){if(!d){++f;break}if(0==--d)break}else if(h>=3&&6>h)++d;else if(/[$\\w]/.test(g))e=!0;else if(e&&!d){++f;break}}e&&!d&&(b.fatArrowAt=f)}}function v(a,b,c,d,e,f){this.indented=a,this.column=b,this.type=c,this.prev=e,this.info=f,null!=d&&(this.align=d)}function w(a,b){for(var c=a.localVars;c;c=c.next)if(c.name==b)return!0;for(var d=a.context;d;d=d.prev)for(var c=d.vars;c;c=c.next)if(c.name==b)return!0}function x(a,b,c,d,e){var g=a.cc;for(y.state=a,y.stream=e,y.marked=null,y.cc=g,a.lexical.hasOwnProperty(\"align\")||(a.lexical.align=!0);;){var h=g.length?g.pop():f?J:I;if(h(c,d)){for(;g.length&&g[g.length-1].lex;)g.pop()();return y.marked?y.marked:\"variable\"==c&&w(a,d)?\"variable-2\":b}}}function z(){for(var a=arguments.length-1;a>=0;a--)y.cc.push(arguments[a])}function A(){return z.apply(null,arguments),!0}function B(a){function c(b){for(var c=b;c;c=c.next)if(c.name==a)return!0;return!1}var d=y.state;if(d.context){if(y.marked=\"def\",c(d.localVars))return;d.localVars={name:a,next:d.localVars}}else{if(c(d.globalVars))return;b.globalVars&&(d.globalVars={name:a,next:d.globalVars})}}function D(){y.state.context={prev:y.state.context,vars:y.state.localVars},y.state.localVars=C}function E(){y.state.localVars=y.state.context.vars,y.state.context=y.state.context.prev}function F(a,b){var c=function(){var c=y.state,d=c.indented;\"stat\"==c.lexical.type&&(d=c.lexical.indented),c.lexical=new v(d,y.stream.column(),a,null,c.lexical,b)};return c.lex=!0,c}function G(){var a=y.state;a.lexical.prev&&(\")\"==a.lexical.type&&(a.indented=a.lexical.indented),a.lexical=a.lexical.prev)}function H(a){return function(b){return b==a?A():\";\"==a?z():A(arguments.callee)}}function I(a,b){return\"var\"==a?A(F(\"vardef\",b.length),cb,H(\";\"),G):\"keyword a\"==a?A(F(\"form\"),J,I,G):\"keyword b\"==a?A(F(\"form\"),I,G):\"{\"==a?A(F(\"}\"),_,G):\";\"==a?A():\"if\"==a?A(F(\"form\"),J,I,G,hb):\"function\"==a?A(nb):\"for\"==a?A(F(\"form\"),ib,I,G):\"variable\"==a?A(F(\"stat\"),U):\"switch\"==a?A(F(\"form\"),J,F(\"}\",\"switch\"),H(\"{\"),_,G,G):\"case\"==a?A(J,H(\":\")):\"default\"==a?A(H(\":\")):\"catch\"==a?A(F(\"form\"),D,H(\"(\"),ob,H(\")\"),I,G,E):\"module\"==a?A(F(\"form\"),D,sb,E,G):\"class\"==a?A(F(\"form\"),pb,rb,G):\"export\"==a?A(F(\"form\"),tb,G):\"import\"==a?A(F(\"form\"),ub,G):z(F(\"stat\"),J,H(\";\"),G)}function J(a){return L(a,!1)}function K(a){return L(a,!0)}function L(a,b){if(y.state.fatArrowAt==y.stream.start){var c=b?T:S;if(\"(\"==a)return A(D,F(\")\"),Z(db,\")\"),G,H(\"=>\"),c,E);if(\"variable\"==a)return z(D,db,H(\"=>\"),c,E)}var d=b?P:O;return u.hasOwnProperty(a)?A(d):\"function\"==a?A(nb):\"keyword c\"==a?A(b?N:M):\"(\"==a?A(F(\")\"),M,zb,H(\")\"),G,d):\"operator\"==a||\"spread\"==a?A(b?K:J):\"[\"==a?A(F(\"]\"),xb,G,d):\"{\"==a?$(W,\"}\",null,d):A()}function M(a){return a.match(/[;\\}\\)\\],]/)?z():z(J)}function N(a){return a.match(/[;\\}\\)\\],]/)?z():z(K)}function O(a,b){return\",\"==a?A(J):P(a,b,!1)}function P(a,b,c){var d=0==c?O:P,e=0==c?J:K;return\"=>\"==b?A(D,c?T:S,E):\"operator\"==a?/\\+\\+|--/.test(b)?A(d):\"?\"==b?A(J,H(\":\"),e):A(e):\"quasi\"==a?(y.cc.push(d),Q(b)):\";\"!=a?\"(\"==a?$(K,\")\",\"call\",d):\".\"==a?A(V,d):\"[\"==a?A(F(\"]\"),M,H(\"]\"),G,d):void 0:void 0}function Q(a){return\"${\"!=a.slice(a.length-2)?A():A(J,R)}function R(a){return\"}\"==a?(y.marked=\"string-2\",y.state.tokenize=r,A()):void 0}function S(a){return t(y.stream,y.state),\"{\"==a?z(I):z(J)}function T(a){return t(y.stream,y.state),\"{\"==a?z(I):z(K)}function U(a){return\":\"==a?A(G,I):z(O,H(\";\"),G)}function V(a){return\"variable\"==a?(y.marked=\"property\",A()):void 0}function W(a,b){if(\"variable\"==a){if(y.marked=\"property\",\"get\"==b||\"set\"==b)return A(X)}else if(\"number\"==a||\"string\"==a)y.marked=e?\"property\":a+\" property\";else if(\"[\"==a)return A(J,H(\"]\"),Y);return u.hasOwnProperty(a)?A(Y):void 0}function X(a){return\"variable\"!=a?z(Y):(y.marked=\"property\",A(nb))}function Y(a){return\":\"==a?A(K):\"(\"==a?z(nb):void 0}function Z(a,b){function c(d){if(\",\"==d){var e=y.state.lexical;return\"call\"==e.info&&(e.pos=(e.pos||0)+1),A(a,c)}return d==b?A():A(H(b))}return function(d){return d==b?A():z(a,c)}}function $(a,b,c){for(var d=3;d<arguments.length;d++)y.cc.push(arguments[d]);return A(F(b,c),Z(a,b),G)}function _(a){return\"}\"==a?A():z(I,_)}function ab(a){return g&&\":\"==a?A(bb):void 0}function bb(a){return\"variable\"==a?(y.marked=\"variable-3\",A()):void 0}function cb(){return z(db,ab,fb,gb)}function db(a,b){return\"variable\"==a?(B(b),A()):\"[\"==a?$(db,\"]\"):\"{\"==a?$(eb,\"}\"):void 0}function eb(a,b){return\"variable\"!=a||y.stream.match(/^\\s*:/,!1)?(\"variable\"==a&&(y.marked=\"property\"),A(H(\":\"),db,fb)):(B(b),A(fb))}function fb(a,b){return\"=\"==b?A(K):void 0}function gb(a){return\",\"==a?A(cb):void 0}function hb(a,b){return\"keyword b\"==a&&\"else\"==b?A(F(\"form\"),I,G):void 0}function ib(a){return\"(\"==a?A(F(\")\"),jb,H(\")\"),G):void 0}function jb(a){return\"var\"==a?A(cb,H(\";\"),lb):\";\"==a?A(lb):\"variable\"==a?A(kb):z(J,H(\";\"),lb)}function kb(a,b){return\"in\"==b||\"of\"==b?(y.marked=\"keyword\",A(J)):A(O,lb)}function lb(a,b){return\";\"==a?A(mb):\"in\"==b||\"of\"==b?(y.marked=\"keyword\",A(J)):z(J,H(\";\"),mb)}function mb(a){\")\"!=a&&A(J)}function nb(a,b){return\"*\"==b?(y.marked=\"keyword\",A(nb)):\"variable\"==a?(B(b),A(nb)):\"(\"==a?A(D,F(\")\"),Z(ob,\")\"),G,I,E):void 0}function ob(a){return\"spread\"==a?A(ob):z(db,ab)}function pb(a,b){return\"variable\"==a?(B(b),A(qb)):void 0}function qb(a,b){return\"extends\"==b?A(J):void 0}function rb(a){return\"{\"==a?$(W,\"}\"):void 0}function sb(a,b){return\"string\"==a?A(I):\"variable\"==a?(B(b),A(wb)):void 0}function tb(a,b){return\"*\"==b?(y.marked=\"keyword\",A(wb,H(\";\"))):\"default\"==b?(y.marked=\"keyword\",A(J,H(\";\"))):z(I)}function ub(a){return\"string\"==a?A():z(vb,wb)}function vb(a,b){return\"{\"==a?$(vb,\"}\"):(\"variable\"==a&&B(b),A())}function wb(a,b){return\"from\"==b?(y.marked=\"keyword\",A(J)):void 0}function xb(a){return\"]\"==a?A():z(K,yb)}function yb(a){return\"for\"==a?z(zb,H(\"]\")):\",\"==a?A(Z(K,\"]\")):z(Z(K,\"]\"))}function zb(a){return\"for\"==a?A(ib,zb):\"if\"==a?A(J,zb):void 0}var l,m,c=a.indentUnit,d=b.statementIndent,e=b.jsonld,f=b.json||e,g=b.typescript,h=function(){function a(a){return{type:a,style:\"keyword\"}}var b=a(\"keyword a\"),c=a(\"keyword b\"),d=a(\"keyword c\"),e=a(\"operator\"),f={type:\"atom\",style:\"atom\"},h={\"if\":a(\"if\"),\"while\":b,\"with\":b,\"else\":c,\"do\":c,\"try\":c,\"finally\":c,\"return\":d,\"break\":d,\"continue\":d,\"new\":d,\"delete\":d,\"throw\":d,\"debugger\":d,\"var\":a(\"var\"),\"const\":a(\"var\"),let:a(\"var\"),\"function\":a(\"function\"),\"catch\":a(\"catch\"),\"for\":a(\"for\"),\"switch\":a(\"switch\"),\"case\":a(\"case\"),\"default\":a(\"default\"),\"in\":e,\"typeof\":e,\"instanceof\":e,\"true\":f,\"false\":f,\"null\":f,undefined:f,NaN:f,Infinity:f,\"this\":a(\"this\"),module:a(\"module\"),\"class\":a(\"class\"),\"super\":a(\"atom\"),yield:d,\"export\":a(\"export\"),\"import\":a(\"import\"),\"extends\":d};if(g){var i={type:\"variable\",style:\"variable-3\"},j={\"interface\":a(\"interface\"),\"extends\":a(\"extends\"),constructor:a(\"constructor\"),\"public\":a(\"public\"),\"private\":a(\"private\"),\"protected\":a(\"protected\"),\"static\":a(\"static\"),string:i,number:i,bool:i,any:i};for(var k in j)h[k]=j[k]}return h}(),i=/[+\\-*&%=<>!?|~^]/,j=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)\"/,s=\"([{}])\",u={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,\"this\":!0,\"jsonld-keyword\":!0},y={state:null,column:null,marked:null,cc:null},C={name:\"this\",next:{name:\"arguments\"}};return G.lex=!0,{startState:function(a){var d={tokenize:o,lastType:\"sof\",cc:[],lexical:new v((a||0)-c,0,\"block\",!1),localVars:b.localVars,context:b.localVars&&{vars:b.localVars},indented:0};return b.globalVars&&(d.globalVars=b.globalVars),d},token:function(a,b){if(a.sol()&&(b.lexical.hasOwnProperty(\"align\")||(b.lexical.align=!1),b.indented=a.indentation(),t(a,b)),b.tokenize!=q&&a.eatSpace())return null;var c=b.tokenize(a,b);return\"comment\"==l?c:(b.lastType=\"operator\"!=l||\"++\"!=m&&\"--\"!=m?l:\"incdec\",x(b,c,l,m,a))},indent:function(a,e){if(a.tokenize==q)return CodeMirror.Pass;if(a.tokenize!=o)return 0;for(var f=e&&e.charAt(0),g=a.lexical,h=a.cc.length-1;h>=0;--h){var i=a.cc[h];if(i==G)g=g.prev;else if(i!=hb)break}\"stat\"==g.type&&\"}\"==f&&(g=g.prev),d&&\")\"==g.type&&\"stat\"==g.prev.type&&(g=g.prev);var j=g.type,k=f==j;return\"vardef\"==j?g.indented+(\"operator\"==a.lastType||\",\"==a.lastType?g.info+1:0):\"form\"==j&&\"{\"==f?g.indented:\"form\"==j?g.indented+c:\"stat\"==j?g.indented+(\"operator\"==a.lastType||\",\"==a.lastType?d||c:0):\"switch\"!=g.info||k||0==b.doubleIndentSwitch?g.align?g.column+(k?0:1):g.indented+(k?0:c):g.indented+(/^(?:case|default)\\b/.test(e)?c:2*c)},electricChars:\":{}\",blockCommentStart:f?null:\"/*\",blockCommentEnd:f?null:\"*/\",lineComment:f?null:\"//\",fold:\"brace\",helperType:f?\"json\":\"javascript\",jsonldMode:e,jsonMode:f}}),CodeMirror.defineMIME(\"text/javascript\",\"javascript\"),CodeMirror.defineMIME(\"text/ecmascript\",\"javascript\"),CodeMirror.defineMIME(\"application/javascript\",\"javascript\"),CodeMirror.defineMIME(\"application/ecmascript\",\"javascript\"),CodeMirror.defineMIME(\"application/json\",{name:\"javascript\",json:!0}),CodeMirror.defineMIME(\"application/x-json\",{name:\"javascript\",json:!0}),CodeMirror.defineMIME(\"application/ld+json\",{name:\"javascript\",jsonld:!0}),CodeMirror.defineMIME(\"text/typescript\",{name:\"javascript\",typescript:!0}),CodeMirror.defineMIME(\"application/typescript\",{name:\"javascript\",typescript:!0}),function(){\"use strict\";function c(c){\"activeLine\"in c.state&&(c.removeLineClass(c.state.activeLine,\"wrap\",a),c.removeLineClass(c.state.activeLine,\"background\",b))}function d(d,e){var f=d.getLineHandleVisualStart(e);d.state.activeLine!=f&&d.operation(function(){c(d),d.addLineClass(f,\"wrap\",a),d.addLineClass(f,\"background\",b),d.state.activeLine=f})}function e(a,b){d(a,b.head.line)}var a=\"CodeMirror-activeline\",b=\"CodeMirror-activeline-background\";CodeMirror.defineOption(\"styleActiveLine\",!1,function(a,b,f){var g=f&&f!=CodeMirror.Init;b&&!g?(d(a,a.getCursor().line),a.on(\"beforeSelectionChange\",e)):!b&&g&&(a.off(\"beforeSelectionChange\",e),c(a),delete a.state.activeLine)})}();"
  },
  {
    "path": "client/js/lib/codemirror.js",
    "content": "// CodeMirror version 3.22\n//\n// CodeMirror is the only global var we claim\nwindow.CodeMirror = (function() {\n  \"use strict\";\n\n  // BROWSER SNIFFING\n\n  // Crude, but necessary to handle a number of hard-to-feature-detect\n  // bugs and behavior differences.\n  var gecko = /gecko\\/\\d/i.test(navigator.userAgent);\n  // IE11 currently doesn't count as 'ie', since it has almost none of\n  // the same bugs as earlier versions. Use ie_gt10 to handle\n  // incompatibilities in that version.\n  var old_ie = /MSIE \\d/.test(navigator.userAgent);\n  var ie_lt8 = old_ie && (document.documentMode == null || document.documentMode < 8);\n  var ie_lt9 = old_ie && (document.documentMode == null || document.documentMode < 9);\n  var ie_lt10 = old_ie && (document.documentMode == null || document.documentMode < 10);\n  var ie_gt10 = /Trident\\/([7-9]|\\d{2,})\\./.test(navigator.userAgent);\n  var ie = old_ie || ie_gt10;\n  var webkit = /WebKit\\//.test(navigator.userAgent);\n  var qtwebkit = webkit && /Qt\\/\\d+\\.\\d+/.test(navigator.userAgent);\n  var chrome = /Chrome\\//.test(navigator.userAgent);\n  var opera = /Opera\\//.test(navigator.userAgent);\n  var safari = /Apple Computer/.test(navigator.vendor);\n  var khtml = /KHTML\\//.test(navigator.userAgent);\n  var mac_geLion = /Mac OS X 1\\d\\D([7-9]|\\d\\d)\\D/.test(navigator.userAgent);\n  var mac_geMountainLion = /Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(navigator.userAgent);\n  var phantom = /PhantomJS/.test(navigator.userAgent);\n\n  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\\/\\w+/.test(navigator.userAgent);\n  // This is woefully incomplete. Suggestions for alternative methods welcome.\n  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);\n  var mac = ios || /Mac/.test(navigator.platform);\n  var windows = /win/i.test(navigator.platform);\n\n  var opera_version = opera && navigator.userAgent.match(/Version\\/(\\d*\\.\\d*)/);\n  if (opera_version) opera_version = Number(opera_version[1]);\n  if (opera_version && opera_version >= 15) { opera = false; webkit = true; }\n  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X\n  var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));\n  var captureMiddleClick = gecko || (ie && !ie_lt9);\n\n  // Optimize some code when these features are not used\n  var sawReadOnlySpans = false, sawCollapsedSpans = false;\n\n  // CONSTRUCTOR\n\n  function CodeMirror(place, options) {\n    if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);\n\n    this.options = options = options || {};\n    // Determine effective options based on given values and defaults.\n    for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))\n      options[opt] = defaults[opt];\n    setGuttersForLineNumbers(options);\n\n    var docStart = typeof options.value == \"string\" ? 0 : options.value.first;\n    var display = this.display = makeDisplay(place, docStart);\n    display.wrapper.CodeMirror = this;\n    updateGutters(this);\n    if (options.autofocus && !mobile) focusInput(this);\n\n    this.state = {keyMaps: [],\n                  overlays: [],\n                  modeGen: 0,\n                  overwrite: false, focused: false,\n                  suppressEdits: false,\n                  pasteIncoming: false, cutIncoming: false,\n                  draggingText: false,\n                  highlight: new Delayed()};\n\n    themeChanged(this);\n    if (options.lineWrapping)\n      this.display.wrapper.className += \" CodeMirror-wrap\";\n\n    var doc = options.value;\n    if (typeof doc == \"string\") doc = new Doc(options.value, options.mode);\n    operation(this, attachDoc)(this, doc);\n\n    // Override magic textarea content restore that IE sometimes does\n    // on our hidden textarea on reload\n    if (old_ie) setTimeout(bind(resetInput, this, true), 20);\n\n    registerEventHandlers(this);\n    // IE throws unspecified error in certain cases, when\n    // trying to access activeElement before onload\n    var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }\n    if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);\n    else onBlur(this);\n\n    operation(this, function() {\n      for (var opt in optionHandlers)\n        if (optionHandlers.propertyIsEnumerable(opt))\n          optionHandlers[opt](this, options[opt], Init);\n      for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);\n    })();\n  }\n\n  // DISPLAY CONSTRUCTOR\n\n  function makeDisplay(place, docStart) {\n    var d = {};\n\n    var input = d.input = elt(\"textarea\", null, null, \"position: absolute; padding: 0; width: 1px; height: 1em; outline: none\");\n    if (webkit) input.style.width = \"1000px\";\n    else input.setAttribute(\"wrap\", \"off\");\n    // if border: 0; -- iOS fails to open keyboard (issue #1287)\n    if (ios) input.style.border = \"1px solid black\";\n    input.setAttribute(\"autocorrect\", \"off\"); input.setAttribute(\"autocapitalize\", \"off\"); input.setAttribute(\"spellcheck\", \"false\");\n\n    // Wraps and hides input textarea\n    d.inputDiv = elt(\"div\", [input], null, \"overflow: hidden; position: relative; width: 3px; height: 0px;\");\n    // The actual fake scrollbars.\n    d.scrollbarH = elt(\"div\", [elt(\"div\", null, null, \"height: 1px\")], \"CodeMirror-hscrollbar\");\n    d.scrollbarV = elt(\"div\", [elt(\"div\", null, null, \"width: 1px\")], \"CodeMirror-vscrollbar\");\n    d.scrollbarFiller = elt(\"div\", null, \"CodeMirror-scrollbar-filler\");\n    d.gutterFiller = elt(\"div\", null, \"CodeMirror-gutter-filler\");\n    // DIVs containing the selection and the actual code\n    d.lineDiv = elt(\"div\", null, \"CodeMirror-code\");\n    d.selectionDiv = elt(\"div\", null, null, \"position: relative; z-index: 1\");\n    // Blinky cursor, and element used to ensure cursor fits at the end of a line\n    d.cursor = elt(\"div\", \"\\u00a0\", \"CodeMirror-cursor\");\n    // Secondary cursor, shown when on a 'jump' in bi-directional text\n    d.otherCursor = elt(\"div\", \"\\u00a0\", \"CodeMirror-cursor CodeMirror-secondarycursor\");\n    // Used to measure text size\n    d.measure = elt(\"div\", null, \"CodeMirror-measure\");\n    // Wraps everything that needs to exist inside the vertically-padded coordinate system\n    d.lineSpace = elt(\"div\", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],\n                         null, \"position: relative; outline: none\");\n    // Moved around its parent to cover visible view\n    d.mover = elt(\"div\", [elt(\"div\", [d.lineSpace], \"CodeMirror-lines\")], null, \"position: relative\");\n    // Set to the height of the text, causes scrolling\n    d.sizer = elt(\"div\", [d.mover], \"CodeMirror-sizer\");\n    // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers\n    d.heightForcer = elt(\"div\", null, null, \"position: absolute; height: \" + scrollerCutOff + \"px; width: 1px;\");\n    // Will contain the gutters, if any\n    d.gutters = elt(\"div\", null, \"CodeMirror-gutters\");\n    d.lineGutter = null;\n    // Provides scrolling\n    d.scroller = elt(\"div\", [d.sizer, d.heightForcer, d.gutters], \"CodeMirror-scroll\");\n    d.scroller.setAttribute(\"tabIndex\", \"-1\");\n    // The element in which the editor lives.\n    d.wrapper = elt(\"div\", [d.inputDiv, d.scrollbarH, d.scrollbarV,\n                            d.scrollbarFiller, d.gutterFiller, d.scroller], \"CodeMirror\");\n    // Work around IE7 z-index bug\n    if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }\n    if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);\n\n    // Needed to hide big blue blinking cursor on Mobile Safari\n    if (ios) input.style.width = \"0px\";\n    if (!webkit) d.scroller.draggable = true;\n    // Needed to handle Tab key in KHTML\n    if (khtml) { d.inputDiv.style.height = \"1px\"; d.inputDiv.style.position = \"absolute\"; }\n    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).\n    else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = \"18px\";\n\n    // Current visible range (may be bigger than the view window).\n    d.viewOffset = d.lastSizeC = 0;\n    d.showingFrom = d.showingTo = docStart;\n\n    // Used to only resize the line number gutter when necessary (when\n    // the amount of lines crosses a boundary that makes its width change)\n    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;\n    // See readInput and resetInput\n    d.prevInput = \"\";\n    // Set to true when a non-horizontal-scrolling widget is added. As\n    // an optimization, widget aligning is skipped when d is false.\n    d.alignWidgets = false;\n    // Flag that indicates whether we currently expect input to appear\n    // (after some event like 'keypress' or 'input') and are polling\n    // intensively.\n    d.pollingFast = false;\n    // Self-resetting timeout for the poller\n    d.poll = new Delayed();\n\n    d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\n    d.measureLineCache = [];\n    d.measureLineCachePos = 0;\n\n    // Tracks when resetInput has punted to just putting a short\n    // string instead of the (large) selection.\n    d.inaccurateSelection = false;\n\n    // Tracks the maximum line length so that the horizontal scrollbar\n    // can be kept static when scrolling.\n    d.maxLine = null;\n    d.maxLineLength = 0;\n    d.maxLineChanged = false;\n\n    // Used for measuring wheel scrolling granularity\n    d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;\n\n    return d;\n  }\n\n  // STATE UPDATES\n\n  // Used to get the editor into a consistent state again when options change.\n\n  function loadMode(cm) {\n    cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);\n    resetModeState(cm);\n  }\n\n  function resetModeState(cm) {\n    cm.doc.iter(function(line) {\n      if (line.stateAfter) line.stateAfter = null;\n      if (line.styles) line.styles = null;\n    });\n    cm.doc.frontier = cm.doc.first;\n    startWorker(cm, 100);\n    cm.state.modeGen++;\n    if (cm.curOp) regChange(cm);\n  }\n\n  function wrappingChanged(cm) {\n    if (cm.options.lineWrapping) {\n      cm.display.wrapper.className += \" CodeMirror-wrap\";\n      cm.display.sizer.style.minWidth = \"\";\n    } else {\n      cm.display.wrapper.className = cm.display.wrapper.className.replace(\" CodeMirror-wrap\", \"\");\n      computeMaxLength(cm);\n    }\n    estimateLineHeights(cm);\n    regChange(cm);\n    clearCaches(cm);\n    setTimeout(function(){updateScrollbars(cm);}, 100);\n  }\n\n  function estimateHeight(cm) {\n    var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;\n    var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);\n    return function(line) {\n      if (lineIsHidden(cm.doc, line))\n        return 0;\n      else if (wrapping)\n        return (Math.ceil(line.text.length / perLine) || 1) * th;\n      else\n        return th;\n    };\n  }\n\n  function estimateLineHeights(cm) {\n    var doc = cm.doc, est = estimateHeight(cm);\n    doc.iter(function(line) {\n      var estHeight = est(line);\n      if (estHeight != line.height) updateLineHeight(line, estHeight);\n    });\n  }\n\n  function keyMapChanged(cm) {\n    var map = keyMap[cm.options.keyMap], style = map.style;\n    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\\s*cm-keymap-\\S+/g, \"\") +\n      (style ? \" cm-keymap-\" + style : \"\");\n  }\n\n  function themeChanged(cm) {\n    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\\s*cm-s-\\S+/g, \"\") +\n      cm.options.theme.replace(/(^|\\s)\\s*/g, \" cm-s-\");\n    clearCaches(cm);\n  }\n\n  function guttersChanged(cm) {\n    updateGutters(cm);\n    regChange(cm);\n    setTimeout(function(){alignHorizontally(cm);}, 20);\n  }\n\n  function updateGutters(cm) {\n    var gutters = cm.display.gutters, specs = cm.options.gutters;\n    removeChildren(gutters);\n    for (var i = 0; i < specs.length; ++i) {\n      var gutterClass = specs[i];\n      var gElt = gutters.appendChild(elt(\"div\", null, \"CodeMirror-gutter \" + gutterClass));\n      if (gutterClass == \"CodeMirror-linenumbers\") {\n        cm.display.lineGutter = gElt;\n        gElt.style.width = (cm.display.lineNumWidth || 1) + \"px\";\n      }\n    }\n    gutters.style.display = i ? \"\" : \"none\";\n  }\n\n  function lineLength(doc, line) {\n    if (line.height == 0) return 0;\n    var len = line.text.length, merged, cur = line;\n    while (merged = collapsedSpanAtStart(cur)) {\n      var found = merged.find();\n      cur = getLine(doc, found.from.line);\n      len += found.from.ch - found.to.ch;\n    }\n    cur = line;\n    while (merged = collapsedSpanAtEnd(cur)) {\n      var found = merged.find();\n      len -= cur.text.length - found.from.ch;\n      cur = getLine(doc, found.to.line);\n      len += cur.text.length - found.to.ch;\n    }\n    return len;\n  }\n\n  function computeMaxLength(cm) {\n    var d = cm.display, doc = cm.doc;\n    d.maxLine = getLine(doc, doc.first);\n    d.maxLineLength = lineLength(doc, d.maxLine);\n    d.maxLineChanged = true;\n    doc.iter(function(line) {\n      var len = lineLength(doc, line);\n      if (len > d.maxLineLength) {\n        d.maxLineLength = len;\n        d.maxLine = line;\n      }\n    });\n  }\n\n  // Make sure the gutters options contains the element\n  // \"CodeMirror-linenumbers\" when the lineNumbers option is true.\n  function setGuttersForLineNumbers(options) {\n    var found = indexOf(options.gutters, \"CodeMirror-linenumbers\");\n    if (found == -1 && options.lineNumbers) {\n      options.gutters = options.gutters.concat([\"CodeMirror-linenumbers\"]);\n    } else if (found > -1 && !options.lineNumbers) {\n      options.gutters = options.gutters.slice(0);\n      options.gutters.splice(found, 1);\n    }\n  }\n\n  // SCROLLBARS\n\n  // Re-synchronize the fake scrollbars with the actual size of the\n  // content. Optionally force a scrollTop.\n  function updateScrollbars(cm) {\n    var d = cm.display, docHeight = cm.doc.height;\n    var totalHeight = docHeight + paddingVert(d);\n    d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + \"px\";\n    d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + \"px\";\n    var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);\n    var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);\n    var needsV = scrollHeight > (d.scroller.clientHeight + 1);\n    if (needsV) {\n      d.scrollbarV.style.display = \"block\";\n      d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + \"px\" : \"0\";\n      // A bug in IE8 can cause this value to be negative, so guard it.\n      d.scrollbarV.firstChild.style.height =\n        Math.max(0, scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + \"px\";\n    } else {\n      d.scrollbarV.style.display = \"\";\n      d.scrollbarV.firstChild.style.height = \"0\";\n    }\n    if (needsH) {\n      d.scrollbarH.style.display = \"block\";\n      d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + \"px\" : \"0\";\n      d.scrollbarH.firstChild.style.width =\n        (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + \"px\";\n    } else {\n      d.scrollbarH.style.display = \"\";\n      d.scrollbarH.firstChild.style.width = \"0\";\n    }\n    if (needsH && needsV) {\n      d.scrollbarFiller.style.display = \"block\";\n      d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + \"px\";\n    } else d.scrollbarFiller.style.display = \"\";\n    if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {\n      d.gutterFiller.style.display = \"block\";\n      d.gutterFiller.style.height = scrollbarWidth(d.measure) + \"px\";\n      d.gutterFiller.style.width = d.gutters.offsetWidth + \"px\";\n    } else d.gutterFiller.style.display = \"\";\n\n    if (mac_geLion && scrollbarWidth(d.measure) === 0) {\n      d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? \"18px\" : \"12px\";\n      d.scrollbarV.style.pointerEvents = d.scrollbarH.style.pointerEvents = \"none\";\n    }\n  }\n\n  function visibleLines(display, doc, viewPort) {\n    var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;\n    if (typeof viewPort == \"number\") top = viewPort;\n    else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}\n    top = Math.floor(top - paddingTop(display));\n    var bottom = Math.ceil(top + height);\n    return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};\n  }\n\n  // LINE NUMBERS\n\n  function alignHorizontally(cm) {\n    var display = cm.display;\n    if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;\n    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;\n    var gutterW = display.gutters.offsetWidth, l = comp + \"px\";\n    for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {\n      for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;\n    }\n    if (cm.options.fixedGutter)\n      display.gutters.style.left = (comp + gutterW) + \"px\";\n  }\n\n  function maybeUpdateLineNumberWidth(cm) {\n    if (!cm.options.lineNumbers) return false;\n    var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;\n    if (last.length != display.lineNumChars) {\n      var test = display.measure.appendChild(elt(\"div\", [elt(\"div\", last)],\n                                                 \"CodeMirror-linenumber CodeMirror-gutter-elt\"));\n      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;\n      display.lineGutter.style.width = \"\";\n      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);\n      display.lineNumWidth = display.lineNumInnerWidth + padding;\n      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;\n      display.lineGutter.style.width = display.lineNumWidth + \"px\";\n      return true;\n    }\n    return false;\n  }\n\n  function lineNumberFor(options, i) {\n    return String(options.lineNumberFormatter(i + options.firstLineNumber));\n  }\n  function compensateForHScroll(display) {\n    return getRect(display.scroller).left - getRect(display.sizer).left;\n  }\n\n  // DISPLAY DRAWING\n\n  function updateDisplay(cm, changes, viewPort, forced) {\n    var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;\n    var visible = visibleLines(cm.display, cm.doc, viewPort);\n    for (var first = true;; first = false) {\n      var oldWidth = cm.display.scroller.clientWidth;\n      if (!updateDisplayInner(cm, changes, visible, forced)) break;\n      updated = true;\n      changes = [];\n      updateSelection(cm);\n      updateScrollbars(cm);\n      if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {\n        forced = true;\n        continue;\n      }\n      forced = false;\n\n      // Clip forced viewport to actual scrollable area\n      if (viewPort)\n        viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,\n                            typeof viewPort == \"number\" ? viewPort : viewPort.top);\n      visible = visibleLines(cm.display, cm.doc, viewPort);\n      if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)\n        break;\n    }\n\n    if (updated) {\n      signalLater(cm, \"update\", cm);\n      if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)\n        signalLater(cm, \"viewportChange\", cm, cm.display.showingFrom, cm.display.showingTo);\n    }\n    return updated;\n  }\n\n  // Uses a set of changes plus the current scroll position to\n  // determine which DOM updates have to be made, and makes the\n  // updates.\n  function updateDisplayInner(cm, changes, visible, forced) {\n    var display = cm.display, doc = cm.doc;\n    if (!display.wrapper.offsetWidth) {\n      display.showingFrom = display.showingTo = doc.first;\n      display.viewOffset = 0;\n      return;\n    }\n\n    // Bail out if the visible area is already rendered and nothing changed.\n    if (!forced && changes.length == 0 &&\n        visible.from > display.showingFrom && visible.to < display.showingTo)\n      return;\n\n    if (maybeUpdateLineNumberWidth(cm))\n      changes = [{from: doc.first, to: doc.first + doc.size}];\n    var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + \"px\";\n    display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : \"0\";\n\n    // Used to determine which lines need their line numbers updated\n    var positionsChangedFrom = Infinity;\n    if (cm.options.lineNumbers)\n      for (var i = 0; i < changes.length; ++i)\n        if (changes[i].diff && changes[i].from < positionsChangedFrom) { positionsChangedFrom = changes[i].from; }\n\n    var end = doc.first + doc.size;\n    var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);\n    var to = Math.min(end, visible.to + cm.options.viewportMargin);\n    if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);\n    if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);\n    if (sawCollapsedSpans) {\n      from = lineNo(visualLine(doc, getLine(doc, from)));\n      while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;\n    }\n\n    // Create a range of theoretically intact lines, and punch holes\n    // in that using the change info.\n    var intact = [{from: Math.max(display.showingFrom, doc.first),\n                   to: Math.min(display.showingTo, end)}];\n    if (intact[0].from >= intact[0].to) intact = [];\n    else intact = computeIntact(intact, changes);\n    // When merged lines are present, we might have to reduce the\n    // intact ranges because changes in continued fragments of the\n    // intact lines do require the lines to be redrawn.\n    if (sawCollapsedSpans)\n      for (var i = 0; i < intact.length; ++i) {\n        var range = intact[i], merged;\n        while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {\n          var newTo = merged.find().from.line;\n          if (newTo > range.from) range.to = newTo;\n          else { intact.splice(i--, 1); break; }\n        }\n      }\n\n    // Clip off the parts that won't be visible\n    var intactLines = 0;\n    for (var i = 0; i < intact.length; ++i) {\n      var range = intact[i];\n      if (range.from < from) range.from = from;\n      if (range.to > to) range.to = to;\n      if (range.from >= range.to) intact.splice(i--, 1);\n      else intactLines += range.to - range.from;\n    }\n    if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {\n      updateViewOffset(cm);\n      return;\n    }\n    intact.sort(function(a, b) {return a.from - b.from;});\n\n    // Avoid crashing on IE's \"unspecified error\" when in iframes\n    try {\n      var focused = document.activeElement;\n    } catch(e) {}\n    if (intactLines < (to - from) * .7) display.lineDiv.style.display = \"none\";\n    patchDisplay(cm, from, to, intact, positionsChangedFrom);\n    display.lineDiv.style.display = \"\";\n    if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();\n\n    var different = from != display.showingFrom || to != display.showingTo ||\n      display.lastSizeC != display.wrapper.clientHeight;\n    // This is just a bogus formula that detects when the editor is\n    // resized or the font size changes.\n    if (different) {\n      display.lastSizeC = display.wrapper.clientHeight;\n      startWorker(cm, 400);\n    }\n    display.showingFrom = from; display.showingTo = to;\n\n    display.gutters.style.height = \"\";\n    updateHeightsInViewport(cm);\n    updateViewOffset(cm);\n\n    return true;\n  }\n\n  function updateHeightsInViewport(cm) {\n    var display = cm.display;\n    var prevBottom = display.lineDiv.offsetTop;\n    for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {\n      if (ie_lt8) {\n        var bot = node.offsetTop + node.offsetHeight;\n        height = bot - prevBottom;\n        prevBottom = bot;\n      } else {\n        var box = getRect(node);\n        height = box.bottom - box.top;\n      }\n      var diff = node.lineObj.height - height;\n      if (height < 2) height = textHeight(display);\n      if (diff > .001 || diff < -.001) {\n        updateLineHeight(node.lineObj, height);\n        var widgets = node.lineObj.widgets;\n        if (widgets) for (var i = 0; i < widgets.length; ++i)\n          widgets[i].height = widgets[i].node.offsetHeight;\n      }\n    }\n  }\n\n  function updateViewOffset(cm) {\n    var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));\n    // Position the mover div to align with the current virtual scroll position\n    cm.display.mover.style.top = off + \"px\";\n  }\n\n  function computeIntact(intact, changes) {\n    for (var i = 0, l = changes.length || 0; i < l; ++i) {\n      var change = changes[i], intact2 = [], diff = change.diff || 0;\n      for (var j = 0, l2 = intact.length; j < l2; ++j) {\n        var range = intact[j];\n        if (change.to <= range.from && change.diff) {\n          intact2.push({from: range.from + diff, to: range.to + diff});\n        } else if (change.to <= range.from || change.from >= range.to) {\n          intact2.push(range);\n        } else {\n          if (change.from > range.from)\n            intact2.push({from: range.from, to: change.from});\n          if (change.to < range.to)\n            intact2.push({from: change.to + diff, to: range.to + diff});\n        }\n      }\n      intact = intact2;\n    }\n    return intact;\n  }\n\n  function getDimensions(cm) {\n    var d = cm.display, left = {}, width = {};\n    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {\n      left[cm.options.gutters[i]] = n.offsetLeft;\n      width[cm.options.gutters[i]] = n.offsetWidth;\n    }\n    return {fixedPos: compensateForHScroll(d),\n            gutterTotalWidth: d.gutters.offsetWidth,\n            gutterLeft: left,\n            gutterWidth: width,\n            wrapperWidth: d.wrapper.clientWidth};\n  }\n\n  function patchDisplay(cm, from, to, intact, updateNumbersFrom) {\n    var dims = getDimensions(cm);\n    var display = cm.display, lineNumbers = cm.options.lineNumbers;\n    if (!intact.length && (!webkit || !cm.display.currentWheelTarget))\n      removeChildren(display.lineDiv);\n    var container = display.lineDiv, cur = container.firstChild;\n\n    function rm(node) {\n      var next = node.nextSibling;\n      if (webkit && mac && cm.display.currentWheelTarget == node) {\n        node.style.display = \"none\";\n        node.lineObj = null;\n      } else {\n        node.parentNode.removeChild(node);\n      }\n      return next;\n    }\n\n    var nextIntact = intact.shift(), lineN = from;\n    cm.doc.iter(from, to, function(line) {\n      if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();\n      if (lineIsHidden(cm.doc, line)) {\n        if (line.height != 0) updateLineHeight(line, 0);\n        if (line.widgets && cur && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {\n          var w = line.widgets[i];\n          if (w.showIfHidden) {\n            var prev = cur.previousSibling;\n            if (/pre/i.test(prev.nodeName)) {\n              var wrap = elt(\"div\", null, null, \"position: relative\");\n              prev.parentNode.replaceChild(wrap, prev);\n              wrap.appendChild(prev);\n              prev = wrap;\n            }\n            var wnode = prev.appendChild(elt(\"div\", [w.node], \"CodeMirror-linewidget\"));\n            if (!w.handleMouseEvents) wnode.ignoreEvents = true;\n            positionLineWidget(w, wnode, prev, dims);\n          }\n        }\n      } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {\n        // This line is intact. Skip to the actual node. Update its\n        // line number if needed.\n        while (cur.lineObj != line) cur = rm(cur);\n        if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)\n          setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));\n        cur = cur.nextSibling;\n      } else {\n        // For lines with widgets, make an attempt to find and reuse\n        // the existing element, so that widgets aren't needlessly\n        // removed and re-inserted into the dom\n        if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)\n          if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }\n        // This line needs to be generated.\n        var lineNode = buildLineElement(cm, line, lineN, dims, reuse);\n        if (lineNode != reuse) {\n          container.insertBefore(lineNode, cur);\n        } else {\n          while (cur != reuse) cur = rm(cur);\n          cur = cur.nextSibling;\n        }\n\n        lineNode.lineObj = line;\n      }\n      ++lineN;\n    });\n    while (cur) cur = rm(cur);\n  }\n\n  function buildLineElement(cm, line, lineNo, dims, reuse) {\n    var built = buildLineContent(cm, line), lineElement = built.pre;\n    var markers = line.gutterMarkers, display = cm.display, wrap;\n\n    var bgClass = built.bgClass ? built.bgClass + \" \" + (line.bgClass || \"\") : line.bgClass;\n    if (!cm.options.lineNumbers && !markers && !bgClass && !line.wrapClass && !line.widgets)\n      return lineElement;\n\n    // Lines with gutter elements, widgets or a background class need\n    // to be wrapped again, and have the extra elements added to the\n    // wrapper div\n\n    if (reuse) {\n      reuse.alignable = null;\n      var isOk = true, widgetsSeen = 0, insertBefore = null;\n      for (var n = reuse.firstChild, next; n; n = next) {\n        next = n.nextSibling;\n        if (!/\\bCodeMirror-linewidget\\b/.test(n.className)) {\n          reuse.removeChild(n);\n        } else {\n          for (var i = 0; i < line.widgets.length; ++i) {\n            var widget = line.widgets[i];\n            if (widget.node == n.firstChild) {\n              if (!widget.above && !insertBefore) insertBefore = n;\n              positionLineWidget(widget, n, reuse, dims);\n              ++widgetsSeen;\n              break;\n            }\n          }\n          if (i == line.widgets.length) { isOk = false; break; }\n        }\n      }\n      reuse.insertBefore(lineElement, insertBefore);\n      if (isOk && widgetsSeen == line.widgets.length) {\n        wrap = reuse;\n        reuse.className = line.wrapClass || \"\";\n      }\n    }\n    if (!wrap) {\n      wrap = elt(\"div\", null, line.wrapClass, \"position: relative\");\n      wrap.appendChild(lineElement);\n    }\n    // Kludge to make sure the styled element lies behind the selection (by z-index)\n    if (bgClass)\n      wrap.insertBefore(elt(\"div\", null, bgClass + \" CodeMirror-linebackground\"), wrap.firstChild);\n    if (cm.options.lineNumbers || markers) {\n      var gutterWrap = wrap.insertBefore(elt(\"div\", null, \"CodeMirror-gutter-wrapper\", \"position: absolute; left: \" +\n                                             (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + \"px\"),\n                                         lineElement);\n      if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);\n      if (cm.options.lineNumbers && (!markers || !markers[\"CodeMirror-linenumbers\"]))\n        wrap.lineNumber = gutterWrap.appendChild(\n          elt(\"div\", lineNumberFor(cm.options, lineNo),\n              \"CodeMirror-linenumber CodeMirror-gutter-elt\",\n              \"left: \" + dims.gutterLeft[\"CodeMirror-linenumbers\"] + \"px; width: \"\n              + display.lineNumInnerWidth + \"px\"));\n      if (markers)\n        for (var k = 0; k < cm.options.gutters.length; ++k) {\n          var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];\n          if (found)\n            gutterWrap.appendChild(elt(\"div\", [found], \"CodeMirror-gutter-elt\", \"left: \" +\n                                       dims.gutterLeft[id] + \"px; width: \" + dims.gutterWidth[id] + \"px\"));\n        }\n    }\n    if (ie_lt8) wrap.style.zIndex = 2;\n    if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {\n      var widget = ws[i], node = elt(\"div\", [widget.node], \"CodeMirror-linewidget\");\n      if (!widget.handleMouseEvents) node.ignoreEvents = true;\n      positionLineWidget(widget, node, wrap, dims);\n      if (widget.above)\n        wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);\n      else\n        wrap.appendChild(node);\n      signalLater(widget, \"redraw\");\n    }\n    return wrap;\n  }\n\n  function positionLineWidget(widget, node, wrap, dims) {\n    if (widget.noHScroll) {\n      (wrap.alignable || (wrap.alignable = [])).push(node);\n      var width = dims.wrapperWidth;\n      node.style.left = dims.fixedPos + \"px\";\n      if (!widget.coverGutter) {\n        width -= dims.gutterTotalWidth;\n        node.style.paddingLeft = dims.gutterTotalWidth + \"px\";\n      }\n      node.style.width = width + \"px\";\n    }\n    if (widget.coverGutter) {\n      node.style.zIndex = 5;\n      node.style.position = \"relative\";\n      if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + \"px\";\n    }\n  }\n\n  // SELECTION / CURSOR\n\n  function updateSelection(cm) {\n    var display = cm.display;\n    var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);\n    if (collapsed || cm.options.showCursorWhenSelecting)\n      updateSelectionCursor(cm);\n    else\n      display.cursor.style.display = display.otherCursor.style.display = \"none\";\n    if (!collapsed)\n      updateSelectionRange(cm);\n    else\n      display.selectionDiv.style.display = \"none\";\n\n    // Move the hidden textarea near the cursor to prevent scrolling artifacts\n    if (cm.options.moveInputWithCursor) {\n      var headPos = cursorCoords(cm, cm.doc.sel.head, \"div\");\n      var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);\n      display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,\n                                                        headPos.top + lineOff.top - wrapOff.top)) + \"px\";\n      display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,\n                                                         headPos.left + lineOff.left - wrapOff.left)) + \"px\";\n    }\n  }\n\n  // No selection, plain cursor\n  function updateSelectionCursor(cm) {\n    var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, \"div\");\n    display.cursor.style.left = pos.left + \"px\";\n    display.cursor.style.top = pos.top + \"px\";\n    display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + \"px\";\n    display.cursor.style.display = \"\";\n\n    if (pos.other) {\n      display.otherCursor.style.display = \"\";\n      display.otherCursor.style.left = pos.other.left + \"px\";\n      display.otherCursor.style.top = pos.other.top + \"px\";\n      display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + \"px\";\n    } else { display.otherCursor.style.display = \"none\"; }\n  }\n\n  // Highlight selection\n  function updateSelectionRange(cm) {\n    var display = cm.display, doc = cm.doc, sel = cm.doc.sel;\n    var fragment = document.createDocumentFragment();\n    var padding = paddingH(cm.display), leftSide = padding.left, rightSide = display.lineSpace.offsetWidth - padding.right;\n\n    function add(left, top, width, bottom) {\n      if (top < 0) top = 0;\n      fragment.appendChild(elt(\"div\", null, \"CodeMirror-selected\", \"position: absolute; left: \" + left +\n                               \"px; top: \" + top + \"px; width: \" + (width == null ? rightSide - left : width) +\n                               \"px; height: \" + (bottom - top) + \"px\"));\n    }\n\n    function drawForLine(line, fromArg, toArg) {\n      var lineObj = getLine(doc, line);\n      var lineLen = lineObj.text.length;\n      var start, end;\n      function coords(ch, bias) {\n        return charCoords(cm, Pos(line, ch), \"div\", lineObj, bias);\n      }\n\n      iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {\n        var leftPos = coords(from, \"left\"), rightPos, left, right;\n        if (from == to) {\n          rightPos = leftPos;\n          left = right = leftPos.left;\n        } else {\n          rightPos = coords(to - 1, \"right\");\n          if (dir == \"rtl\") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }\n          left = leftPos.left;\n          right = rightPos.right;\n        }\n        if (fromArg == null && from == 0) left = leftSide;\n        if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part\n          add(left, leftPos.top, null, leftPos.bottom);\n          left = leftSide;\n          if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);\n        }\n        if (toArg == null && to == lineLen) right = rightSide;\n        if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)\n          start = leftPos;\n        if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)\n          end = rightPos;\n        if (left < leftSide + 1) left = leftSide;\n        add(left, rightPos.top, right - left, rightPos.bottom);\n      });\n      return {start: start, end: end};\n    }\n\n    if (sel.from.line == sel.to.line) {\n      drawForLine(sel.from.line, sel.from.ch, sel.to.ch);\n    } else {\n      var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);\n      var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);\n      var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;\n      var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;\n      if (singleVLine) {\n        if (leftEnd.top < rightStart.top - 2) {\n          add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);\n          add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);\n        } else {\n          add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);\n        }\n      }\n      if (leftEnd.bottom < rightStart.top)\n        add(leftSide, leftEnd.bottom, null, rightStart.top);\n    }\n\n    removeChildrenAndAdd(display.selectionDiv, fragment);\n    display.selectionDiv.style.display = \"\";\n  }\n\n  // Cursor-blinking\n  function restartBlink(cm) {\n    if (!cm.state.focused) return;\n    var display = cm.display;\n    clearInterval(display.blinker);\n    var on = true;\n    display.cursor.style.visibility = display.otherCursor.style.visibility = \"\";\n    if (cm.options.cursorBlinkRate > 0)\n      display.blinker = setInterval(function() {\n        display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? \"\" : \"hidden\";\n      }, cm.options.cursorBlinkRate);\n  }\n\n  // HIGHLIGHT WORKER\n\n  function startWorker(cm, time) {\n    if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)\n      cm.state.highlight.set(time, bind(highlightWorker, cm));\n  }\n\n  function highlightWorker(cm) {\n    var doc = cm.doc;\n    if (doc.frontier < doc.first) doc.frontier = doc.first;\n    if (doc.frontier >= cm.display.showingTo) return;\n    var end = +new Date + cm.options.workTime;\n    var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));\n    var changed = [], prevChange;\n    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {\n      if (doc.frontier >= cm.display.showingFrom) { // Visible\n        var oldStyles = line.styles;\n        line.styles = highlightLine(cm, line, state, true);\n        var ischange = !oldStyles || oldStyles.length != line.styles.length;\n        for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];\n        if (ischange) {\n          if (prevChange && prevChange.end == doc.frontier) prevChange.end++;\n          else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});\n        }\n        line.stateAfter = copyState(doc.mode, state);\n      } else {\n        processLine(cm, line.text, state);\n        line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;\n      }\n      ++doc.frontier;\n      if (+new Date > end) {\n        startWorker(cm, cm.options.workDelay);\n        return true;\n      }\n    });\n    if (changed.length)\n      operation(cm, function() {\n        for (var i = 0; i < changed.length; ++i)\n          regChange(this, changed[i].start, changed[i].end);\n      })();\n  }\n\n  // Finds the line to start with when starting a parse. Tries to\n  // find a line with a stateAfter, so that it can start with a\n  // valid state. If that fails, it returns the line with the\n  // smallest indentation, which tends to need the least context to\n  // parse correctly.\n  function findStartLine(cm, n, precise) {\n    var minindent, minline, doc = cm.doc;\n    var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);\n    for (var search = n; search > lim; --search) {\n      if (search <= doc.first) return doc.first;\n      var line = getLine(doc, search - 1);\n      if (line.stateAfter && (!precise || search <= doc.frontier)) return search;\n      var indented = countColumn(line.text, null, cm.options.tabSize);\n      if (minline == null || minindent > indented) {\n        minline = search - 1;\n        minindent = indented;\n      }\n    }\n    return minline;\n  }\n\n  function getStateBefore(cm, n, precise) {\n    var doc = cm.doc, display = cm.display;\n    if (!doc.mode.startState) return true;\n    var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;\n    if (!state) state = startState(doc.mode);\n    else state = copyState(doc.mode, state);\n    doc.iter(pos, n, function(line) {\n      processLine(cm, line.text, state);\n      var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;\n      line.stateAfter = save ? copyState(doc.mode, state) : null;\n      ++pos;\n    });\n    if (precise) doc.frontier = pos;\n    return state;\n  }\n\n  // POSITION MEASUREMENT\n\n  function paddingTop(display) {return display.lineSpace.offsetTop;}\n  function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}\n  function paddingH(display) {\n    if (display.cachedPaddingH) return display.cachedPaddingH;\n    var e = removeChildrenAndAdd(display.measure, elt(\"pre\", \"x\"));\n    var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;\n    return display.cachedPaddingH = {left: parseInt(style.paddingLeft),\n                                     right: parseInt(style.paddingRight)};\n  }\n\n  function measureChar(cm, line, ch, data, bias) {\n    var dir = -1;\n    data = data || measureLine(cm, line);\n    if (data.crude) {\n      var left = data.left + ch * data.width;\n      return {left: left, right: left + data.width, top: data.top, bottom: data.bottom};\n    }\n\n    for (var pos = ch;; pos += dir) {\n      var r = data[pos];\n      if (r) break;\n      if (dir < 0 && pos == 0) dir = 1;\n    }\n    bias = pos > ch ? \"left\" : pos < ch ? \"right\" : bias;\n    if (bias == \"left\" && r.leftSide) r = r.leftSide;\n    else if (bias == \"right\" && r.rightSide) r = r.rightSide;\n    return {left: pos < ch ? r.right : r.left,\n            right: pos > ch ? r.left : r.right,\n            top: r.top,\n            bottom: r.bottom};\n  }\n\n  function findCachedMeasurement(cm, line) {\n    var cache = cm.display.measureLineCache;\n    for (var i = 0; i < cache.length; ++i) {\n      var memo = cache[i];\n      if (memo.text == line.text && memo.markedSpans == line.markedSpans &&\n          cm.display.scroller.clientWidth == memo.width &&\n          memo.classes == line.textClass + \"|\" + line.wrapClass)\n        return memo;\n    }\n  }\n\n  function clearCachedMeasurement(cm, line) {\n    var exists = findCachedMeasurement(cm, line);\n    if (exists) exists.text = exists.measure = exists.markedSpans = null;\n  }\n\n  function measureLine(cm, line) {\n    // First look in the cache\n    var cached = findCachedMeasurement(cm, line);\n    if (cached) return cached.measure;\n\n    // Failing that, recompute and store result in cache\n    var measure = measureLineInner(cm, line);\n    var cache = cm.display.measureLineCache;\n    var memo = {text: line.text, width: cm.display.scroller.clientWidth,\n                markedSpans: line.markedSpans, measure: measure,\n                classes: line.textClass + \"|\" + line.wrapClass};\n    if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;\n    else cache.push(memo);\n    return measure;\n  }\n\n  function measureLineInner(cm, line) {\n    if (!cm.options.lineWrapping && line.text.length >= cm.options.crudeMeasuringFrom)\n      return crudelyMeasureLine(cm, line);\n\n    var display = cm.display, measure = emptyArray(line.text.length);\n    var pre = buildLineContent(cm, line, measure, true).pre;\n\n    // IE does not cache element positions of inline elements between\n    // calls to getBoundingClientRect. This makes the loop below,\n    // which gathers the positions of all the characters on the line,\n    // do an amount of layout work quadratic to the number of\n    // characters. When line wrapping is off, we try to improve things\n    // by first subdividing the line into a bunch of inline blocks, so\n    // that IE can reuse most of the layout information from caches\n    // for those blocks. This does interfere with line wrapping, so it\n    // doesn't work when wrapping is on, but in that case the\n    // situation is slightly better, since IE does cache line-wrapping\n    // information and only recomputes per-line.\n    if (old_ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {\n      var fragment = document.createDocumentFragment();\n      var chunk = 10, n = pre.childNodes.length;\n      for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {\n        var wrap = elt(\"div\", null, null, \"display: inline-block\");\n        for (var j = 0; j < chunk && n; ++j) {\n          wrap.appendChild(pre.firstChild);\n          --n;\n        }\n        fragment.appendChild(wrap);\n      }\n      pre.appendChild(fragment);\n    }\n\n    removeChildrenAndAdd(display.measure, pre);\n\n    var outer = getRect(display.lineDiv);\n    var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;\n    // Work around an IE7/8 bug where it will sometimes have randomly\n    // replaced our pre with a clone at this point.\n    if (ie_lt9 && display.measure.first != pre)\n      removeChildrenAndAdd(display.measure, pre);\n\n    function measureRect(rect) {\n      var top = rect.top - outer.top, bot = rect.bottom - outer.top;\n      if (bot > maxBot) bot = maxBot;\n      if (top < 0) top = 0;\n      for (var i = vranges.length - 2; i >= 0; i -= 2) {\n        var rtop = vranges[i], rbot = vranges[i+1];\n        if (rtop > bot || rbot < top) continue;\n        if (rtop <= top && rbot >= bot ||\n            top <= rtop && bot >= rbot ||\n            Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {\n          vranges[i] = Math.min(top, rtop);\n          vranges[i+1] = Math.max(bot, rbot);\n          break;\n        }\n      }\n      if (i < 0) { i = vranges.length; vranges.push(top, bot); }\n      return {left: rect.left - outer.left,\n              right: rect.right - outer.left,\n              top: i, bottom: null};\n    }\n    function finishRect(rect) {\n      rect.bottom = vranges[rect.top+1];\n      rect.top = vranges[rect.top];\n    }\n\n    for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {\n      var node = cur, rect = null;\n      // A widget might wrap, needs special care\n      if (/\\bCodeMirror-widget\\b/.test(cur.className) && cur.getClientRects) {\n        if (cur.firstChild.nodeType == 1) node = cur.firstChild;\n        var rects = node.getClientRects();\n        if (rects.length > 1) {\n          rect = data[i] = measureRect(rects[0]);\n          rect.rightSide = measureRect(rects[rects.length - 1]);\n        }\n      }\n      if (!rect) rect = data[i] = measureRect(getRect(node));\n      if (cur.measureRight) rect.right = getRect(cur.measureRight).left - outer.left;\n      if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));\n    }\n    removeChildren(cm.display.measure);\n    for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {\n      finishRect(cur);\n      if (cur.leftSide) finishRect(cur.leftSide);\n      if (cur.rightSide) finishRect(cur.rightSide);\n    }\n    return data;\n  }\n\n  function crudelyMeasureLine(cm, line) {\n    var copy = new Line(line.text.slice(0, 100), null);\n    if (line.textClass) copy.textClass = line.textClass;\n    var measure = measureLineInner(cm, copy);\n    var left = measureChar(cm, copy, 0, measure, \"left\");\n    var right = measureChar(cm, copy, 99, measure, \"right\");\n    return {crude: true, top: left.top, left: left.left, bottom: left.bottom, width: (right.right - left.left) / 100};\n  }\n\n  function measureLineWidth(cm, line) {\n    var hasBadSpan = false;\n    if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {\n      var sp = line.markedSpans[i];\n      if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;\n    }\n    var cached = !hasBadSpan && findCachedMeasurement(cm, line);\n    if (cached || line.text.length >= cm.options.crudeMeasuringFrom)\n      return measureChar(cm, line, line.text.length, cached && cached.measure, \"right\").right;\n\n    var pre = buildLineContent(cm, line, null, true).pre;\n    var end = pre.appendChild(zeroWidthElement(cm.display.measure));\n    removeChildrenAndAdd(cm.display.measure, pre);\n    return getRect(end).right - getRect(cm.display.lineDiv).left;\n  }\n\n  function clearCaches(cm) {\n    cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;\n    cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;\n    if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;\n    cm.display.lineNumChars = null;\n  }\n\n  function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }\n  function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }\n\n  // Context is one of \"line\", \"div\" (display.lineDiv), \"local\"/null (editor), or \"page\"\n  function intoCoordSystem(cm, lineObj, rect, context) {\n    if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {\n      var size = widgetHeight(lineObj.widgets[i]);\n      rect.top += size; rect.bottom += size;\n    }\n    if (context == \"line\") return rect;\n    if (!context) context = \"local\";\n    var yOff = heightAtLine(cm, lineObj);\n    if (context == \"local\") yOff += paddingTop(cm.display);\n    else yOff -= cm.display.viewOffset;\n    if (context == \"page\" || context == \"window\") {\n      var lOff = getRect(cm.display.lineSpace);\n      yOff += lOff.top + (context == \"window\" ? 0 : pageScrollY());\n      var xOff = lOff.left + (context == \"window\" ? 0 : pageScrollX());\n      rect.left += xOff; rect.right += xOff;\n    }\n    rect.top += yOff; rect.bottom += yOff;\n    return rect;\n  }\n\n  // Context may be \"window\", \"page\", \"div\", or \"local\"/null\n  // Result is in \"div\" coords\n  function fromCoordSystem(cm, coords, context) {\n    if (context == \"div\") return coords;\n    var left = coords.left, top = coords.top;\n    // First move into \"page\" coordinate system\n    if (context == \"page\") {\n      left -= pageScrollX();\n      top -= pageScrollY();\n    } else if (context == \"local\" || !context) {\n      var localBox = getRect(cm.display.sizer);\n      left += localBox.left;\n      top += localBox.top;\n    }\n\n    var lineSpaceBox = getRect(cm.display.lineSpace);\n    return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};\n  }\n\n  function charCoords(cm, pos, context, lineObj, bias) {\n    if (!lineObj) lineObj = getLine(cm.doc, pos.line);\n    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);\n  }\n\n  function cursorCoords(cm, pos, context, lineObj, measurement) {\n    lineObj = lineObj || getLine(cm.doc, pos.line);\n    if (!measurement) measurement = measureLine(cm, lineObj);\n    function get(ch, right) {\n      var m = measureChar(cm, lineObj, ch, measurement, right ? \"right\" : \"left\");\n      if (right) m.left = m.right; else m.right = m.left;\n      return intoCoordSystem(cm, lineObj, m, context);\n    }\n    function getBidi(ch, partPos) {\n      var part = order[partPos], right = part.level % 2;\n      if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {\n        part = order[--partPos];\n        ch = bidiRight(part) - (part.level % 2 ? 0 : 1);\n        right = true;\n      } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {\n        part = order[++partPos];\n        ch = bidiLeft(part) - part.level % 2;\n        right = false;\n      }\n      if (right && ch == part.to && ch > part.from) return get(ch - 1);\n      return get(ch, right);\n    }\n    var order = getOrder(lineObj), ch = pos.ch;\n    if (!order) return get(ch);\n    var partPos = getBidiPartAt(order, ch);\n    var val = getBidi(ch, partPos);\n    if (bidiOther != null) val.other = getBidi(ch, bidiOther);\n    return val;\n  }\n\n  function PosWithInfo(line, ch, outside, xRel) {\n    var pos = new Pos(line, ch);\n    pos.xRel = xRel;\n    if (outside) pos.outside = true;\n    return pos;\n  }\n\n  // Coords must be lineSpace-local\n  function coordsChar(cm, x, y) {\n    var doc = cm.doc;\n    y += cm.display.viewOffset;\n    if (y < 0) return PosWithInfo(doc.first, 0, true, -1);\n    var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;\n    if (lineNo > last)\n      return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);\n    if (x < 0) x = 0;\n\n    for (;;) {\n      var lineObj = getLine(doc, lineNo);\n      var found = coordsCharInner(cm, lineObj, lineNo, x, y);\n      var merged = collapsedSpanAtEnd(lineObj);\n      var mergedPos = merged && merged.find();\n      if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))\n        lineNo = mergedPos.to.line;\n      else\n        return found;\n    }\n  }\n\n  function coordsCharInner(cm, lineObj, lineNo, x, y) {\n    var innerOff = y - heightAtLine(cm, lineObj);\n    var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;\n    var measurement = measureLine(cm, lineObj);\n\n    function getX(ch) {\n      var sp = cursorCoords(cm, Pos(lineNo, ch), \"line\",\n                            lineObj, measurement);\n      wrongLine = true;\n      if (innerOff > sp.bottom) return sp.left - adjust;\n      else if (innerOff < sp.top) return sp.left + adjust;\n      else wrongLine = false;\n      return sp.left;\n    }\n\n    var bidi = getOrder(lineObj), dist = lineObj.text.length;\n    var from = lineLeft(lineObj), to = lineRight(lineObj);\n    var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;\n\n    if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);\n    // Do a binary search between these bounds.\n    for (;;) {\n      if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {\n        var ch = x < fromX || x - fromX <= toX - x ? from : to;\n        var xDiff = x - (ch == from ? fromX : toX);\n        while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;\n        var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,\n                              xDiff < 0 ? -1 : xDiff ? 1 : 0);\n        return pos;\n      }\n      var step = Math.ceil(dist / 2), middle = from + step;\n      if (bidi) {\n        middle = from;\n        for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);\n      }\n      var middleX = getX(middle);\n      if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}\n      else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}\n    }\n  }\n\n  var measureText;\n  function textHeight(display) {\n    if (display.cachedTextHeight != null) return display.cachedTextHeight;\n    if (measureText == null) {\n      measureText = elt(\"pre\");\n      // Measure a bunch of lines, for browsers that compute\n      // fractional heights.\n      for (var i = 0; i < 49; ++i) {\n        measureText.appendChild(document.createTextNode(\"x\"));\n        measureText.appendChild(elt(\"br\"));\n      }\n      measureText.appendChild(document.createTextNode(\"x\"));\n    }\n    removeChildrenAndAdd(display.measure, measureText);\n    var height = measureText.offsetHeight / 50;\n    if (height > 3) display.cachedTextHeight = height;\n    removeChildren(display.measure);\n    return height || 1;\n  }\n\n  function charWidth(display) {\n    if (display.cachedCharWidth != null) return display.cachedCharWidth;\n    var anchor = elt(\"span\", \"x\");\n    var pre = elt(\"pre\", [anchor]);\n    removeChildrenAndAdd(display.measure, pre);\n    var width = anchor.offsetWidth;\n    if (width > 2) display.cachedCharWidth = width;\n    return width || 10;\n  }\n\n  // OPERATIONS\n\n  // Operations are used to wrap changes in such a way that each\n  // change won't have to update the cursor and display (which would\n  // be awkward, slow, and error-prone), but instead updates are\n  // batched and then all combined and executed at once.\n\n  var nextOpId = 0;\n  function startOperation(cm) {\n    cm.curOp = {\n      // An array of ranges of lines that have to be updated. See\n      // updateDisplay.\n      changes: [],\n      forceUpdate: false,\n      updateInput: null,\n      userSelChange: null,\n      textChanged: null,\n      selectionChanged: false,\n      cursorActivity: false,\n      updateMaxLine: false,\n      updateScrollPos: false,\n      id: ++nextOpId\n    };\n    if (!delayedCallbackDepth++) delayedCallbacks = [];\n  }\n\n  function endOperation(cm) {\n    var op = cm.curOp, doc = cm.doc, display = cm.display;\n    cm.curOp = null;\n\n    if (op.updateMaxLine) computeMaxLength(cm);\n    if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {\n      var width = measureLineWidth(cm, display.maxLine);\n      display.sizer.style.minWidth = Math.max(0, width + 3) + \"px\";\n      display.maxLineChanged = false;\n      var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);\n      if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)\n        setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);\n    }\n    var newScrollPos, updated;\n    if (op.updateScrollPos) {\n      newScrollPos = op.updateScrollPos;\n    } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible\n      var coords = cursorCoords(cm, doc.sel.head);\n      newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);\n    }\n    if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {\n      updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);\n      if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;\n    }\n    if (!updated && op.selectionChanged) updateSelection(cm);\n    if (op.updateScrollPos) {\n      var top = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, newScrollPos.scrollTop));\n      var left = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, newScrollPos.scrollLeft));\n      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = top;\n      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = left;\n      alignHorizontally(cm);\n      if (op.scrollToPos)\n        scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos.from),\n                          clipPos(cm.doc, op.scrollToPos.to), op.scrollToPos.margin);\n    } else if (newScrollPos) {\n      scrollCursorIntoView(cm);\n    }\n    if (op.selectionChanged) restartBlink(cm);\n\n    if (cm.state.focused && op.updateInput)\n      resetInput(cm, op.userSelChange);\n\n    var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;\n    if (hidden) for (var i = 0; i < hidden.length; ++i)\n      if (!hidden[i].lines.length) signal(hidden[i], \"hide\");\n    if (unhidden) for (var i = 0; i < unhidden.length; ++i)\n      if (unhidden[i].lines.length) signal(unhidden[i], \"unhide\");\n\n    var delayed;\n    if (!--delayedCallbackDepth) {\n      delayed = delayedCallbacks;\n      delayedCallbacks = null;\n    }\n    if (op.textChanged)\n      signal(cm, \"change\", cm, op.textChanged);\n    if (op.cursorActivity) signal(cm, \"cursorActivity\", cm);\n    if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();\n  }\n\n  // Wraps a function in an operation. Returns the wrapped function.\n  function operation(cm1, f) {\n    return function() {\n      var cm = cm1 || this, withOp = !cm.curOp;\n      if (withOp) startOperation(cm);\n      try { var result = f.apply(cm, arguments); }\n      finally { if (withOp) endOperation(cm); }\n      return result;\n    };\n  }\n  function docOperation(f) {\n    return function() {\n      var withOp = this.cm && !this.cm.curOp, result;\n      if (withOp) startOperation(this.cm);\n      try { result = f.apply(this, arguments); }\n      finally { if (withOp) endOperation(this.cm); }\n      return result;\n    };\n  }\n  function runInOp(cm, f) {\n    var withOp = !cm.curOp, result;\n    if (withOp) startOperation(cm);\n    try { result = f(); }\n    finally { if (withOp) endOperation(cm); }\n    return result;\n  }\n\n  function regChange(cm, from, to, lendiff) {\n    if (from == null) from = cm.doc.first;\n    if (to == null) to = cm.doc.first + cm.doc.size;\n    cm.curOp.changes.push({from: from, to: to, diff: lendiff});\n  }\n\n  // INPUT HANDLING\n\n  function slowPoll(cm) {\n    if (cm.display.pollingFast) return;\n    cm.display.poll.set(cm.options.pollInterval, function() {\n      readInput(cm);\n      if (cm.state.focused) slowPoll(cm);\n    });\n  }\n\n  function fastPoll(cm) {\n    var missed = false;\n    cm.display.pollingFast = true;\n    function p() {\n      var changed = readInput(cm);\n      if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}\n      else {cm.display.pollingFast = false; slowPoll(cm);}\n    }\n    cm.display.poll.set(20, p);\n  }\n\n  // prevInput is a hack to work with IME. If we reset the textarea\n  // on every change, that breaks IME. So we look for changes\n  // compared to the previous content instead. (Modern browsers have\n  // events that indicate IME taking place, but these are not widely\n  // supported or compatible enough yet to rely on.)\n  function readInput(cm) {\n    var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;\n    if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.options.disableInput) return false;\n    if (cm.state.pasteIncoming && cm.state.fakedLastChar) {\n      input.value = input.value.substring(0, input.value.length - 1);\n      cm.state.fakedLastChar = false;\n    }\n    var text = input.value;\n    if (text == prevInput && posEq(sel.from, sel.to)) return false;\n    if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {\n      resetInput(cm, true);\n      return false;\n    }\n\n    var withOp = !cm.curOp;\n    if (withOp) startOperation(cm);\n    sel.shift = false;\n    var same = 0, l = Math.min(prevInput.length, text.length);\n    while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;\n    var from = sel.from, to = sel.to;\n    var inserted = text.slice(same);\n    if (same < prevInput.length)\n      from = Pos(from.line, from.ch - (prevInput.length - same));\n    else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)\n      to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + inserted.length));\n\n    var updateInput = cm.curOp.updateInput;\n    var changeEvent = {from: from, to: to, text: splitLines(inserted),\n                       origin: cm.state.pasteIncoming ? \"paste\" : cm.state.cutIncoming ? \"cut\" : \"+input\"};\n    makeChange(cm.doc, changeEvent, \"end\");\n    cm.curOp.updateInput = updateInput;\n    signalLater(cm, \"inputRead\", cm, changeEvent);\n    if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&\n        cm.options.smartIndent && sel.head.ch < 100) {\n      var electric = cm.getModeAt(sel.head).electricChars;\n      if (electric) for (var i = 0; i < electric.length; i++)\n        if (inserted.indexOf(electric.charAt(i)) > -1) {\n          indentLine(cm, sel.head.line, \"smart\");\n          break;\n        }\n    }\n\n    if (text.length > 1000 || text.indexOf(\"\\n\") > -1) input.value = cm.display.prevInput = \"\";\n    else cm.display.prevInput = text;\n    if (withOp) endOperation(cm);\n    cm.state.pasteIncoming = cm.state.cutIncoming = false;\n    return true;\n  }\n\n  function resetInput(cm, user) {\n    var minimal, selected, doc = cm.doc;\n    if (!posEq(doc.sel.from, doc.sel.to)) {\n      cm.display.prevInput = \"\";\n      minimal = hasCopyEvent &&\n        (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);\n      var content = minimal ? \"-\" : selected || cm.getSelection();\n      cm.display.input.value = content;\n      if (cm.state.focused) selectInput(cm.display.input);\n      if (ie && !ie_lt9) cm.display.inputHasSelection = content;\n    } else if (user) {\n      cm.display.prevInput = cm.display.input.value = \"\";\n      if (ie && !ie_lt9) cm.display.inputHasSelection = null;\n    }\n    cm.display.inaccurateSelection = minimal;\n  }\n\n  function focusInput(cm) {\n    if (cm.options.readOnly != \"nocursor\" && (!mobile || document.activeElement != cm.display.input))\n      cm.display.input.focus();\n  }\n\n  function ensureFocus(cm) {\n    if (!cm.state.focused) { focusInput(cm); onFocus(cm); }\n  }\n\n  function isReadOnly(cm) {\n    return cm.options.readOnly || cm.doc.cantEdit;\n  }\n\n  // EVENT HANDLERS\n\n  function registerEventHandlers(cm) {\n    var d = cm.display;\n    on(d.scroller, \"mousedown\", operation(cm, onMouseDown));\n    if (old_ie)\n      on(d.scroller, \"dblclick\", operation(cm, function(e) {\n        if (signalDOMEvent(cm, e)) return;\n        var pos = posFromMouse(cm, e);\n        if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;\n        e_preventDefault(e);\n        var word = findWordAt(getLine(cm.doc, pos.line).text, pos);\n        extendSelection(cm.doc, word.from, word.to);\n      }));\n    else\n      on(d.scroller, \"dblclick\", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });\n    on(d.lineSpace, \"selectstart\", function(e) {\n      if (!eventInWidget(d, e)) e_preventDefault(e);\n    });\n    // Gecko browsers fire contextmenu *after* opening the menu, at\n    // which point we can't mess with it anymore. Context menu is\n    // handled in onMouseDown for Gecko.\n    if (!captureMiddleClick) on(d.scroller, \"contextmenu\", function(e) {onContextMenu(cm, e);});\n\n    on(d.scroller, \"scroll\", function() {\n      if (d.scroller.clientHeight) {\n        setScrollTop(cm, d.scroller.scrollTop);\n        setScrollLeft(cm, d.scroller.scrollLeft, true);\n        signal(cm, \"scroll\", cm);\n      }\n    });\n    on(d.scrollbarV, \"scroll\", function() {\n      if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);\n    });\n    on(d.scrollbarH, \"scroll\", function() {\n      if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);\n    });\n\n    on(d.scroller, \"mousewheel\", function(e){onScrollWheel(cm, e);});\n    on(d.scroller, \"DOMMouseScroll\", function(e){onScrollWheel(cm, e);});\n\n    function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }\n    on(d.scrollbarH, \"mousedown\", reFocus);\n    on(d.scrollbarV, \"mousedown\", reFocus);\n    // Prevent wrapper from ever scrolling\n    on(d.wrapper, \"scroll\", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });\n\n    var resizeTimer;\n    function onResize() {\n      if (resizeTimer == null) resizeTimer = setTimeout(function() {\n        resizeTimer = null;\n        // Might be a text scaling operation, clear size caches.\n        d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = knownScrollbarWidth = null;\n        clearCaches(cm);\n        runInOp(cm, bind(regChange, cm));\n      }, 100);\n    }\n    on(window, \"resize\", onResize);\n    // Above handler holds on to the editor and its data structures.\n    // Here we poll to unregister it when the editor is no longer in\n    // the document, so that it can be garbage-collected.\n    function unregister() {\n      for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}\n      if (p) setTimeout(unregister, 5000);\n      else off(window, \"resize\", onResize);\n    }\n    setTimeout(unregister, 5000);\n\n    on(d.input, \"keyup\", operation(cm, onKeyUp));\n    on(d.input, \"input\", function() {\n      if (ie && !ie_lt9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;\n      fastPoll(cm);\n    });\n    on(d.input, \"keydown\", operation(cm, onKeyDown));\n    on(d.input, \"keypress\", operation(cm, onKeyPress));\n    on(d.input, \"focus\", bind(onFocus, cm));\n    on(d.input, \"blur\", bind(onBlur, cm));\n\n    function drag_(e) {\n      if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;\n      e_stop(e);\n    }\n    if (cm.options.dragDrop) {\n      on(d.scroller, \"dragstart\", function(e){onDragStart(cm, e);});\n      on(d.scroller, \"dragenter\", drag_);\n      on(d.scroller, \"dragover\", drag_);\n      on(d.scroller, \"drop\", operation(cm, onDrop));\n    }\n    on(d.scroller, \"paste\", function(e) {\n      if (eventInWidget(d, e)) return;\n      focusInput(cm);\n      fastPoll(cm);\n    });\n    on(d.input, \"paste\", function() {\n      // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206\n      // Add a char to the end of textarea before paste occur so that\n      // selection doesn't span to the end of textarea.\n      if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {\n        var start = d.input.selectionStart, end = d.input.selectionEnd;\n        d.input.value += \"$\";\n        d.input.selectionStart = start;\n        d.input.selectionEnd = end;\n        cm.state.fakedLastChar = true;\n      }\n      cm.state.pasteIncoming = true;\n      fastPoll(cm);\n    });\n\n    function prepareCopy(e) {\n      if (d.inaccurateSelection) {\n        d.prevInput = \"\";\n        d.inaccurateSelection = false;\n        d.input.value = cm.getSelection();\n        selectInput(d.input);\n      }\n      if (e.type == \"cut\") cm.state.cutIncoming = true;\n    }\n    on(d.input, \"cut\", prepareCopy);\n    on(d.input, \"copy\", prepareCopy);\n\n    // Needed to handle Tab key in KHTML\n    if (khtml) on(d.sizer, \"mouseup\", function() {\n      if (document.activeElement == d.input) d.input.blur();\n      focusInput(cm);\n    });\n  }\n\n  function eventInWidget(display, e) {\n    for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {\n      if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;\n    }\n  }\n\n  function posFromMouse(cm, e, liberal) {\n    var display = cm.display;\n    if (!liberal) {\n      var target = e_target(e);\n      if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||\n          target == display.scrollbarV || target == display.scrollbarV.firstChild ||\n          target == display.scrollbarFiller || target == display.gutterFiller) return null;\n    }\n    var x, y, space = getRect(display.lineSpace);\n    // Fails unpredictably on IE[67] when mouse is dragged around quickly.\n    try { x = e.clientX; y = e.clientY; } catch (e) { return null; }\n    return coordsChar(cm, x - space.left, y - space.top);\n  }\n\n  var lastClick, lastDoubleClick;\n  function onMouseDown(e) {\n    if (signalDOMEvent(this, e)) return;\n    var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;\n    sel.shift = e.shiftKey;\n\n    if (eventInWidget(display, e)) {\n      if (!webkit) {\n        display.scroller.draggable = false;\n        setTimeout(function(){display.scroller.draggable = true;}, 100);\n      }\n      return;\n    }\n    if (clickInGutter(cm, e)) return;\n    var start = posFromMouse(cm, e);\n    window.focus();\n\n    switch (e_button(e)) {\n    case 3:\n      if (captureMiddleClick) onContextMenu.call(cm, cm, e);\n      return;\n    case 2:\n      if (webkit) cm.state.lastMiddleDown = +new Date;\n      if (start) extendSelection(cm.doc, start);\n      setTimeout(bind(focusInput, cm), 20);\n      e_preventDefault(e);\n      return;\n    }\n    // For button 1, if it was clicked inside the editor\n    // (posFromMouse returning non-null), we have to adjust the\n    // selection.\n    if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}\n\n    setTimeout(bind(ensureFocus, cm), 0);\n\n    var now = +new Date, type = \"single\";\n    if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {\n      type = \"triple\";\n      e_preventDefault(e);\n      setTimeout(bind(focusInput, cm), 20);\n      selectLine(cm, start.line);\n    } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {\n      type = \"double\";\n      lastDoubleClick = {time: now, pos: start};\n      e_preventDefault(e);\n      var word = findWordAt(getLine(doc, start.line).text, start);\n      extendSelection(cm.doc, word.from, word.to);\n    } else { lastClick = {time: now, pos: start}; }\n\n    var last = start;\n    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&\n        !posLess(start, sel.from) && !posLess(sel.to, start) && type == \"single\") {\n      var dragEnd = operation(cm, function(e2) {\n        if (webkit) display.scroller.draggable = false;\n        cm.state.draggingText = false;\n        off(document, \"mouseup\", dragEnd);\n        off(display.scroller, \"drop\", dragEnd);\n        if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {\n          e_preventDefault(e2);\n          extendSelection(cm.doc, start);\n          focusInput(cm);\n          // Work around unexplainable focus problem in IE9 (#2127)\n          if (old_ie && !ie_lt9)\n            setTimeout(function() {document.body.focus(); focusInput(cm);}, 20);\n        }\n      });\n      // Let the drag handler handle this.\n      if (webkit) display.scroller.draggable = true;\n      cm.state.draggingText = dragEnd;\n      // IE's approach to draggable\n      if (display.scroller.dragDrop) display.scroller.dragDrop();\n      on(document, \"mouseup\", dragEnd);\n      on(display.scroller, \"drop\", dragEnd);\n      return;\n    }\n    e_preventDefault(e);\n    if (type == \"single\") extendSelection(cm.doc, clipPos(doc, start));\n\n    var startstart = sel.from, startend = sel.to, lastPos = start;\n\n    function doSelect(cur) {\n      if (posEq(lastPos, cur)) return;\n      lastPos = cur;\n\n      if (type == \"single\") {\n        extendSelection(cm.doc, clipPos(doc, start), cur);\n        return;\n      }\n\n      startstart = clipPos(doc, startstart);\n      startend = clipPos(doc, startend);\n      if (type == \"double\") {\n        var word = findWordAt(getLine(doc, cur.line).text, cur);\n        if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);\n        else extendSelection(cm.doc, startstart, word.to);\n      } else if (type == \"triple\") {\n        if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));\n        else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));\n      }\n    }\n\n    var editorSize = getRect(display.wrapper);\n    // Used to ensure timeout re-tries don't fire when another extend\n    // happened in the meantime (clearTimeout isn't reliable -- at\n    // least on Chrome, the timeouts still happen even when cleared,\n    // if the clear happens after their scheduled firing time).\n    var counter = 0;\n\n    function extend(e) {\n      var curCount = ++counter;\n      var cur = posFromMouse(cm, e, true);\n      if (!cur) return;\n      if (!posEq(cur, last)) {\n        ensureFocus(cm);\n        last = cur;\n        doSelect(cur);\n        var visible = visibleLines(display, doc);\n        if (cur.line >= visible.to || cur.line < visible.from)\n          setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);\n      } else {\n        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;\n        if (outside) setTimeout(operation(cm, function() {\n          if (counter != curCount) return;\n          display.scroller.scrollTop += outside;\n          extend(e);\n        }), 50);\n      }\n    }\n\n    function done(e) {\n      counter = Infinity;\n      e_preventDefault(e);\n      focusInput(cm);\n      off(document, \"mousemove\", move);\n      off(document, \"mouseup\", up);\n    }\n\n    var move = operation(cm, function(e) {\n      if ((ie && !ie_lt10) ?  !e.buttons : !e_button(e)) done(e);\n      else extend(e);\n    });\n    var up = operation(cm, done);\n    on(document, \"mousemove\", move);\n    on(document, \"mouseup\", up);\n  }\n\n  function gutterEvent(cm, e, type, prevent, signalfn) {\n    try { var mX = e.clientX, mY = e.clientY; }\n    catch(e) { return false; }\n    if (mX >= Math.floor(getRect(cm.display.gutters).right)) return false;\n    if (prevent) e_preventDefault(e);\n\n    var display = cm.display;\n    var lineBox = getRect(display.lineDiv);\n\n    if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);\n    mY -= lineBox.top - display.viewOffset;\n\n    for (var i = 0; i < cm.options.gutters.length; ++i) {\n      var g = display.gutters.childNodes[i];\n      if (g && getRect(g).right >= mX) {\n        var line = lineAtHeight(cm.doc, mY);\n        var gutter = cm.options.gutters[i];\n        signalfn(cm, type, cm, line, gutter, e);\n        return e_defaultPrevented(e);\n      }\n    }\n  }\n\n  function contextMenuInGutter(cm, e) {\n    if (!hasHandler(cm, \"gutterContextMenu\")) return false;\n    return gutterEvent(cm, e, \"gutterContextMenu\", false, signal);\n  }\n\n  function clickInGutter(cm, e) {\n    return gutterEvent(cm, e, \"gutterClick\", true, signalLater);\n  }\n\n  // Kludge to work around strange IE behavior where it'll sometimes\n  // re-fire a series of drag-related events right after the drop (#1551)\n  var lastDrop = 0;\n\n  function onDrop(e) {\n    var cm = this;\n    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))\n      return;\n    e_preventDefault(e);\n    if (ie) lastDrop = +new Date;\n    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;\n    if (!pos || isReadOnly(cm)) return;\n    if (files && files.length && window.FileReader && window.File) {\n      var n = files.length, text = Array(n), read = 0;\n      var loadFile = function(file, i) {\n        var reader = new FileReader;\n        reader.onload = function() {\n          text[i] = reader.result;\n          if (++read == n) {\n            pos = clipPos(cm.doc, pos);\n            makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join(\"\\n\")), origin: \"paste\"}, \"around\");\n          }\n        };\n        reader.readAsText(file);\n      };\n      for (var i = 0; i < n; ++i) loadFile(files[i], i);\n    } else {\n      // Don't do a replace if the drop happened inside of the selected text.\n      if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {\n        cm.state.draggingText(e);\n        // Ensure the editor is re-focused\n        setTimeout(bind(focusInput, cm), 20);\n        return;\n      }\n      try {\n        var text = e.dataTransfer.getData(\"Text\");\n        if (text) {\n          var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;\n          setSelection(cm.doc, pos, pos);\n          if (cm.state.draggingText) replaceRange(cm.doc, \"\", curFrom, curTo, \"paste\");\n          cm.replaceSelection(text, null, \"paste\");\n          focusInput(cm);\n        }\n      }\n      catch(e){}\n    }\n  }\n\n  function onDragStart(cm, e) {\n    if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }\n    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;\n\n    var txt = cm.getSelection();\n    e.dataTransfer.setData(\"Text\", txt);\n\n    // Use dummy image instead of default browsers image.\n    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.\n    if (e.dataTransfer.setDragImage && !safari) {\n      var img = elt(\"img\", null, null, \"position: fixed; left: 0; top: 0;\");\n      img.src = \"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\";\n      if (opera) {\n        img.width = img.height = 1;\n        cm.display.wrapper.appendChild(img);\n        // Force a relayout, or Opera won't use our image for some obscure reason\n        img._top = img.offsetTop;\n      }\n      e.dataTransfer.setDragImage(img, 0, 0);\n      if (opera) img.parentNode.removeChild(img);\n    }\n  }\n\n  function setScrollTop(cm, val) {\n    if (Math.abs(cm.doc.scrollTop - val) < 2) return;\n    cm.doc.scrollTop = val;\n    if (!gecko) updateDisplay(cm, [], val);\n    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;\n    if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;\n    if (gecko) updateDisplay(cm, []);\n    startWorker(cm, 100);\n  }\n  function setScrollLeft(cm, val, isScroller) {\n    if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;\n    val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);\n    cm.doc.scrollLeft = val;\n    alignHorizontally(cm);\n    if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;\n    if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;\n  }\n\n  // Since the delta values reported on mouse wheel events are\n  // unstandardized between browsers and even browser versions, and\n  // generally horribly unpredictable, this code starts by measuring\n  // the scroll effect that the first few mouse wheel events have,\n  // and, from that, detects the way it can convert deltas to pixel\n  // offsets afterwards.\n  //\n  // The reason we want to know the amount a wheel event will scroll\n  // is that it gives us a chance to update the display before the\n  // actual scrolling happens, reducing flickering.\n\n  var wheelSamples = 0, wheelPixelsPerUnit = null;\n  // Fill in a browser-detected starting value on browsers where we\n  // know one. These don't have to be accurate -- the result of them\n  // being wrong would just be a slight flicker on the first wheel\n  // scroll (if it is large enough).\n  if (ie) wheelPixelsPerUnit = -.53;\n  else if (gecko) wheelPixelsPerUnit = 15;\n  else if (chrome) wheelPixelsPerUnit = -.7;\n  else if (safari) wheelPixelsPerUnit = -1/3;\n\n  function onScrollWheel(cm, e) {\n    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;\n    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;\n    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;\n    else if (dy == null) dy = e.wheelDelta;\n\n    var display = cm.display, scroll = display.scroller;\n    // Quit if there's nothing to scroll here\n    if (!(dx && scroll.scrollWidth > scroll.clientWidth ||\n          dy && scroll.scrollHeight > scroll.clientHeight)) return;\n\n    // Webkit browsers on OS X abort momentum scrolls when the target\n    // of the scroll event is removed from the scrollable element.\n    // This hack (see related code in patchDisplay) makes sure the\n    // element is kept around.\n    if (dy && mac && webkit) {\n      for (var cur = e.target; cur != scroll; cur = cur.parentNode) {\n        if (cur.lineObj) {\n          cm.display.currentWheelTarget = cur;\n          break;\n        }\n      }\n    }\n\n    // On some browsers, horizontal scrolling will cause redraws to\n    // happen before the gutter has been realigned, causing it to\n    // wriggle around in a most unseemly way. When we have an\n    // estimated pixels/delta value, we just handle horizontal\n    // scrolling entirely here. It'll be slightly off from native, but\n    // better than glitching out.\n    if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {\n      if (dy)\n        setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));\n      setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));\n      e_preventDefault(e);\n      display.wheelStartX = null; // Abort measurement, if in progress\n      return;\n    }\n\n    if (dy && wheelPixelsPerUnit != null) {\n      var pixels = dy * wheelPixelsPerUnit;\n      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;\n      if (pixels < 0) top = Math.max(0, top + pixels - 50);\n      else bot = Math.min(cm.doc.height, bot + pixels + 50);\n      updateDisplay(cm, [], {top: top, bottom: bot});\n    }\n\n    if (wheelSamples < 20) {\n      if (display.wheelStartX == null) {\n        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;\n        display.wheelDX = dx; display.wheelDY = dy;\n        setTimeout(function() {\n          if (display.wheelStartX == null) return;\n          var movedX = scroll.scrollLeft - display.wheelStartX;\n          var movedY = scroll.scrollTop - display.wheelStartY;\n          var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||\n            (movedX && display.wheelDX && movedX / display.wheelDX);\n          display.wheelStartX = display.wheelStartY = null;\n          if (!sample) return;\n          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);\n          ++wheelSamples;\n        }, 200);\n      } else {\n        display.wheelDX += dx; display.wheelDY += dy;\n      }\n    }\n  }\n\n  function doHandleBinding(cm, bound, dropShift) {\n    if (typeof bound == \"string\") {\n      bound = commands[bound];\n      if (!bound) return false;\n    }\n    // Ensure previous input has been read, so that the handler sees a\n    // consistent view of the document\n    if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;\n    var doc = cm.doc, prevShift = doc.sel.shift, done = false;\n    try {\n      if (isReadOnly(cm)) cm.state.suppressEdits = true;\n      if (dropShift) doc.sel.shift = false;\n      done = bound(cm) != Pass;\n    } finally {\n      doc.sel.shift = prevShift;\n      cm.state.suppressEdits = false;\n    }\n    return done;\n  }\n\n  function allKeyMaps(cm) {\n    var maps = cm.state.keyMaps.slice(0);\n    if (cm.options.extraKeys) maps.push(cm.options.extraKeys);\n    maps.push(cm.options.keyMap);\n    return maps;\n  }\n\n  var maybeTransition;\n  function handleKeyBinding(cm, e) {\n    // Handle auto keymap transitions\n    var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;\n    clearTimeout(maybeTransition);\n    if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {\n      if (getKeyMap(cm.options.keyMap) == startMap) {\n        cm.options.keyMap = (next.call ? next.call(null, cm) : next);\n        keyMapChanged(cm);\n      }\n    }, 50);\n\n    var name = keyName(e, true), handled = false;\n    if (!name) return false;\n    var keymaps = allKeyMaps(cm);\n\n    if (e.shiftKey) {\n      // First try to resolve full name (including 'Shift-'). Failing\n      // that, see if there is a cursor-motion command (starting with\n      // 'go') bound to the keyname without 'Shift-'.\n      handled = lookupKey(\"Shift-\" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})\n             || lookupKey(name, keymaps, function(b) {\n                  if (typeof b == \"string\" ? /^go[A-Z]/.test(b) : b.motion)\n                    return doHandleBinding(cm, b);\n                });\n    } else {\n      handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });\n    }\n\n    if (handled) {\n      e_preventDefault(e);\n      restartBlink(cm);\n      if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }\n      signalLater(cm, \"keyHandled\", cm, name, e);\n    }\n    return handled;\n  }\n\n  function handleCharBinding(cm, e, ch) {\n    var handled = lookupKey(\"'\" + ch + \"'\", allKeyMaps(cm),\n                            function(b) { return doHandleBinding(cm, b, true); });\n    if (handled) {\n      e_preventDefault(e);\n      restartBlink(cm);\n      signalLater(cm, \"keyHandled\", cm, \"'\" + ch + \"'\", e);\n    }\n    return handled;\n  }\n\n  function onKeyUp(e) {\n    var cm = this;\n    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;\n    if (e.keyCode == 16) cm.doc.sel.shift = false;\n  }\n\n  var lastStoppedKey = null;\n  function onKeyDown(e) {\n    var cm = this;\n    ensureFocus(cm);\n    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;\n    if (old_ie && e.keyCode == 27) e.returnValue = false;\n    var code = e.keyCode;\n    // IE does strange things with escape.\n    cm.doc.sel.shift = code == 16 || e.shiftKey;\n    // First give onKeyEvent option a chance to handle this.\n    var handled = handleKeyBinding(cm, e);\n    if (opera) {\n      lastStoppedKey = handled ? code : null;\n      // Opera has no cut event... we try to at least catch the key combo\n      if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))\n        cm.replaceSelection(\"\");\n    }\n  }\n\n  function onKeyPress(e) {\n    var cm = this;\n    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;\n    var keyCode = e.keyCode, charCode = e.charCode;\n    if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}\n    if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;\n    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);\n    if (handleCharBinding(cm, e, ch)) return;\n    if (ie && !ie_lt9) cm.display.inputHasSelection = null;\n    fastPoll(cm);\n  }\n\n  function onFocus(cm) {\n    if (cm.options.readOnly == \"nocursor\") return;\n    if (!cm.state.focused) {\n      signal(cm, \"focus\", cm);\n      cm.state.focused = true;\n      if (cm.display.wrapper.className.search(/\\bCodeMirror-focused\\b/) == -1)\n        cm.display.wrapper.className += \" CodeMirror-focused\";\n      if (!cm.curOp) {\n        resetInput(cm, true);\n        if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730\n      }\n    }\n    slowPoll(cm);\n    restartBlink(cm);\n  }\n  function onBlur(cm) {\n    if (cm.state.focused) {\n      signal(cm, \"blur\", cm);\n      cm.state.focused = false;\n      cm.display.wrapper.className = cm.display.wrapper.className.replace(\" CodeMirror-focused\", \"\");\n    }\n    clearInterval(cm.display.blinker);\n    setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);\n  }\n\n  var detectingSelectAll;\n  function onContextMenu(cm, e) {\n    if (signalDOMEvent(cm, e, \"contextmenu\")) return;\n    var display = cm.display, sel = cm.doc.sel;\n    if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;\n\n    var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;\n    if (!pos || opera) return; // Opera is difficult.\n\n    // Reset the current text selection only if the click is done outside of the selection\n    // and 'resetSelectionOnContextMenu' option is true.\n    var reset = cm.options.resetSelectionOnContextMenu;\n    if (reset && (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)))\n      operation(cm, setSelection)(cm.doc, pos, pos);\n\n    var oldCSS = display.input.style.cssText;\n    display.inputDiv.style.position = \"absolute\";\n    display.input.style.cssText = \"position: fixed; width: 30px; height: 30px; top: \" + (e.clientY - 5) +\n      \"px; left: \" + (e.clientX - 5) + \"px; z-index: 1000; background: transparent; outline: none;\" +\n      \"border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);\";\n    focusInput(cm);\n    resetInput(cm, true);\n    // Adds \"Select all\" to context menu in FF\n    if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = \" \";\n\n    function prepareSelectAllHack() {\n      if (display.input.selectionStart != null) {\n        var extval = display.input.value = \"\\u200b\" + (posEq(sel.from, sel.to) ? \"\" : display.input.value);\n        display.prevInput = \"\\u200b\";\n        display.input.selectionStart = 1; display.input.selectionEnd = extval.length;\n      }\n    }\n    function rehide() {\n      display.inputDiv.style.position = \"relative\";\n      display.input.style.cssText = oldCSS;\n      if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;\n      slowPoll(cm);\n\n      // Try to detect the user choosing select-all\n      if (display.input.selectionStart != null) {\n        if (!ie || ie_lt9) prepareSelectAllHack();\n        clearTimeout(detectingSelectAll);\n        var i = 0, poll = function(){\n          if (display.prevInput == \"\\u200b\" && display.input.selectionStart == 0)\n            operation(cm, commands.selectAll)(cm);\n          else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);\n          else resetInput(cm);\n        };\n        detectingSelectAll = setTimeout(poll, 200);\n      }\n    }\n\n    if (ie && !ie_lt9) prepareSelectAllHack();\n    if (captureMiddleClick) {\n      e_stop(e);\n      var mouseup = function() {\n        off(window, \"mouseup\", mouseup);\n        setTimeout(rehide, 20);\n      };\n      on(window, \"mouseup\", mouseup);\n    } else {\n      setTimeout(rehide, 50);\n    }\n  }\n\n  // UPDATING\n\n  var changeEnd = CodeMirror.changeEnd = function(change) {\n    if (!change.text) return change.to;\n    return Pos(change.from.line + change.text.length - 1,\n               lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));\n  };\n\n  // Make sure a position will be valid after the given change.\n  function clipPostChange(doc, change, pos) {\n    if (!posLess(change.from, pos)) return clipPos(doc, pos);\n    var diff = (change.text.length - 1) - (change.to.line - change.from.line);\n    if (pos.line > change.to.line + diff) {\n      var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;\n      if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);\n      return clipToLen(pos, getLine(doc, preLine).text.length);\n    }\n    if (pos.line == change.to.line + diff)\n      return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +\n                       getLine(doc, change.to.line).text.length - change.to.ch);\n    var inside = pos.line - change.from.line;\n    return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));\n  }\n\n  // Hint can be null|\"end\"|\"start\"|\"around\"|{anchor,head}\n  function computeSelAfterChange(doc, change, hint) {\n    if (hint && typeof hint == \"object\") // Assumed to be {anchor, head} object\n      return {anchor: clipPostChange(doc, change, hint.anchor),\n              head: clipPostChange(doc, change, hint.head)};\n\n    if (hint == \"start\") return {anchor: change.from, head: change.from};\n\n    var end = changeEnd(change);\n    if (hint == \"around\") return {anchor: change.from, head: end};\n    if (hint == \"end\") return {anchor: end, head: end};\n\n    // hint is null, leave the selection alone as much as possible\n    var adjustPos = function(pos) {\n      if (posLess(pos, change.from)) return pos;\n      if (!posLess(change.to, pos)) return end;\n\n      var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;\n      if (pos.line == change.to.line) ch += end.ch - change.to.ch;\n      return Pos(line, ch);\n    };\n    return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};\n  }\n\n  function filterChange(doc, change, update) {\n    var obj = {\n      canceled: false,\n      from: change.from,\n      to: change.to,\n      text: change.text,\n      origin: change.origin,\n      cancel: function() { this.canceled = true; }\n    };\n    if (update) obj.update = function(from, to, text, origin) {\n      if (from) this.from = clipPos(doc, from);\n      if (to) this.to = clipPos(doc, to);\n      if (text) this.text = text;\n      if (origin !== undefined) this.origin = origin;\n    };\n    signal(doc, \"beforeChange\", doc, obj);\n    if (doc.cm) signal(doc.cm, \"beforeChange\", doc.cm, obj);\n\n    if (obj.canceled) return null;\n    return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};\n  }\n\n  // Replace the range from from to to by the strings in replacement.\n  // change is a {from, to, text [, origin]} object\n  function makeChange(doc, change, selUpdate, ignoreReadOnly) {\n    if (doc.cm) {\n      if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);\n      if (doc.cm.state.suppressEdits) return;\n    }\n\n    if (hasHandler(doc, \"beforeChange\") || doc.cm && hasHandler(doc.cm, \"beforeChange\")) {\n      change = filterChange(doc, change, true);\n      if (!change) return;\n    }\n\n    // Possibly split or suppress the update based on the presence\n    // of read-only spans in its range.\n    var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);\n    if (split) {\n      for (var i = split.length - 1; i >= 1; --i)\n        makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [\"\"]});\n      if (split.length)\n        makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);\n    } else {\n      makeChangeNoReadonly(doc, change, selUpdate);\n    }\n  }\n\n  function makeChangeNoReadonly(doc, change, selUpdate) {\n    if (change.text.length == 1 && change.text[0] == \"\" && posEq(change.from, change.to)) return;\n    var selAfter = computeSelAfterChange(doc, change, selUpdate);\n    addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);\n\n    makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));\n    var rebased = [];\n\n    linkedDocs(doc, function(doc, sharedHist) {\n      if (!sharedHist && indexOf(rebased, doc.history) == -1) {\n        rebaseHist(doc.history, change);\n        rebased.push(doc.history);\n      }\n      makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));\n    });\n  }\n\n  function makeChangeFromHistory(doc, type) {\n    if (doc.cm && doc.cm.state.suppressEdits) return;\n\n    var hist = doc.history;\n    var event = (type == \"undo\" ? hist.done : hist.undone).pop();\n    if (!event) return;\n\n    var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,\n                anchorAfter: event.anchorBefore, headAfter: event.headBefore,\n                generation: hist.generation};\n    (type == \"undo\" ? hist.undone : hist.done).push(anti);\n    hist.generation = event.generation || ++hist.maxGeneration;\n\n    var filter = hasHandler(doc, \"beforeChange\") || doc.cm && hasHandler(doc.cm, \"beforeChange\");\n\n    for (var i = event.changes.length - 1; i >= 0; --i) {\n      var change = event.changes[i];\n      change.origin = type;\n      if (filter && !filterChange(doc, change, false)) {\n        (type == \"undo\" ? hist.done : hist.undone).length = 0;\n        return;\n      }\n\n      anti.changes.push(historyChangeFromChange(doc, change));\n\n      var after = i ? computeSelAfterChange(doc, change, null)\n                    : {anchor: event.anchorBefore, head: event.headBefore};\n      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));\n      var rebased = [];\n\n      linkedDocs(doc, function(doc, sharedHist) {\n        if (!sharedHist && indexOf(rebased, doc.history) == -1) {\n          rebaseHist(doc.history, change);\n          rebased.push(doc.history);\n        }\n        makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));\n      });\n    }\n  }\n\n  function shiftDoc(doc, distance) {\n    function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}\n    doc.first += distance;\n    if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);\n    doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);\n    doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);\n  }\n\n  function makeChangeSingleDoc(doc, change, selAfter, spans) {\n    if (doc.cm && !doc.cm.curOp)\n      return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);\n\n    if (change.to.line < doc.first) {\n      shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));\n      return;\n    }\n    if (change.from.line > doc.lastLine()) return;\n\n    // Clip the change to the size of this doc\n    if (change.from.line < doc.first) {\n      var shift = change.text.length - 1 - (doc.first - change.from.line);\n      shiftDoc(doc, shift);\n      change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),\n                text: [lst(change.text)], origin: change.origin};\n    }\n    var last = doc.lastLine();\n    if (change.to.line > last) {\n      change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),\n                text: [change.text[0]], origin: change.origin};\n    }\n\n    change.removed = getBetween(doc, change.from, change.to);\n\n    if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);\n    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);\n    else updateDoc(doc, change, spans, selAfter);\n  }\n\n  function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {\n    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;\n\n    var recomputeMaxLength = false, checkWidthStart = from.line;\n    if (!cm.options.lineWrapping) {\n      checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));\n      doc.iter(checkWidthStart, to.line + 1, function(line) {\n        if (line == display.maxLine) {\n          recomputeMaxLength = true;\n          return true;\n        }\n      });\n    }\n\n    if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))\n      cm.curOp.cursorActivity = true;\n\n    updateDoc(doc, change, spans, selAfter, estimateHeight(cm));\n\n    if (!cm.options.lineWrapping) {\n      doc.iter(checkWidthStart, from.line + change.text.length, function(line) {\n        var len = lineLength(doc, line);\n        if (len > display.maxLineLength) {\n          display.maxLine = line;\n          display.maxLineLength = len;\n          display.maxLineChanged = true;\n          recomputeMaxLength = false;\n        }\n      });\n      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;\n    }\n\n    // Adjust frontier, schedule worker\n    doc.frontier = Math.min(doc.frontier, from.line);\n    startWorker(cm, 400);\n\n    var lendiff = change.text.length - (to.line - from.line) - 1;\n    // Remember that these lines changed, for updating the display\n    regChange(cm, from.line, to.line + 1, lendiff);\n\n    if (hasHandler(cm, \"change\")) {\n      var changeObj = {from: from, to: to,\n                       text: change.text,\n                       removed: change.removed,\n                       origin: change.origin};\n      if (cm.curOp.textChanged) {\n        for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}\n        cur.next = changeObj;\n      } else cm.curOp.textChanged = changeObj;\n    }\n  }\n\n  function replaceRange(doc, code, from, to, origin) {\n    if (!to) to = from;\n    if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }\n    if (typeof code == \"string\") code = splitLines(code);\n    makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);\n  }\n\n  // POSITION OBJECT\n\n  function Pos(line, ch) {\n    if (!(this instanceof Pos)) return new Pos(line, ch);\n    this.line = line; this.ch = ch;\n  }\n  CodeMirror.Pos = Pos;\n\n  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}\n  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}\n  function cmp(a, b) {return a.line - b.line || a.ch - b.ch;}\n  function copyPos(x) {return Pos(x.line, x.ch);}\n\n  // SELECTION\n\n  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}\n  function clipPos(doc, pos) {\n    if (pos.line < doc.first) return Pos(doc.first, 0);\n    var last = doc.first + doc.size - 1;\n    if (pos.line > last) return Pos(last, getLine(doc, last).text.length);\n    return clipToLen(pos, getLine(doc, pos.line).text.length);\n  }\n  function clipToLen(pos, linelen) {\n    var ch = pos.ch;\n    if (ch == null || ch > linelen) return Pos(pos.line, linelen);\n    else if (ch < 0) return Pos(pos.line, 0);\n    else return pos;\n  }\n  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}\n\n  // If shift is held, this will move the selection anchor. Otherwise,\n  // it'll set the whole selection.\n  function extendSelection(doc, pos, other, bias) {\n    if (doc.sel.shift || doc.sel.extend) {\n      var anchor = doc.sel.anchor;\n      if (other) {\n        var posBefore = posLess(pos, anchor);\n        if (posBefore != posLess(other, anchor)) {\n          anchor = pos;\n          pos = other;\n        } else if (posBefore != posLess(pos, other)) {\n          pos = other;\n        }\n      }\n      setSelection(doc, anchor, pos, bias);\n    } else {\n      setSelection(doc, pos, other || pos, bias);\n    }\n    if (doc.cm) doc.cm.curOp.userSelChange = true;\n  }\n\n  function filterSelectionChange(doc, anchor, head) {\n    var obj = {anchor: anchor, head: head};\n    signal(doc, \"beforeSelectionChange\", doc, obj);\n    if (doc.cm) signal(doc.cm, \"beforeSelectionChange\", doc.cm, obj);\n    obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);\n    return obj;\n  }\n\n  // Update the selection. Last two args are only used by\n  // updateDoc, since they have to be expressed in the line\n  // numbers before the update.\n  function setSelection(doc, anchor, head, bias, checkAtomic) {\n    if (!checkAtomic && hasHandler(doc, \"beforeSelectionChange\") || doc.cm && hasHandler(doc.cm, \"beforeSelectionChange\")) {\n      var filtered = filterSelectionChange(doc, anchor, head);\n      head = filtered.head;\n      anchor = filtered.anchor;\n    }\n\n    var sel = doc.sel;\n    sel.goalColumn = null;\n    if (bias == null) bias = posLess(head, sel.head) ? -1 : 1;\n    // Skip over atomic spans.\n    if (checkAtomic || !posEq(anchor, sel.anchor))\n      anchor = skipAtomic(doc, anchor, bias, checkAtomic != \"push\");\n    if (checkAtomic || !posEq(head, sel.head))\n      head = skipAtomic(doc, head, bias, checkAtomic != \"push\");\n\n    if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;\n\n    sel.anchor = anchor; sel.head = head;\n    var inv = posLess(head, anchor);\n    sel.from = inv ? head : anchor;\n    sel.to = inv ? anchor : head;\n\n    if (doc.cm)\n      doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =\n        doc.cm.curOp.cursorActivity = true;\n\n    signalLater(doc, \"cursorActivity\", doc);\n  }\n\n  function reCheckSelection(cm) {\n    setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, \"push\");\n  }\n\n  function skipAtomic(doc, pos, bias, mayClear) {\n    var flipped = false, curPos = pos;\n    var dir = bias || 1;\n    doc.cantEdit = false;\n    search: for (;;) {\n      var line = getLine(doc, curPos.line);\n      if (line.markedSpans) {\n        for (var i = 0; i < line.markedSpans.length; ++i) {\n          var sp = line.markedSpans[i], m = sp.marker;\n          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&\n              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {\n            if (mayClear) {\n              signal(m, \"beforeCursorEnter\");\n              if (m.explicitlyCleared) {\n                if (!line.markedSpans) break;\n                else {--i; continue;}\n              }\n            }\n            if (!m.atomic) continue;\n            var newPos = m.find()[dir < 0 ? \"from\" : \"to\"];\n            if (posEq(newPos, curPos)) {\n              newPos.ch += dir;\n              if (newPos.ch < 0) {\n                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));\n                else newPos = null;\n              } else if (newPos.ch > line.text.length) {\n                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);\n                else newPos = null;\n              }\n              if (!newPos) {\n                if (flipped) {\n                  // Driven in a corner -- no valid cursor position found at all\n                  // -- try again *with* clearing, if we didn't already\n                  if (!mayClear) return skipAtomic(doc, pos, bias, true);\n                  // Otherwise, turn off editing until further notice, and return the start of the doc\n                  doc.cantEdit = true;\n                  return Pos(doc.first, 0);\n                }\n                flipped = true; newPos = pos; dir = -dir;\n              }\n            }\n            curPos = newPos;\n            continue search;\n          }\n        }\n      }\n      return curPos;\n    }\n  }\n\n  // SCROLLING\n\n  function scrollCursorIntoView(cm) {\n    var coords = scrollPosIntoView(cm, cm.doc.sel.head, null, cm.options.cursorScrollMargin);\n    if (!cm.state.focused) return;\n    var display = cm.display, box = getRect(display.sizer), doScroll = null;\n    if (coords.top + box.top < 0) doScroll = true;\n    else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;\n    if (doScroll != null && !phantom) {\n      var scrollNode = elt(\"div\", \"\\u200b\", null, \"position: absolute; top: \" +\n                           (coords.top - display.viewOffset) + \"px; height: \" +\n                           (coords.bottom - coords.top + scrollerCutOff) + \"px; left: \" +\n                           coords.left + \"px; width: 2px;\");\n      cm.display.lineSpace.appendChild(scrollNode);\n      scrollNode.scrollIntoView(doScroll);\n      cm.display.lineSpace.removeChild(scrollNode);\n    }\n  }\n\n  function scrollPosIntoView(cm, pos, end, margin) {\n    if (margin == null) margin = 0;\n    for (;;) {\n      var changed = false, coords = cursorCoords(cm, pos);\n      var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);\n      var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),\n                                         Math.min(coords.top, endCoords.top) - margin,\n                                         Math.max(coords.left, endCoords.left),\n                                         Math.max(coords.bottom, endCoords.bottom) + margin);\n      var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;\n      if (scrollPos.scrollTop != null) {\n        setScrollTop(cm, scrollPos.scrollTop);\n        if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;\n      }\n      if (scrollPos.scrollLeft != null) {\n        setScrollLeft(cm, scrollPos.scrollLeft);\n        if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;\n      }\n      if (!changed) return coords;\n    }\n  }\n\n  function scrollIntoView(cm, x1, y1, x2, y2) {\n    var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);\n    if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);\n    if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);\n  }\n\n  function calculateScrollPos(cm, x1, y1, x2, y2) {\n    var display = cm.display, snapMargin = textHeight(cm.display);\n    if (y1 < 0) y1 = 0;\n    var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};\n    var docBottom = cm.doc.height + paddingVert(display);\n    var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;\n    if (y1 < screentop) {\n      result.scrollTop = atTop ? 0 : y1;\n    } else if (y2 > screentop + screen) {\n      var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);\n      if (newTop != screentop) result.scrollTop = newTop;\n    }\n\n    var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;\n    x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;\n    var gutterw = display.gutters.offsetWidth;\n    var atLeft = x1 < gutterw + 10;\n    if (x1 < screenleft + gutterw || atLeft) {\n      if (atLeft) x1 = 0;\n      result.scrollLeft = Math.max(0, x1 - 10 - gutterw);\n    } else if (x2 > screenw + screenleft - 3) {\n      result.scrollLeft = x2 + 10 - screenw;\n    }\n    return result;\n  }\n\n  function updateScrollPos(cm, left, top) {\n    cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,\n                                scrollTop: top == null ? cm.doc.scrollTop : top};\n  }\n\n  function addToScrollPos(cm, left, top) {\n    var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});\n    var scroll = cm.display.scroller;\n    pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));\n    pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));\n  }\n\n  // API UTILITIES\n\n  function indentLine(cm, n, how, aggressive) {\n    var doc = cm.doc, state;\n    if (how == null) how = \"add\";\n    if (how == \"smart\") {\n      if (!cm.doc.mode.indent) how = \"prev\";\n      else state = getStateBefore(cm, n);\n    }\n\n    var tabSize = cm.options.tabSize;\n    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);\n    if (line.stateAfter) line.stateAfter = null;\n    var curSpaceString = line.text.match(/^\\s*/)[0], indentation;\n    if (!aggressive && !/\\S/.test(line.text)) {\n      indentation = 0;\n      how = \"not\";\n    } else if (how == \"smart\") {\n      indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);\n      if (indentation == Pass) {\n        if (!aggressive) return;\n        how = \"prev\";\n      }\n    }\n    if (how == \"prev\") {\n      if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);\n      else indentation = 0;\n    } else if (how == \"add\") {\n      indentation = curSpace + cm.options.indentUnit;\n    } else if (how == \"subtract\") {\n      indentation = curSpace - cm.options.indentUnit;\n    } else if (typeof how == \"number\") {\n      indentation = curSpace + how;\n    }\n    indentation = Math.max(0, indentation);\n\n    var indentString = \"\", pos = 0;\n    if (cm.options.indentWithTabs)\n      for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += \"\\t\";}\n    if (pos < indentation) indentString += spaceStr(indentation - pos);\n\n    if (indentString != curSpaceString)\n      replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), \"+input\");\n    else if (doc.sel.head.line == n && doc.sel.head.ch < curSpaceString.length)\n      setSelection(doc, Pos(n, curSpaceString.length), Pos(n, curSpaceString.length), 1);\n    line.stateAfter = null;\n  }\n\n  function changeLine(cm, handle, op) {\n    var no = handle, line = handle, doc = cm.doc;\n    if (typeof handle == \"number\") line = getLine(doc, clipLine(doc, handle));\n    else no = lineNo(handle);\n    if (no == null) return null;\n    if (op(line, no)) regChange(cm, no, no + 1);\n    else return null;\n    return line;\n  }\n\n  function findPosH(doc, pos, dir, unit, visually) {\n    var line = pos.line, ch = pos.ch, origDir = dir;\n    var lineObj = getLine(doc, line);\n    var possible = true;\n    function findNextLine() {\n      var l = line + dir;\n      if (l < doc.first || l >= doc.first + doc.size) return (possible = false);\n      line = l;\n      return lineObj = getLine(doc, l);\n    }\n    function moveOnce(boundToLine) {\n      var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);\n      if (next == null) {\n        if (!boundToLine && findNextLine()) {\n          if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);\n          else ch = dir < 0 ? lineObj.text.length : 0;\n        } else return (possible = false);\n      } else ch = next;\n      return true;\n    }\n\n    if (unit == \"char\") moveOnce();\n    else if (unit == \"column\") moveOnce(true);\n    else if (unit == \"word\" || unit == \"group\") {\n      var sawType = null, group = unit == \"group\";\n      for (var first = true;; first = false) {\n        if (dir < 0 && !moveOnce(!first)) break;\n        var cur = lineObj.text.charAt(ch) || \"\\n\";\n        var type = isWordChar(cur) ? \"w\"\n          : group && cur == \"\\n\" ? \"n\"\n          : !group || /\\s/.test(cur) ? null\n          : \"p\";\n        if (group && !first && !type) type = \"s\";\n        if (sawType && sawType != type) {\n          if (dir < 0) {dir = 1; moveOnce();}\n          break;\n        }\n\n        if (type) sawType = type;\n        if (dir > 0 && !moveOnce(!first)) break;\n      }\n    }\n    var result = skipAtomic(doc, Pos(line, ch), origDir, true);\n    if (!possible) result.hitSide = true;\n    return result;\n  }\n\n  function findPosV(cm, pos, dir, unit) {\n    var doc = cm.doc, x = pos.left, y;\n    if (unit == \"page\") {\n      var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);\n      y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));\n    } else if (unit == \"line\") {\n      y = dir > 0 ? pos.bottom + 3 : pos.top - 3;\n    }\n    for (;;) {\n      var target = coordsChar(cm, x, y);\n      if (!target.outside) break;\n      if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }\n      y += dir * 5;\n    }\n    return target;\n  }\n\n  function findWordAt(line, pos) {\n    var start = pos.ch, end = pos.ch;\n    if (line) {\n      if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;\n      var startChar = line.charAt(start);\n      var check = isWordChar(startChar) ? isWordChar\n        : /\\s/.test(startChar) ? function(ch) {return /\\s/.test(ch);}\n        : function(ch) {return !/\\s/.test(ch) && !isWordChar(ch);};\n      while (start > 0 && check(line.charAt(start - 1))) --start;\n      while (end < line.length && check(line.charAt(end))) ++end;\n    }\n    return {from: Pos(pos.line, start), to: Pos(pos.line, end)};\n  }\n\n  function selectLine(cm, line) {\n    extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));\n  }\n\n  // PROTOTYPE\n\n  // The publicly visible API. Note that operation(null, f) means\n  // 'wrap f in an operation, performed on its `this` parameter'\n\n  CodeMirror.prototype = {\n    constructor: CodeMirror,\n    focus: function(){window.focus(); focusInput(this); fastPoll(this);},\n\n    setOption: function(option, value) {\n      var options = this.options, old = options[option];\n      if (options[option] == value && option != \"mode\") return;\n      options[option] = value;\n      if (optionHandlers.hasOwnProperty(option))\n        operation(this, optionHandlers[option])(this, value, old);\n    },\n\n    getOption: function(option) {return this.options[option];},\n    getDoc: function() {return this.doc;},\n\n    addKeyMap: function(map, bottom) {\n      this.state.keyMaps[bottom ? \"push\" : \"unshift\"](map);\n    },\n    removeKeyMap: function(map) {\n      var maps = this.state.keyMaps;\n      for (var i = 0; i < maps.length; ++i)\n        if (maps[i] == map || (typeof maps[i] != \"string\" && maps[i].name == map)) {\n          maps.splice(i, 1);\n          return true;\n        }\n    },\n\n    addOverlay: operation(null, function(spec, options) {\n      var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);\n      if (mode.startState) throw new Error(\"Overlays may not be stateful.\");\n      this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});\n      this.state.modeGen++;\n      regChange(this);\n    }),\n    removeOverlay: operation(null, function(spec) {\n      var overlays = this.state.overlays;\n      for (var i = 0; i < overlays.length; ++i) {\n        var cur = overlays[i].modeSpec;\n        if (cur == spec || typeof spec == \"string\" && cur.name == spec) {\n          overlays.splice(i, 1);\n          this.state.modeGen++;\n          regChange(this);\n          return;\n        }\n      }\n    }),\n\n    indentLine: operation(null, function(n, dir, aggressive) {\n      if (typeof dir != \"string\" && typeof dir != \"number\") {\n        if (dir == null) dir = this.options.smartIndent ? \"smart\" : \"prev\";\n        else dir = dir ? \"add\" : \"subtract\";\n      }\n      if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);\n    }),\n    indentSelection: operation(null, function(how) {\n      var sel = this.doc.sel;\n      if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how, true);\n      var e = sel.to.line - (sel.to.ch ? 0 : 1);\n      for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);\n    }),\n\n    // Fetch the parser token for a given character. Useful for hacks\n    // that want to inspect the mode state (say, for completion).\n    getTokenAt: function(pos, precise) {\n      var doc = this.doc;\n      pos = clipPos(doc, pos);\n      var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;\n      var line = getLine(doc, pos.line);\n      var stream = new StringStream(line.text, this.options.tabSize);\n      while (stream.pos < pos.ch && !stream.eol()) {\n        stream.start = stream.pos;\n        var style = mode.token(stream, state);\n      }\n      return {start: stream.start,\n              end: stream.pos,\n              string: stream.current(),\n              className: style || null, // Deprecated, use 'type' instead\n              type: style || null,\n              state: state};\n    },\n\n    getTokenTypeAt: function(pos) {\n      pos = clipPos(this.doc, pos);\n      var styles = getLineStyles(this, getLine(this.doc, pos.line));\n      var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;\n      if (ch == 0) return styles[2];\n      for (;;) {\n        var mid = (before + after) >> 1;\n        if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;\n        else if (styles[mid * 2 + 1] < ch) before = mid + 1;\n        else return styles[mid * 2 + 2];\n      }\n    },\n\n    getModeAt: function(pos) {\n      var mode = this.doc.mode;\n      if (!mode.innerMode) return mode;\n      return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;\n    },\n\n    getHelper: function(pos, type) {\n      return this.getHelpers(pos, type)[0];\n    },\n\n    getHelpers: function(pos, type) {\n      var found = [];\n      if (!helpers.hasOwnProperty(type)) return helpers;\n      var help = helpers[type], mode = this.getModeAt(pos);\n      if (typeof mode[type] == \"string\") {\n        if (help[mode[type]]) found.push(help[mode[type]]);\n      } else if (mode[type]) {\n        for (var i = 0; i < mode[type].length; i++) {\n          var val = help[mode[type][i]];\n          if (val) found.push(val);\n        }\n      } else if (mode.helperType && help[mode.helperType]) {\n        found.push(help[mode.helperType]);\n      } else if (help[mode.name]) {\n        found.push(help[mode.name]);\n      }\n      for (var i = 0; i < help._global.length; i++) {\n        var cur = help._global[i];\n        if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)\n          found.push(cur.val);\n      }\n      return found;\n    },\n\n    getStateAfter: function(line, precise) {\n      var doc = this.doc;\n      line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);\n      return getStateBefore(this, line + 1, precise);\n    },\n\n    cursorCoords: function(start, mode) {\n      var pos, sel = this.doc.sel;\n      if (start == null) pos = sel.head;\n      else if (typeof start == \"object\") pos = clipPos(this.doc, start);\n      else pos = start ? sel.from : sel.to;\n      return cursorCoords(this, pos, mode || \"page\");\n    },\n\n    charCoords: function(pos, mode) {\n      return charCoords(this, clipPos(this.doc, pos), mode || \"page\");\n    },\n\n    coordsChar: function(coords, mode) {\n      coords = fromCoordSystem(this, coords, mode || \"page\");\n      return coordsChar(this, coords.left, coords.top);\n    },\n\n    lineAtHeight: function(height, mode) {\n      height = fromCoordSystem(this, {top: height, left: 0}, mode || \"page\").top;\n      return lineAtHeight(this.doc, height + this.display.viewOffset);\n    },\n    heightAtLine: function(line, mode) {\n      var end = false, last = this.doc.first + this.doc.size - 1;\n      if (line < this.doc.first) line = this.doc.first;\n      else if (line > last) { line = last; end = true; }\n      var lineObj = getLine(this.doc, line);\n      return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || \"page\").top +\n        (end ? lineObj.height : 0);\n    },\n\n    defaultTextHeight: function() { return textHeight(this.display); },\n    defaultCharWidth: function() { return charWidth(this.display); },\n\n    setGutterMarker: operation(null, function(line, gutterID, value) {\n      return changeLine(this, line, function(line) {\n        var markers = line.gutterMarkers || (line.gutterMarkers = {});\n        markers[gutterID] = value;\n        if (!value && isEmpty(markers)) line.gutterMarkers = null;\n        return true;\n      });\n    }),\n\n    clearGutter: operation(null, function(gutterID) {\n      var cm = this, doc = cm.doc, i = doc.first;\n      doc.iter(function(line) {\n        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {\n          line.gutterMarkers[gutterID] = null;\n          regChange(cm, i, i + 1);\n          if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;\n        }\n        ++i;\n      });\n    }),\n\n    addLineClass: operation(null, function(handle, where, cls) {\n      return changeLine(this, handle, function(line) {\n        var prop = where == \"text\" ? \"textClass\" : where == \"background\" ? \"bgClass\" : \"wrapClass\";\n        if (!line[prop]) line[prop] = cls;\n        else if (new RegExp(\"(?:^|\\\\s)\" + cls + \"(?:$|\\\\s)\").test(line[prop])) return false;\n        else line[prop] += \" \" + cls;\n        return true;\n      });\n    }),\n\n    removeLineClass: operation(null, function(handle, where, cls) {\n      return changeLine(this, handle, function(line) {\n        var prop = where == \"text\" ? \"textClass\" : where == \"background\" ? \"bgClass\" : \"wrapClass\";\n        var cur = line[prop];\n        if (!cur) return false;\n        else if (cls == null) line[prop] = null;\n        else {\n          var found = cur.match(new RegExp(\"(?:^|\\\\s+)\" + cls + \"(?:$|\\\\s+)\"));\n          if (!found) return false;\n          var end = found.index + found[0].length;\n          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? \"\" : \" \") + cur.slice(end) || null;\n        }\n        return true;\n      });\n    }),\n\n    addLineWidget: operation(null, function(handle, node, options) {\n      return addLineWidget(this, handle, node, options);\n    }),\n\n    removeLineWidget: function(widget) { widget.clear(); },\n\n    lineInfo: function(line) {\n      if (typeof line == \"number\") {\n        if (!isLine(this.doc, line)) return null;\n        var n = line;\n        line = getLine(this.doc, line);\n        if (!line) return null;\n      } else {\n        var n = lineNo(line);\n        if (n == null) return null;\n      }\n      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,\n              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,\n              widgets: line.widgets};\n    },\n\n    getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},\n\n    addWidget: function(pos, node, scroll, vert, horiz) {\n      var display = this.display;\n      pos = cursorCoords(this, clipPos(this.doc, pos));\n      var top = pos.bottom, left = pos.left;\n      node.style.position = \"absolute\";\n      display.sizer.appendChild(node);\n      if (vert == \"over\") {\n        top = pos.top;\n      } else if (vert == \"above\" || vert == \"near\") {\n        var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),\n        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);\n        // Default to positioning above (if specified and possible); otherwise default to positioning below\n        if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)\n          top = pos.top - node.offsetHeight;\n        else if (pos.bottom + node.offsetHeight <= vspace)\n          top = pos.bottom;\n        if (left + node.offsetWidth > hspace)\n          left = hspace - node.offsetWidth;\n      }\n      node.style.top = top + \"px\";\n      node.style.left = node.style.right = \"\";\n      if (horiz == \"right\") {\n        left = display.sizer.clientWidth - node.offsetWidth;\n        node.style.right = \"0px\";\n      } else {\n        if (horiz == \"left\") left = 0;\n        else if (horiz == \"middle\") left = (display.sizer.clientWidth - node.offsetWidth) / 2;\n        node.style.left = left + \"px\";\n      }\n      if (scroll)\n        scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);\n    },\n\n    triggerOnKeyDown: operation(null, onKeyDown),\n    triggerOnKeyPress: operation(null, onKeyPress),\n    triggerOnKeyUp: operation(null, onKeyUp),\n\n    execCommand: function(cmd) {\n      if (commands.hasOwnProperty(cmd))\n        return commands[cmd](this);\n    },\n\n    findPosH: function(from, amount, unit, visually) {\n      var dir = 1;\n      if (amount < 0) { dir = -1; amount = -amount; }\n      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {\n        cur = findPosH(this.doc, cur, dir, unit, visually);\n        if (cur.hitSide) break;\n      }\n      return cur;\n    },\n\n    moveH: operation(null, function(dir, unit) {\n      var sel = this.doc.sel, pos;\n      if (sel.shift || sel.extend || posEq(sel.from, sel.to))\n        pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);\n      else\n        pos = dir < 0 ? sel.from : sel.to;\n      extendSelection(this.doc, pos, pos, dir);\n    }),\n\n    deleteH: operation(null, function(dir, unit) {\n      var sel = this.doc.sel;\n      if (!posEq(sel.from, sel.to)) replaceRange(this.doc, \"\", sel.from, sel.to, \"+delete\");\n      else replaceRange(this.doc, \"\", sel.from, findPosH(this.doc, sel.head, dir, unit, false), \"+delete\");\n      this.curOp.userSelChange = true;\n    }),\n\n    findPosV: function(from, amount, unit, goalColumn) {\n      var dir = 1, x = goalColumn;\n      if (amount < 0) { dir = -1; amount = -amount; }\n      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {\n        var coords = cursorCoords(this, cur, \"div\");\n        if (x == null) x = coords.left;\n        else coords.left = x;\n        cur = findPosV(this, coords, dir, unit);\n        if (cur.hitSide) break;\n      }\n      return cur;\n    },\n\n    moveV: operation(null, function(dir, unit) {\n      var sel = this.doc.sel, target, goal;\n      if (sel.shift || sel.extend || posEq(sel.from, sel.to)) {\n        var pos = cursorCoords(this, sel.head, \"div\");\n        if (sel.goalColumn != null) pos.left = sel.goalColumn;\n        target = findPosV(this, pos, dir, unit);\n        if (unit == \"page\") addToScrollPos(this, 0, charCoords(this, target, \"div\").top - pos.top);\n        goal = pos.left;\n      } else {\n        target = dir < 0 ? sel.from : sel.to;\n      }\n      extendSelection(this.doc, target, target, dir);\n      if (goal != null) sel.goalColumn = goal;\n    }),\n\n    toggleOverwrite: function(value) {\n      if (value != null && value == this.state.overwrite) return;\n      if (this.state.overwrite = !this.state.overwrite)\n        this.display.cursor.className += \" CodeMirror-overwrite\";\n      else\n        this.display.cursor.className = this.display.cursor.className.replace(\" CodeMirror-overwrite\", \"\");\n\n      signal(this, \"overwriteToggle\", this, this.state.overwrite);\n    },\n    hasFocus: function() { return document.activeElement == this.display.input; },\n\n    scrollTo: operation(null, function(x, y) {\n      updateScrollPos(this, x, y);\n    }),\n    getScrollInfo: function() {\n      var scroller = this.display.scroller, co = scrollerCutOff;\n      return {left: scroller.scrollLeft, top: scroller.scrollTop,\n              height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,\n              clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};\n    },\n\n    scrollIntoView: operation(null, function(range, margin) {\n      if (range == null) range = {from: this.doc.sel.head, to: null};\n      else if (typeof range == \"number\") range = {from: Pos(range, 0), to: null};\n      else if (range.from == null) range = {from: range, to: null};\n      if (!range.to) range.to = range.from;\n      if (!margin) margin = 0;\n\n      var coords = range;\n      if (range.from.line != null) {\n        this.curOp.scrollToPos = {from: range.from, to: range.to, margin: margin};\n        coords = {from: cursorCoords(this, range.from),\n                  to: cursorCoords(this, range.to)};\n      }\n      var sPos = calculateScrollPos(this, Math.min(coords.from.left, coords.to.left),\n                                    Math.min(coords.from.top, coords.to.top) - margin,\n                                    Math.max(coords.from.right, coords.to.right),\n                                    Math.max(coords.from.bottom, coords.to.bottom) + margin);\n      updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);\n    }),\n\n    setSize: operation(null, function(width, height) {\n      function interpret(val) {\n        return typeof val == \"number\" || /^\\d+$/.test(String(val)) ? val + \"px\" : val;\n      }\n      if (width != null) this.display.wrapper.style.width = interpret(width);\n      if (height != null) this.display.wrapper.style.height = interpret(height);\n      if (this.options.lineWrapping)\n        this.display.measureLineCache.length = this.display.measureLineCachePos = 0;\n      this.curOp.forceUpdate = true;\n      signal(this, \"refresh\", this);\n    }),\n\n    operation: function(f){return runInOp(this, f);},\n\n    refresh: operation(null, function() {\n      var oldHeight = this.display.cachedTextHeight;\n      clearCaches(this);\n      updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);\n      regChange(this);\n      if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)\n        estimateLineHeights(this);\n      signal(this, \"refresh\", this);\n    }),\n\n    swapDoc: operation(null, function(doc) {\n      var old = this.doc;\n      old.cm = null;\n      attachDoc(this, doc);\n      clearCaches(this);\n      resetInput(this, true);\n      updateScrollPos(this, doc.scrollLeft, doc.scrollTop);\n      signalLater(this, \"swapDoc\", this, old);\n      return old;\n    }),\n\n    getInputField: function(){return this.display.input;},\n    getWrapperElement: function(){return this.display.wrapper;},\n    getScrollerElement: function(){return this.display.scroller;},\n    getGutterElement: function(){return this.display.gutters;}\n  };\n  eventMixin(CodeMirror);\n\n  // OPTION DEFAULTS\n\n  var optionHandlers = CodeMirror.optionHandlers = {};\n\n  // The default configuration options.\n  var defaults = CodeMirror.defaults = {};\n\n  function option(name, deflt, handle, notOnInit) {\n    CodeMirror.defaults[name] = deflt;\n    if (handle) optionHandlers[name] =\n      notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;\n  }\n\n  var Init = CodeMirror.Init = {toString: function(){return \"CodeMirror.Init\";}};\n\n  // These two are, on init, called from the constructor because they\n  // have to be initialized before the editor can start at all.\n  option(\"value\", \"\", function(cm, val) {\n    cm.setValue(val);\n  }, true);\n  option(\"mode\", null, function(cm, val) {\n    cm.doc.modeOption = val;\n    loadMode(cm);\n  }, true);\n\n  option(\"indentUnit\", 2, loadMode, true);\n  option(\"indentWithTabs\", false);\n  option(\"smartIndent\", true);\n  option(\"tabSize\", 4, function(cm) {\n    resetModeState(cm);\n    clearCaches(cm);\n    regChange(cm);\n  }, true);\n  option(\"specialChars\", /[\\t\\u0000-\\u0019\\u00ad\\u200b\\u2028\\u2029\\ufeff]/g, function(cm, val) {\n    cm.options.specialChars = new RegExp(val.source + (val.test(\"\\t\") ? \"\" : \"|\\t\"), \"g\");\n    cm.refresh();\n  }, true);\n  option(\"specialCharPlaceholder\", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);\n  option(\"electricChars\", true);\n  option(\"rtlMoveVisually\", !windows);\n  option(\"wholeLineUpdateBefore\", true);\n\n  option(\"theme\", \"default\", function(cm) {\n    themeChanged(cm);\n    guttersChanged(cm);\n  }, true);\n  option(\"keyMap\", \"default\", keyMapChanged);\n  option(\"extraKeys\", null);\n\n  option(\"onKeyEvent\", null);\n  option(\"onDragEvent\", null);\n\n  option(\"lineWrapping\", false, wrappingChanged, true);\n  option(\"gutters\", [], function(cm) {\n    setGuttersForLineNumbers(cm.options);\n    guttersChanged(cm);\n  }, true);\n  option(\"fixedGutter\", true, function(cm, val) {\n    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + \"px\" : \"0\";\n    cm.refresh();\n  }, true);\n  option(\"coverGutterNextToScrollbar\", false, updateScrollbars, true);\n  option(\"lineNumbers\", false, function(cm) {\n    setGuttersForLineNumbers(cm.options);\n    guttersChanged(cm);\n  }, true);\n  option(\"firstLineNumber\", 1, guttersChanged, true);\n  option(\"lineNumberFormatter\", function(integer) {return integer;}, guttersChanged, true);\n  option(\"showCursorWhenSelecting\", false, updateSelection, true);\n\n  option(\"resetSelectionOnContextMenu\", true);\n\n  option(\"readOnly\", false, function(cm, val) {\n    if (val == \"nocursor\") {\n      onBlur(cm);\n      cm.display.input.blur();\n      cm.display.disabled = true;\n    } else {\n      cm.display.disabled = false;\n      if (!val) resetInput(cm, true);\n    }\n  });\n  option(\"disableInput\", false, function(cm, val) {if (!val) resetInput(cm, true);}, true);\n  option(\"dragDrop\", true);\n\n  option(\"cursorBlinkRate\", 530);\n  option(\"cursorScrollMargin\", 0);\n  option(\"cursorHeight\", 1);\n  option(\"workTime\", 100);\n  option(\"workDelay\", 100);\n  option(\"flattenSpans\", true, resetModeState, true);\n  option(\"addModeClass\", false, resetModeState, true);\n  option(\"pollInterval\", 100);\n  option(\"undoDepth\", 40, function(cm, val){cm.doc.history.undoDepth = val;});\n  option(\"historyEventDelay\", 500);\n  option(\"viewportMargin\", 10, function(cm){cm.refresh();}, true);\n  option(\"maxHighlightLength\", 10000, resetModeState, true);\n  option(\"crudeMeasuringFrom\", 10000);\n  option(\"moveInputWithCursor\", true, function(cm, val) {\n    if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;\n  });\n\n  option(\"tabindex\", null, function(cm, val) {\n    cm.display.input.tabIndex = val || \"\";\n  });\n  option(\"autofocus\", null);\n\n  // MODE DEFINITION AND QUERYING\n\n  // Known modes, by name and by MIME\n  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};\n\n  CodeMirror.defineMode = function(name, mode) {\n    if (!CodeMirror.defaults.mode && name != \"null\") CodeMirror.defaults.mode = name;\n    if (arguments.length > 2) {\n      mode.dependencies = [];\n      for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);\n    }\n    modes[name] = mode;\n  };\n\n  CodeMirror.defineMIME = function(mime, spec) {\n    mimeModes[mime] = spec;\n  };\n\n  CodeMirror.resolveMode = function(spec) {\n    if (typeof spec == \"string\" && mimeModes.hasOwnProperty(spec)) {\n      spec = mimeModes[spec];\n    } else if (spec && typeof spec.name == \"string\" && mimeModes.hasOwnProperty(spec.name)) {\n      var found = mimeModes[spec.name];\n      if (typeof found == \"string\") found = {name: found};\n      spec = createObj(found, spec);\n      spec.name = found.name;\n    } else if (typeof spec == \"string\" && /^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(spec)) {\n      return CodeMirror.resolveMode(\"application/xml\");\n    }\n    if (typeof spec == \"string\") return {name: spec};\n    else return spec || {name: \"null\"};\n  };\n\n  CodeMirror.getMode = function(options, spec) {\n    var spec = CodeMirror.resolveMode(spec);\n    var mfactory = modes[spec.name];\n    if (!mfactory) return CodeMirror.getMode(options, \"text/plain\");\n    var modeObj = mfactory(options, spec);\n    if (modeExtensions.hasOwnProperty(spec.name)) {\n      var exts = modeExtensions[spec.name];\n      for (var prop in exts) {\n        if (!exts.hasOwnProperty(prop)) continue;\n        if (modeObj.hasOwnProperty(prop)) modeObj[\"_\" + prop] = modeObj[prop];\n        modeObj[prop] = exts[prop];\n      }\n    }\n    modeObj.name = spec.name;\n    if (spec.helperType) modeObj.helperType = spec.helperType;\n    if (spec.modeProps) for (var prop in spec.modeProps)\n      modeObj[prop] = spec.modeProps[prop];\n\n    return modeObj;\n  };\n\n  CodeMirror.defineMode(\"null\", function() {\n    return {token: function(stream) {stream.skipToEnd();}};\n  });\n  CodeMirror.defineMIME(\"text/plain\", \"null\");\n\n  var modeExtensions = CodeMirror.modeExtensions = {};\n  CodeMirror.extendMode = function(mode, properties) {\n    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});\n    copyObj(properties, exts);\n  };\n\n  // EXTENSIONS\n\n  CodeMirror.defineExtension = function(name, func) {\n    CodeMirror.prototype[name] = func;\n  };\n  CodeMirror.defineDocExtension = function(name, func) {\n    Doc.prototype[name] = func;\n  };\n  CodeMirror.defineOption = option;\n\n  var initHooks = [];\n  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};\n\n  var helpers = CodeMirror.helpers = {};\n  CodeMirror.registerHelper = function(type, name, value) {\n    if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};\n    helpers[type][name] = value;\n  };\n  CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {\n    CodeMirror.registerHelper(type, name, value);\n    helpers[type]._global.push({pred: predicate, val: value});\n  };\n\n  // UTILITIES\n\n  CodeMirror.isWordChar = isWordChar;\n\n  // MODE STATE HANDLING\n\n  // Utility functions for working with state. Exported because modes\n  // sometimes need to do this.\n  function copyState(mode, state) {\n    if (state === true) return state;\n    if (mode.copyState) return mode.copyState(state);\n    var nstate = {};\n    for (var n in state) {\n      var val = state[n];\n      if (val instanceof Array) val = val.concat([]);\n      nstate[n] = val;\n    }\n    return nstate;\n  }\n  CodeMirror.copyState = copyState;\n\n  function startState(mode, a1, a2) {\n    return mode.startState ? mode.startState(a1, a2) : true;\n  }\n  CodeMirror.startState = startState;\n\n  CodeMirror.innerMode = function(mode, state) {\n    while (mode.innerMode) {\n      var info = mode.innerMode(state);\n      if (!info || info.mode == mode) break;\n      state = info.state;\n      mode = info.mode;\n    }\n    return info || {mode: mode, state: state};\n  };\n\n  // STANDARD COMMANDS\n\n  var commands = CodeMirror.commands = {\n    selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},\n    killLine: function(cm) {\n      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);\n      if (!sel && cm.getLine(from.line).length == from.ch)\n        cm.replaceRange(\"\", from, Pos(from.line + 1, 0), \"+delete\");\n      else cm.replaceRange(\"\", from, sel ? to : Pos(from.line), \"+delete\");\n    },\n    deleteLine: function(cm) {\n      var l = cm.getCursor().line;\n      cm.replaceRange(\"\", Pos(l, 0), Pos(l + 1, 0), \"+delete\");\n    },\n    delLineLeft: function(cm) {\n      var cur = cm.getCursor();\n      cm.replaceRange(\"\", Pos(cur.line, 0), cur, \"+delete\");\n    },\n    undo: function(cm) {cm.undo();},\n    redo: function(cm) {cm.redo();},\n    goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},\n    goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},\n    goLineStart: function(cm) {\n      cm.extendSelection(lineStart(cm, cm.getCursor().line));\n    },\n    goLineStartSmart: function(cm) {\n      var cur = cm.getCursor(), start = lineStart(cm, cur.line);\n      var line = cm.getLineHandle(start.line);\n      var order = getOrder(line);\n      if (!order || order[0].level == 0) {\n        var firstNonWS = Math.max(0, line.text.search(/\\S/));\n        var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;\n        cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));\n      } else cm.extendSelection(start);\n    },\n    goLineEnd: function(cm) {\n      cm.extendSelection(lineEnd(cm, cm.getCursor().line));\n    },\n    goLineRight: function(cm) {\n      var top = cm.charCoords(cm.getCursor(), \"div\").top + 5;\n      cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, \"div\"));\n    },\n    goLineLeft: function(cm) {\n      var top = cm.charCoords(cm.getCursor(), \"div\").top + 5;\n      cm.extendSelection(cm.coordsChar({left: 0, top: top}, \"div\"));\n    },\n    goLineUp: function(cm) {cm.moveV(-1, \"line\");},\n    goLineDown: function(cm) {cm.moveV(1, \"line\");},\n    goPageUp: function(cm) {cm.moveV(-1, \"page\");},\n    goPageDown: function(cm) {cm.moveV(1, \"page\");},\n    goCharLeft: function(cm) {cm.moveH(-1, \"char\");},\n    goCharRight: function(cm) {cm.moveH(1, \"char\");},\n    goColumnLeft: function(cm) {cm.moveH(-1, \"column\");},\n    goColumnRight: function(cm) {cm.moveH(1, \"column\");},\n    goWordLeft: function(cm) {cm.moveH(-1, \"word\");},\n    goGroupRight: function(cm) {cm.moveH(1, \"group\");},\n    goGroupLeft: function(cm) {cm.moveH(-1, \"group\");},\n    goWordRight: function(cm) {cm.moveH(1, \"word\");},\n    delCharBefore: function(cm) {cm.deleteH(-1, \"char\");},\n    delCharAfter: function(cm) {cm.deleteH(1, \"char\");},\n    delWordBefore: function(cm) {cm.deleteH(-1, \"word\");},\n    delWordAfter: function(cm) {cm.deleteH(1, \"word\");},\n    delGroupBefore: function(cm) {cm.deleteH(-1, \"group\");},\n    delGroupAfter: function(cm) {cm.deleteH(1, \"group\");},\n    indentAuto: function(cm) {cm.indentSelection(\"smart\");},\n    indentMore: function(cm) {cm.indentSelection(\"add\");},\n    indentLess: function(cm) {cm.indentSelection(\"subtract\");},\n    insertTab: function(cm) {\n      cm.replaceSelection(\"\\t\", \"end\", \"+input\");\n    },\n    defaultTab: function(cm) {\n      if (cm.somethingSelected()) cm.indentSelection(\"add\");\n      else cm.replaceSelection(\"\\t\", \"end\", \"+input\");\n    },\n    transposeChars: function(cm) {\n      var cur = cm.getCursor(), line = cm.getLine(cur.line);\n      if (cur.ch > 0 && cur.ch < line.length - 1)\n        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),\n                        Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));\n    },\n    newlineAndIndent: function(cm) {\n      operation(cm, function() {\n        cm.replaceSelection(\"\\n\", \"end\", \"+input\");\n        cm.indentLine(cm.getCursor().line, null, true);\n      })();\n    },\n    toggleOverwrite: function(cm) {cm.toggleOverwrite();}\n  };\n\n  // STANDARD KEYMAPS\n\n  var keyMap = CodeMirror.keyMap = {};\n  keyMap.basic = {\n    \"Left\": \"goCharLeft\", \"Right\": \"goCharRight\", \"Up\": \"goLineUp\", \"Down\": \"goLineDown\",\n    \"End\": \"goLineEnd\", \"Home\": \"goLineStartSmart\", \"PageUp\": \"goPageUp\", \"PageDown\": \"goPageDown\",\n    \"Delete\": \"delCharAfter\", \"Backspace\": \"delCharBefore\", \"Shift-Backspace\": \"delCharBefore\",\n    \"Tab\": \"defaultTab\", \"Shift-Tab\": \"indentAuto\",\n    \"Enter\": \"newlineAndIndent\", \"Insert\": \"toggleOverwrite\"\n  };\n  // Note that the save and find-related commands aren't defined by\n  // default. Unknown commands are simply ignored.\n  keyMap.pcDefault = {\n    \"Ctrl-A\": \"selectAll\", \"Ctrl-D\": \"deleteLine\", \"Ctrl-Z\": \"undo\", \"Shift-Ctrl-Z\": \"redo\", \"Ctrl-Y\": \"redo\",\n    \"Ctrl-Home\": \"goDocStart\", \"Ctrl-Up\": \"goDocStart\", \"Ctrl-End\": \"goDocEnd\", \"Ctrl-Down\": \"goDocEnd\",\n    \"Ctrl-Left\": \"goGroupLeft\", \"Ctrl-Right\": \"goGroupRight\", \"Alt-Left\": \"goLineStart\", \"Alt-Right\": \"goLineEnd\",\n    \"Ctrl-Backspace\": \"delGroupBefore\", \"Ctrl-Delete\": \"delGroupAfter\", \"Ctrl-S\": \"save\", \"Ctrl-F\": \"find\",\n    \"Ctrl-G\": \"findNext\", \"Shift-Ctrl-G\": \"findPrev\", \"Shift-Ctrl-F\": \"replace\", \"Shift-Ctrl-R\": \"replaceAll\",\n    \"Ctrl-[\": \"indentLess\", \"Ctrl-]\": \"indentMore\",\n    fallthrough: \"basic\"\n  };\n  keyMap.macDefault = {\n    \"Cmd-A\": \"selectAll\", \"Cmd-D\": \"deleteLine\", \"Cmd-Z\": \"undo\", \"Shift-Cmd-Z\": \"redo\", \"Cmd-Y\": \"redo\",\n    \"Cmd-Up\": \"goDocStart\", \"Cmd-End\": \"goDocEnd\", \"Cmd-Down\": \"goDocEnd\", \"Alt-Left\": \"goGroupLeft\",\n    \"Alt-Right\": \"goGroupRight\", \"Cmd-Left\": \"goLineStart\", \"Cmd-Right\": \"goLineEnd\", \"Alt-Backspace\": \"delGroupBefore\",\n    \"Ctrl-Alt-Backspace\": \"delGroupAfter\", \"Alt-Delete\": \"delGroupAfter\", \"Cmd-S\": \"save\", \"Cmd-F\": \"find\",\n    \"Cmd-G\": \"findNext\", \"Shift-Cmd-G\": \"findPrev\", \"Cmd-Alt-F\": \"replace\", \"Shift-Cmd-Alt-F\": \"replaceAll\",\n    \"Cmd-[\": \"indentLess\", \"Cmd-]\": \"indentMore\", \"Cmd-Backspace\": \"delLineLeft\",\n    fallthrough: [\"basic\", \"emacsy\"]\n  };\n  keyMap[\"default\"] = mac ? keyMap.macDefault : keyMap.pcDefault;\n  keyMap.emacsy = {\n    \"Ctrl-F\": \"goCharRight\", \"Ctrl-B\": \"goCharLeft\", \"Ctrl-P\": \"goLineUp\", \"Ctrl-N\": \"goLineDown\",\n    \"Alt-F\": \"goWordRight\", \"Alt-B\": \"goWordLeft\", \"Ctrl-A\": \"goLineStart\", \"Ctrl-E\": \"goLineEnd\",\n    \"Ctrl-V\": \"goPageDown\", \"Shift-Ctrl-V\": \"goPageUp\", \"Ctrl-D\": \"delCharAfter\", \"Ctrl-H\": \"delCharBefore\",\n    \"Alt-D\": \"delWordAfter\", \"Alt-Backspace\": \"delWordBefore\", \"Ctrl-K\": \"killLine\", \"Ctrl-T\": \"transposeChars\"\n  };\n\n  // KEYMAP DISPATCH\n\n  function getKeyMap(val) {\n    if (typeof val == \"string\") return keyMap[val];\n    else return val;\n  }\n\n  function lookupKey(name, maps, handle) {\n    function lookup(map) {\n      map = getKeyMap(map);\n      var found = map[name];\n      if (found === false) return \"stop\";\n      if (found != null && handle(found)) return true;\n      if (map.nofallthrough) return \"stop\";\n\n      var fallthrough = map.fallthrough;\n      if (fallthrough == null) return false;\n      if (Object.prototype.toString.call(fallthrough) != \"[object Array]\")\n        return lookup(fallthrough);\n      for (var i = 0, e = fallthrough.length; i < e; ++i) {\n        var done = lookup(fallthrough[i]);\n        if (done) return done;\n      }\n      return false;\n    }\n\n    for (var i = 0; i < maps.length; ++i) {\n      var done = lookup(maps[i]);\n      if (done) return done != \"stop\";\n    }\n  }\n  function isModifierKey(event) {\n    var name = keyNames[event.keyCode];\n    return name == \"Ctrl\" || name == \"Alt\" || name == \"Shift\" || name == \"Mod\";\n  }\n  function keyName(event, noShift) {\n    if (opera && event.keyCode == 34 && event[\"char\"]) return false;\n    var name = keyNames[event.keyCode];\n    if (name == null || event.altGraphKey) return false;\n    if (event.altKey) name = \"Alt-\" + name;\n    if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = \"Ctrl-\" + name;\n    if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = \"Cmd-\" + name;\n    if (!noShift && event.shiftKey) name = \"Shift-\" + name;\n    return name;\n  }\n  CodeMirror.lookupKey = lookupKey;\n  CodeMirror.isModifierKey = isModifierKey;\n  CodeMirror.keyName = keyName;\n\n  // FROMTEXTAREA\n\n  CodeMirror.fromTextArea = function(textarea, options) {\n    if (!options) options = {};\n    options.value = textarea.value;\n    if (!options.tabindex && textarea.tabindex)\n      options.tabindex = textarea.tabindex;\n    if (!options.placeholder && textarea.placeholder)\n      options.placeholder = textarea.placeholder;\n    // Set autofocus to true if this textarea is focused, or if it has\n    // autofocus and no other element is focused.\n    if (options.autofocus == null) {\n      var hasFocus = document.body;\n      // doc.activeElement occasionally throws on IE\n      try { hasFocus = document.activeElement; } catch(e) {}\n      options.autofocus = hasFocus == textarea ||\n        textarea.getAttribute(\"autofocus\") != null && hasFocus == document.body;\n    }\n\n    function save() {textarea.value = cm.getValue();}\n    if (textarea.form) {\n      on(textarea.form, \"submit\", save);\n      // Deplorable hack to make the submit method do the right thing.\n      if (!options.leaveSubmitMethodAlone) {\n        var form = textarea.form, realSubmit = form.submit;\n        try {\n          var wrappedSubmit = form.submit = function() {\n            save();\n            form.submit = realSubmit;\n            form.submit();\n            form.submit = wrappedSubmit;\n          };\n        } catch(e) {}\n      }\n    }\n\n    textarea.style.display = \"none\";\n    var cm = CodeMirror(function(node) {\n      textarea.parentNode.insertBefore(node, textarea.nextSibling);\n    }, options);\n    cm.save = save;\n    cm.getTextArea = function() { return textarea; };\n    cm.toTextArea = function() {\n      save();\n      textarea.parentNode.removeChild(cm.getWrapperElement());\n      textarea.style.display = \"\";\n      if (textarea.form) {\n        off(textarea.form, \"submit\", save);\n        if (typeof textarea.form.submit == \"function\")\n          textarea.form.submit = realSubmit;\n      }\n    };\n    return cm;\n  };\n\n  // STRING STREAM\n\n  // Fed to the mode parsers, provides helper functions to make\n  // parsers more succinct.\n\n  // The character stream used by a mode's parser.\n  function StringStream(string, tabSize) {\n    this.pos = this.start = 0;\n    this.string = string;\n    this.tabSize = tabSize || 8;\n    this.lastColumnPos = this.lastColumnValue = 0;\n    this.lineStart = 0;\n  }\n\n  StringStream.prototype = {\n    eol: function() {return this.pos >= this.string.length;},\n    sol: function() {return this.pos == this.lineStart;},\n    peek: function() {return this.string.charAt(this.pos) || undefined;},\n    next: function() {\n      if (this.pos < this.string.length)\n        return this.string.charAt(this.pos++);\n    },\n    eat: function(match) {\n      var ch = this.string.charAt(this.pos);\n      if (typeof match == \"string\") var ok = ch == match;\n      else var ok = ch && (match.test ? match.test(ch) : match(ch));\n      if (ok) {++this.pos; return ch;}\n    },\n    eatWhile: function(match) {\n      var start = this.pos;\n      while (this.eat(match)){}\n      return this.pos > start;\n    },\n    eatSpace: function() {\n      var start = this.pos;\n      while (/[\\s\\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;\n      return this.pos > start;\n    },\n    skipToEnd: function() {this.pos = this.string.length;},\n    skipTo: function(ch) {\n      var found = this.string.indexOf(ch, this.pos);\n      if (found > -1) {this.pos = found; return true;}\n    },\n    backUp: function(n) {this.pos -= n;},\n    column: function() {\n      if (this.lastColumnPos < this.start) {\n        this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);\n        this.lastColumnPos = this.start;\n      }\n      return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);\n    },\n    indentation: function() {\n      return countColumn(this.string, null, this.tabSize) -\n        (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);\n    },\n    match: function(pattern, consume, caseInsensitive) {\n      if (typeof pattern == \"string\") {\n        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};\n        var substr = this.string.substr(this.pos, pattern.length);\n        if (cased(substr) == cased(pattern)) {\n          if (consume !== false) this.pos += pattern.length;\n          return true;\n        }\n      } else {\n        var match = this.string.slice(this.pos).match(pattern);\n        if (match && match.index > 0) return null;\n        if (match && consume !== false) this.pos += match[0].length;\n        return match;\n      }\n    },\n    current: function(){return this.string.slice(this.start, this.pos);},\n    hideFirstChars: function(n, inner) {\n      this.lineStart += n;\n      try { return inner(); }\n      finally { this.lineStart -= n; }\n    }\n  };\n  CodeMirror.StringStream = StringStream;\n\n  // TEXTMARKERS\n\n  function TextMarker(doc, type) {\n    this.lines = [];\n    this.type = type;\n    this.doc = doc;\n  }\n  CodeMirror.TextMarker = TextMarker;\n  eventMixin(TextMarker);\n\n  TextMarker.prototype.clear = function() {\n    if (this.explicitlyCleared) return;\n    var cm = this.doc.cm, withOp = cm && !cm.curOp;\n    if (withOp) startOperation(cm);\n    if (hasHandler(this, \"clear\")) {\n      var found = this.find();\n      if (found) signalLater(this, \"clear\", found.from, found.to);\n    }\n    var min = null, max = null;\n    for (var i = 0; i < this.lines.length; ++i) {\n      var line = this.lines[i];\n      var span = getMarkedSpanFor(line.markedSpans, this);\n      if (span.to != null) max = lineNo(line);\n      line.markedSpans = removeMarkedSpan(line.markedSpans, span);\n      if (span.from != null)\n        min = lineNo(line);\n      else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)\n        updateLineHeight(line, textHeight(cm.display));\n    }\n    if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {\n      var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);\n      if (len > cm.display.maxLineLength) {\n        cm.display.maxLine = visual;\n        cm.display.maxLineLength = len;\n        cm.display.maxLineChanged = true;\n      }\n    }\n\n    if (min != null && cm) regChange(cm, min, max + 1);\n    this.lines.length = 0;\n    this.explicitlyCleared = true;\n    if (this.atomic && this.doc.cantEdit) {\n      this.doc.cantEdit = false;\n      if (cm) reCheckSelection(cm);\n    }\n    if (withOp) endOperation(cm);\n  };\n\n  TextMarker.prototype.find = function(bothSides) {\n    var from, to;\n    for (var i = 0; i < this.lines.length; ++i) {\n      var line = this.lines[i];\n      var span = getMarkedSpanFor(line.markedSpans, this);\n      if (span.from != null || span.to != null) {\n        var found = lineNo(line);\n        if (span.from != null) from = Pos(found, span.from);\n        if (span.to != null) to = Pos(found, span.to);\n      }\n    }\n    if (this.type == \"bookmark\" && !bothSides) return from;\n    return from && {from: from, to: to};\n  };\n\n  TextMarker.prototype.changed = function() {\n    var pos = this.find(), cm = this.doc.cm;\n    if (!pos || !cm) return;\n    if (this.type != \"bookmark\") pos = pos.from;\n    var line = getLine(this.doc, pos.line);\n    clearCachedMeasurement(cm, line);\n    if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) {\n      for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {\n        if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);\n        break;\n      }\n      runInOp(cm, function() {\n        cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;\n      });\n    }\n  };\n\n  TextMarker.prototype.attachLine = function(line) {\n    if (!this.lines.length && this.doc.cm) {\n      var op = this.doc.cm.curOp;\n      if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)\n        (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);\n    }\n    this.lines.push(line);\n  };\n  TextMarker.prototype.detachLine = function(line) {\n    this.lines.splice(indexOf(this.lines, line), 1);\n    if (!this.lines.length && this.doc.cm) {\n      var op = this.doc.cm.curOp;\n      (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);\n    }\n  };\n\n  var nextMarkerId = 0;\n\n  function markText(doc, from, to, options, type) {\n    if (options && options.shared) return markTextShared(doc, from, to, options, type);\n    if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);\n\n    var marker = new TextMarker(doc, type);\n    if (options) copyObj(options, marker);\n    if (posLess(to, from) || posEq(from, to) && marker.clearWhenEmpty !== false)\n      return marker;\n    if (marker.replacedWith) {\n      marker.collapsed = true;\n      marker.replacedWith = elt(\"span\", [marker.replacedWith], \"CodeMirror-widget\");\n      if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;\n    }\n    if (marker.collapsed) {\n      if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||\n          from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))\n        throw new Error(\"Inserting collapsed marker partially overlapping an existing one\");\n      sawCollapsedSpans = true;\n    }\n\n    if (marker.addToHistory)\n      addToHistory(doc, {from: from, to: to, origin: \"markText\"},\n                   {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);\n\n    var curLine = from.line, cm = doc.cm, updateMaxLine;\n    doc.iter(curLine, to.line + 1, function(line) {\n      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)\n        updateMaxLine = true;\n      var span = {from: null, to: null, marker: marker};\n      if (curLine == from.line) span.from = from.ch;\n      if (curLine == to.line) span.to = to.ch;\n      if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);\n      addMarkedSpan(line, span);\n      ++curLine;\n    });\n    if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {\n      if (lineIsHidden(doc, line)) updateLineHeight(line, 0);\n    });\n\n    if (marker.clearOnEnter) on(marker, \"beforeCursorEnter\", function() { marker.clear(); });\n\n    if (marker.readOnly) {\n      sawReadOnlySpans = true;\n      if (doc.history.done.length || doc.history.undone.length)\n        doc.clearHistory();\n    }\n    if (marker.collapsed) {\n      marker.id = ++nextMarkerId;\n      marker.atomic = true;\n    }\n    if (cm) {\n      if (updateMaxLine) cm.curOp.updateMaxLine = true;\n      if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)\n        regChange(cm, from.line, to.line + 1);\n      if (marker.atomic) reCheckSelection(cm);\n    }\n    return marker;\n  }\n\n  // SHARED TEXTMARKERS\n\n  function SharedTextMarker(markers, primary) {\n    this.markers = markers;\n    this.primary = primary;\n    for (var i = 0, me = this; i < markers.length; ++i) {\n      markers[i].parent = this;\n      on(markers[i], \"clear\", function(){me.clear();});\n    }\n  }\n  CodeMirror.SharedTextMarker = SharedTextMarker;\n  eventMixin(SharedTextMarker);\n\n  SharedTextMarker.prototype.clear = function() {\n    if (this.explicitlyCleared) return;\n    this.explicitlyCleared = true;\n    for (var i = 0; i < this.markers.length; ++i)\n      this.markers[i].clear();\n    signalLater(this, \"clear\");\n  };\n  SharedTextMarker.prototype.find = function() {\n    return this.primary.find();\n  };\n\n  function markTextShared(doc, from, to, options, type) {\n    options = copyObj(options);\n    options.shared = false;\n    var markers = [markText(doc, from, to, options, type)], primary = markers[0];\n    var widget = options.replacedWith;\n    linkedDocs(doc, function(doc) {\n      if (widget) options.replacedWith = widget.cloneNode(true);\n      markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));\n      for (var i = 0; i < doc.linked.length; ++i)\n        if (doc.linked[i].isParent) return;\n      primary = lst(markers);\n    });\n    return new SharedTextMarker(markers, primary);\n  }\n\n  // TEXTMARKER SPANS\n\n  function getMarkedSpanFor(spans, marker) {\n    if (spans) for (var i = 0; i < spans.length; ++i) {\n      var span = spans[i];\n      if (span.marker == marker) return span;\n    }\n  }\n  function removeMarkedSpan(spans, span) {\n    for (var r, i = 0; i < spans.length; ++i)\n      if (spans[i] != span) (r || (r = [])).push(spans[i]);\n    return r;\n  }\n  function addMarkedSpan(line, span) {\n    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];\n    span.marker.attachLine(line);\n  }\n\n  function markedSpansBefore(old, startCh, isInsert) {\n    if (old) for (var i = 0, nw; i < old.length; ++i) {\n      var span = old[i], marker = span.marker;\n      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);\n      if (startsBefore || span.from == startCh && marker.type == \"bookmark\" && (!isInsert || !span.marker.insertLeft)) {\n        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);\n        (nw || (nw = [])).push({from: span.from,\n                                to: endsAfter ? null : span.to,\n                                marker: marker});\n      }\n    }\n    return nw;\n  }\n\n  function markedSpansAfter(old, endCh, isInsert) {\n    if (old) for (var i = 0, nw; i < old.length; ++i) {\n      var span = old[i], marker = span.marker;\n      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);\n      if (endsAfter || span.from == endCh && marker.type == \"bookmark\" && (!isInsert || span.marker.insertLeft)) {\n        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);\n        (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,\n                                to: span.to == null ? null : span.to - endCh,\n                                marker: marker});\n      }\n    }\n    return nw;\n  }\n\n  function stretchSpansOverChange(doc, change) {\n    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;\n    var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;\n    if (!oldFirst && !oldLast) return null;\n\n    var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);\n    // Get the spans that 'stick out' on both sides\n    var first = markedSpansBefore(oldFirst, startCh, isInsert);\n    var last = markedSpansAfter(oldLast, endCh, isInsert);\n\n    // Next, merge those two ends\n    var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);\n    if (first) {\n      // Fix up .to properties of first\n      for (var i = 0; i < first.length; ++i) {\n        var span = first[i];\n        if (span.to == null) {\n          var found = getMarkedSpanFor(last, span.marker);\n          if (!found) span.to = startCh;\n          else if (sameLine) span.to = found.to == null ? null : found.to + offset;\n        }\n      }\n    }\n    if (last) {\n      // Fix up .from in last (or move them into first in case of sameLine)\n      for (var i = 0; i < last.length; ++i) {\n        var span = last[i];\n        if (span.to != null) span.to += offset;\n        if (span.from == null) {\n          var found = getMarkedSpanFor(first, span.marker);\n          if (!found) {\n            span.from = offset;\n            if (sameLine) (first || (first = [])).push(span);\n          }\n        } else {\n          span.from += offset;\n          if (sameLine) (first || (first = [])).push(span);\n        }\n      }\n    }\n    // Make sure we didn't create any zero-length spans\n    if (first) first = clearEmptySpans(first);\n    if (last && last != first) last = clearEmptySpans(last);\n\n    var newMarkers = [first];\n    if (!sameLine) {\n      // Fill gap with whole-line-spans\n      var gap = change.text.length - 2, gapMarkers;\n      if (gap > 0 && first)\n        for (var i = 0; i < first.length; ++i)\n          if (first[i].to == null)\n            (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});\n      for (var i = 0; i < gap; ++i)\n        newMarkers.push(gapMarkers);\n      newMarkers.push(last);\n    }\n    return newMarkers;\n  }\n\n  function clearEmptySpans(spans) {\n    for (var i = 0; i < spans.length; ++i) {\n      var span = spans[i];\n      if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)\n        spans.splice(i--, 1);\n    }\n    if (!spans.length) return null;\n    return spans;\n  }\n\n  function mergeOldSpans(doc, change) {\n    var old = getOldSpans(doc, change);\n    var stretched = stretchSpansOverChange(doc, change);\n    if (!old) return stretched;\n    if (!stretched) return old;\n\n    for (var i = 0; i < old.length; ++i) {\n      var oldCur = old[i], stretchCur = stretched[i];\n      if (oldCur && stretchCur) {\n        spans: for (var j = 0; j < stretchCur.length; ++j) {\n          var span = stretchCur[j];\n          for (var k = 0; k < oldCur.length; ++k)\n            if (oldCur[k].marker == span.marker) continue spans;\n          oldCur.push(span);\n        }\n      } else if (stretchCur) {\n        old[i] = stretchCur;\n      }\n    }\n    return old;\n  }\n\n  function removeReadOnlyRanges(doc, from, to) {\n    var markers = null;\n    doc.iter(from.line, to.line + 1, function(line) {\n      if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {\n        var mark = line.markedSpans[i].marker;\n        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))\n          (markers || (markers = [])).push(mark);\n      }\n    });\n    if (!markers) return null;\n    var parts = [{from: from, to: to}];\n    for (var i = 0; i < markers.length; ++i) {\n      var mk = markers[i], m = mk.find();\n      for (var j = 0; j < parts.length; ++j) {\n        var p = parts[j];\n        if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;\n        var newParts = [j, 1];\n        if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))\n          newParts.push({from: p.from, to: m.from});\n        if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))\n          newParts.push({from: m.to, to: p.to});\n        parts.splice.apply(parts, newParts);\n        j += newParts.length - 1;\n      }\n    }\n    return parts;\n  }\n\n  function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }\n  function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }\n\n  function compareCollapsedMarkers(a, b) {\n    var lenDiff = a.lines.length - b.lines.length;\n    if (lenDiff != 0) return lenDiff;\n    var aPos = a.find(), bPos = b.find();\n    var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);\n    if (fromCmp) return -fromCmp;\n    var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);\n    if (toCmp) return toCmp;\n    return b.id - a.id;\n  }\n\n  function collapsedSpanAtSide(line, start) {\n    var sps = sawCollapsedSpans && line.markedSpans, found;\n    if (sps) for (var sp, i = 0; i < sps.length; ++i) {\n      sp = sps[i];\n      if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&\n          (!found || compareCollapsedMarkers(found, sp.marker) < 0))\n        found = sp.marker;\n    }\n    return found;\n  }\n  function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }\n  function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }\n\n  function conflictingCollapsedRange(doc, lineNo, from, to, marker) {\n    var line = getLine(doc, lineNo);\n    var sps = sawCollapsedSpans && line.markedSpans;\n    if (sps) for (var i = 0; i < sps.length; ++i) {\n      var sp = sps[i];\n      if (!sp.marker.collapsed) continue;\n      var found = sp.marker.find(true);\n      var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);\n      var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);\n      if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;\n      if (fromCmp <= 0 && (cmp(found.to, from) || extraRight(sp.marker) - extraLeft(marker)) > 0 ||\n          fromCmp >= 0 && (cmp(found.from, to) || extraLeft(sp.marker) - extraRight(marker)) < 0)\n        return true;\n    }\n  }\n\n  function visualLine(doc, line) {\n    var merged;\n    while (merged = collapsedSpanAtStart(line))\n      line = getLine(doc, merged.find().from.line);\n    return line;\n  }\n\n  function lineIsHidden(doc, line) {\n    var sps = sawCollapsedSpans && line.markedSpans;\n    if (sps) for (var sp, i = 0; i < sps.length; ++i) {\n      sp = sps[i];\n      if (!sp.marker.collapsed) continue;\n      if (sp.from == null) return true;\n      if (sp.marker.replacedWith) continue;\n      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))\n        return true;\n    }\n  }\n  function lineIsHiddenInner(doc, line, span) {\n    if (span.to == null) {\n      var end = span.marker.find().to, endLine = getLine(doc, end.line);\n      return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));\n    }\n    if (span.marker.inclusiveRight && span.to == line.text.length)\n      return true;\n    for (var sp, i = 0; i < line.markedSpans.length; ++i) {\n      sp = line.markedSpans[i];\n      if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&\n          (sp.to == null || sp.to != span.from) &&\n          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&\n          lineIsHiddenInner(doc, line, sp)) return true;\n    }\n  }\n\n  function detachMarkedSpans(line) {\n    var spans = line.markedSpans;\n    if (!spans) return;\n    for (var i = 0; i < spans.length; ++i)\n      spans[i].marker.detachLine(line);\n    line.markedSpans = null;\n  }\n\n  function attachMarkedSpans(line, spans) {\n    if (!spans) return;\n    for (var i = 0; i < spans.length; ++i)\n      spans[i].marker.attachLine(line);\n    line.markedSpans = spans;\n  }\n\n  // LINE WIDGETS\n\n  var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {\n    if (options) for (var opt in options) if (options.hasOwnProperty(opt))\n      this[opt] = options[opt];\n    this.cm = cm;\n    this.node = node;\n  };\n  eventMixin(LineWidget);\n  function widgetOperation(f) {\n    return function() {\n      var withOp = !this.cm.curOp;\n      if (withOp) startOperation(this.cm);\n      try {var result = f.apply(this, arguments);}\n      finally {if (withOp) endOperation(this.cm);}\n      return result;\n    };\n  }\n  LineWidget.prototype.clear = widgetOperation(function() {\n    var ws = this.line.widgets, no = lineNo(this.line);\n    if (no == null || !ws) return;\n    for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);\n    if (!ws.length) this.line.widgets = null;\n    var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;\n    updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));\n    if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);\n    regChange(this.cm, no, no + 1);\n  });\n  LineWidget.prototype.changed = widgetOperation(function() {\n    var oldH = this.height;\n    this.height = null;\n    var diff = widgetHeight(this) - oldH;\n    if (!diff) return;\n    updateLineHeight(this.line, this.line.height + diff);\n    var no = lineNo(this.line);\n    regChange(this.cm, no, no + 1);\n  });\n\n  function widgetHeight(widget) {\n    if (widget.height != null) return widget.height;\n    if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)\n      removeChildrenAndAdd(widget.cm.display.measure, elt(\"div\", [widget.node], null, \"position: relative\"));\n    return widget.height = widget.node.offsetHeight;\n  }\n\n  function addLineWidget(cm, handle, node, options) {\n    var widget = new LineWidget(cm, node, options);\n    if (widget.noHScroll) cm.display.alignWidgets = true;\n    changeLine(cm, handle, function(line) {\n      var widgets = line.widgets || (line.widgets = []);\n      if (widget.insertAt == null) widgets.push(widget);\n      else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);\n      widget.line = line;\n      if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {\n        var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;\n        updateLineHeight(line, line.height + widgetHeight(widget));\n        if (aboveVisible) addToScrollPos(cm, 0, widget.height);\n        cm.curOp.forceUpdate = true;\n      }\n      return true;\n    });\n    return widget;\n  }\n\n  // LINE DATA STRUCTURE\n\n  // Line objects. These hold state related to a line, including\n  // highlighting info (the styles array).\n  var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {\n    this.text = text;\n    attachMarkedSpans(this, markedSpans);\n    this.height = estimateHeight ? estimateHeight(this) : 1;\n  };\n  eventMixin(Line);\n  Line.prototype.lineNo = function() { return lineNo(this); };\n\n  function updateLine(line, text, markedSpans, estimateHeight) {\n    line.text = text;\n    if (line.stateAfter) line.stateAfter = null;\n    if (line.styles) line.styles = null;\n    if (line.order != null) line.order = null;\n    detachMarkedSpans(line);\n    attachMarkedSpans(line, markedSpans);\n    var estHeight = estimateHeight ? estimateHeight(line) : 1;\n    if (estHeight != line.height) updateLineHeight(line, estHeight);\n  }\n\n  function cleanUpLine(line) {\n    line.parent = null;\n    detachMarkedSpans(line);\n  }\n\n  // Run the given mode's parser over a line, update the styles\n  // array, which contains alternating fragments of text and CSS\n  // classes.\n  function runMode(cm, text, mode, state, f, forceToEnd) {\n    var flattenSpans = mode.flattenSpans;\n    if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;\n    var curStart = 0, curStyle = null;\n    var stream = new StringStream(text, cm.options.tabSize), style;\n    if (text == \"\" && mode.blankLine) mode.blankLine(state);\n    while (!stream.eol()) {\n      if (stream.pos > cm.options.maxHighlightLength) {\n        flattenSpans = false;\n        if (forceToEnd) processLine(cm, text, state, stream.pos);\n        stream.pos = text.length;\n        style = null;\n      } else {\n        style = mode.token(stream, state);\n      }\n      if (cm.options.addModeClass) {\n        var mName = CodeMirror.innerMode(mode, state).mode.name;\n        if (mName) style = \"m-\" + (style ? mName + \" \" + style : mName);\n      }\n      if (!flattenSpans || curStyle != style) {\n        if (curStart < stream.start) f(stream.start, curStyle);\n        curStart = stream.start; curStyle = style;\n      }\n      stream.start = stream.pos;\n    }\n    while (curStart < stream.pos) {\n      // Webkit seems to refuse to render text nodes longer than 57444 characters\n      var pos = Math.min(stream.pos, curStart + 50000);\n      f(pos, curStyle);\n      curStart = pos;\n    }\n  }\n\n  function highlightLine(cm, line, state, forceToEnd) {\n    // A styles array always starts with a number identifying the\n    // mode/overlays that it is based on (for easy invalidation).\n    var st = [cm.state.modeGen];\n    // Compute the base array of styles\n    runMode(cm, line.text, cm.doc.mode, state, function(end, style) {\n      st.push(end, style);\n    }, forceToEnd);\n\n    // Run overlays, adjust style array.\n    for (var o = 0; o < cm.state.overlays.length; ++o) {\n      var overlay = cm.state.overlays[o], i = 1, at = 0;\n      runMode(cm, line.text, overlay.mode, true, function(end, style) {\n        var start = i;\n        // Ensure there's a token end at the current position, and that i points at it\n        while (at < end) {\n          var i_end = st[i];\n          if (i_end > end)\n            st.splice(i, 1, end, st[i+1], i_end);\n          i += 2;\n          at = Math.min(end, i_end);\n        }\n        if (!style) return;\n        if (overlay.opaque) {\n          st.splice(start, i - start, end, style);\n          i = start + 2;\n        } else {\n          for (; start < i; start += 2) {\n            var cur = st[start+1];\n            st[start+1] = cur ? cur + \" \" + style : style;\n          }\n        }\n      });\n    }\n\n    return st;\n  }\n\n  function getLineStyles(cm, line) {\n    if (!line.styles || line.styles[0] != cm.state.modeGen)\n      line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));\n    return line.styles;\n  }\n\n  // Lightweight form of highlight -- proceed over this line and\n  // update state, but don't save a style array.\n  function processLine(cm, text, state, startAt) {\n    var mode = cm.doc.mode;\n    var stream = new StringStream(text, cm.options.tabSize);\n    stream.start = stream.pos = startAt || 0;\n    if (text == \"\" && mode.blankLine) mode.blankLine(state);\n    while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {\n      mode.token(stream, state);\n      stream.start = stream.pos;\n    }\n  }\n\n  var styleToClassCache = {}, styleToClassCacheWithMode = {};\n  function interpretTokenStyle(style, builder) {\n    if (!style) return null;\n    for (;;) {\n      var lineClass = style.match(/(?:^|\\s+)line-(background-)?(\\S+)/);\n      if (!lineClass) break;\n      style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length);\n      var prop = lineClass[1] ? \"bgClass\" : \"textClass\";\n      if (builder[prop] == null)\n        builder[prop] = lineClass[2];\n      else if (!(new RegExp(\"(?:^|\\s)\" + lineClass[2] + \"(?:$|\\s)\")).test(builder[prop]))\n        builder[prop] += \" \" + lineClass[2];\n    }\n    if (/^\\s*$/.test(style)) return null;\n    var cache = builder.cm.options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;\n    return cache[style] ||\n      (cache[style] = style.replace(/\\S+/g, \"cm-$&\"));\n  }\n\n  function buildLineContent(cm, realLine, measure, copyWidgets) {\n    var merged, line = realLine, empty = true;\n    while (merged = collapsedSpanAtStart(line))\n      line = getLine(cm.doc, merged.find().from.line);\n\n    var builder = {pre: elt(\"pre\"), col: 0, pos: 0,\n                   measure: null, measuredSomething: false, cm: cm,\n                   copyWidgets: copyWidgets};\n\n    do {\n      if (line.text) empty = false;\n      builder.measure = line == realLine && measure;\n      builder.pos = 0;\n      builder.addToken = builder.measure ? buildTokenMeasure : buildToken;\n      if ((ie || webkit) && cm.getOption(\"lineWrapping\"))\n        builder.addToken = buildTokenSplitSpaces(builder.addToken);\n      var next = insertLineContent(line, builder, getLineStyles(cm, line));\n      if (measure && line == realLine && !builder.measuredSomething) {\n        measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));\n        builder.measuredSomething = true;\n      }\n      if (next) line = getLine(cm.doc, next.to.line);\n    } while (next);\n\n    if (measure && !builder.measuredSomething && !measure[0])\n      measure[0] = builder.pre.appendChild(empty ? elt(\"span\", \"\\u00a0\") : zeroWidthElement(cm.display.measure));\n    if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))\n      builder.pre.appendChild(document.createTextNode(\"\\u00a0\"));\n\n    var order;\n    // Work around problem with the reported dimensions of single-char\n    // direction spans on IE (issue #1129). See also the comment in\n    // cursorCoords.\n    if (measure && ie && (order = getOrder(line))) {\n      var l = order.length - 1;\n      if (order[l].from == order[l].to) --l;\n      var last = order[l], prev = order[l - 1];\n      if (last.from + 1 == last.to && prev && last.level < prev.level) {\n        var span = measure[builder.pos - 1];\n        if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),\n                                               span.nextSibling);\n      }\n    }\n\n    var textClass = builder.textClass ? builder.textClass + \" \" + (realLine.textClass || \"\") : realLine.textClass;\n    if (textClass) builder.pre.className = textClass;\n\n    signal(cm, \"renderLine\", cm, realLine, builder.pre);\n    return builder;\n  }\n\n  function defaultSpecialCharPlaceholder(ch) {\n    var token = elt(\"span\", \"\\u2022\", \"cm-invalidchar\");\n    token.title = \"\\\\u\" + ch.charCodeAt(0).toString(16);\n    return token;\n  }\n\n  function buildToken(builder, text, style, startStyle, endStyle, title) {\n    if (!text) return;\n    var special = builder.cm.options.specialChars;\n    if (!special.test(text)) {\n      builder.col += text.length;\n      var content = document.createTextNode(text);\n    } else {\n      var content = document.createDocumentFragment(), pos = 0;\n      while (true) {\n        special.lastIndex = pos;\n        var m = special.exec(text);\n        var skipped = m ? m.index - pos : text.length - pos;\n        if (skipped) {\n          content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));\n          builder.col += skipped;\n        }\n        if (!m) break;\n        pos += skipped + 1;\n        if (m[0] == \"\\t\") {\n          var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;\n          content.appendChild(elt(\"span\", spaceStr(tabWidth), \"cm-tab\"));\n          builder.col += tabWidth;\n        } else {\n          var token = builder.cm.options.specialCharPlaceholder(m[0]);\n          content.appendChild(token);\n          builder.col += 1;\n        }\n      }\n    }\n    if (style || startStyle || endStyle || builder.measure) {\n      var fullStyle = style || \"\";\n      if (startStyle) fullStyle += startStyle;\n      if (endStyle) fullStyle += endStyle;\n      var token = elt(\"span\", [content], fullStyle);\n      if (title) token.title = title;\n      return builder.pre.appendChild(token);\n    }\n    builder.pre.appendChild(content);\n  }\n\n  function buildTokenMeasure(builder, text, style, startStyle, endStyle) {\n    var wrapping = builder.cm.options.lineWrapping;\n    for (var i = 0; i < text.length; ++i) {\n      var start = i == 0, to = i + 1;\n      while (to < text.length && isExtendingChar(text.charAt(to))) ++to;\n      var ch = text.slice(i, to);\n      i = to - 1;\n      if (i && wrapping && spanAffectsWrapping(text, i))\n        builder.pre.appendChild(elt(\"wbr\"));\n      var old = builder.measure[builder.pos];\n      var span = builder.measure[builder.pos] =\n        buildToken(builder, ch, style,\n                   start && startStyle, i == text.length - 1 && endStyle);\n      if (old) span.leftSide = old.leftSide || old;\n      // In IE single-space nodes wrap differently than spaces\n      // embedded in larger text nodes, except when set to\n      // white-space: normal (issue #1268).\n      if (old_ie && wrapping && ch == \" \" && i && !/\\s/.test(text.charAt(i - 1)) &&\n          i < text.length - 1 && !/\\s/.test(text.charAt(i + 1)))\n        span.style.whiteSpace = \"normal\";\n      builder.pos += ch.length;\n    }\n    if (text.length) builder.measuredSomething = true;\n  }\n\n  function buildTokenSplitSpaces(inner) {\n    function split(old) {\n      var out = \" \";\n      for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? \" \" : \"\\u00a0\";\n      out += \" \";\n      return out;\n    }\n    return function(builder, text, style, startStyle, endStyle, title) {\n      return inner(builder, text.replace(/ {3,}/g, split), style, startStyle, endStyle, title);\n    };\n  }\n\n  function buildCollapsedSpan(builder, size, marker, ignoreWidget) {\n    var widget = !ignoreWidget && marker.replacedWith;\n    if (widget) {\n      if (builder.copyWidgets) widget = widget.cloneNode(true);\n      builder.pre.appendChild(widget);\n      if (builder.measure) {\n        if (size) {\n          builder.measure[builder.pos] = widget;\n        } else {\n          var elt = zeroWidthElement(builder.cm.display.measure);\n          if (marker.type == \"bookmark\" && !marker.insertLeft)\n            builder.measure[builder.pos] = builder.pre.appendChild(elt);\n          else if (builder.measure[builder.pos])\n            return;\n          else\n            builder.measure[builder.pos] = builder.pre.insertBefore(elt, widget);\n        }\n        builder.measuredSomething = true;\n      }\n    }\n    builder.pos += size;\n  }\n\n  // Outputs a number of spans to make up a line, taking highlighting\n  // and marked text into account.\n  function insertLineContent(line, builder, styles) {\n    var spans = line.markedSpans, allText = line.text, at = 0;\n    if (!spans) {\n      for (var i = 1; i < styles.length; i+=2)\n        builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder));\n      return;\n    }\n\n    var len = allText.length, pos = 0, i = 1, text = \"\", style;\n    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;\n    for (;;) {\n      if (nextChange == pos) { // Update current marker set\n        spanStyle = spanEndStyle = spanStartStyle = title = \"\";\n        collapsed = null; nextChange = Infinity;\n        var foundBookmarks = [];\n        for (var j = 0; j < spans.length; ++j) {\n          var sp = spans[j], m = sp.marker;\n          if (sp.from <= pos && (sp.to == null || sp.to > pos)) {\n            if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = \"\"; }\n            if (m.className) spanStyle += \" \" + m.className;\n            if (m.startStyle && sp.from == pos) spanStartStyle += \" \" + m.startStyle;\n            if (m.endStyle && sp.to == nextChange) spanEndStyle += \" \" + m.endStyle;\n            if (m.title && !title) title = m.title;\n            if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))\n              collapsed = sp;\n          } else if (sp.from > pos && nextChange > sp.from) {\n            nextChange = sp.from;\n          }\n          if (m.type == \"bookmark\" && sp.from == pos && m.replacedWith) foundBookmarks.push(m);\n        }\n        if (collapsed && (collapsed.from || 0) == pos) {\n          buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,\n                             collapsed.marker, collapsed.from == null);\n          if (collapsed.to == null) return collapsed.marker.find();\n        }\n        if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)\n          buildCollapsedSpan(builder, 0, foundBookmarks[j]);\n      }\n      if (pos >= len) break;\n\n      var upto = Math.min(len, nextChange);\n      while (true) {\n        if (text) {\n          var end = pos + text.length;\n          if (!collapsed) {\n            var tokenText = end > upto ? text.slice(0, upto - pos) : text;\n            builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,\n                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : \"\", title);\n          }\n          if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}\n          pos = end;\n          spanStartStyle = \"\";\n        }\n        text = allText.slice(at, at = styles[i++]);\n        style = interpretTokenStyle(styles[i++], builder);\n      }\n    }\n  }\n\n  // DOCUMENT DATA STRUCTURE\n\n  function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {\n    function spansFor(n) {return markedSpans ? markedSpans[n] : null;}\n    function update(line, text, spans) {\n      updateLine(line, text, spans, estimateHeight);\n      signalLater(line, \"change\", line, change);\n    }\n\n    var from = change.from, to = change.to, text = change.text;\n    var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);\n    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;\n\n    // First adjust the line structure\n    if (from.ch == 0 && to.ch == 0 && lastText == \"\" &&\n        (!doc.cm || doc.cm.options.wholeLineUpdateBefore)) {\n      // This is a whole-line replace. Treated specially to make\n      // sure line objects move the way they are supposed to.\n      for (var i = 0, e = text.length - 1, added = []; i < e; ++i)\n        added.push(new Line(text[i], spansFor(i), estimateHeight));\n      update(lastLine, lastLine.text, lastSpans);\n      if (nlines) doc.remove(from.line, nlines);\n      if (added.length) doc.insert(from.line, added);\n    } else if (firstLine == lastLine) {\n      if (text.length == 1) {\n        update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);\n      } else {\n        for (var added = [], i = 1, e = text.length - 1; i < e; ++i)\n          added.push(new Line(text[i], spansFor(i), estimateHeight));\n        added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));\n        update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));\n        doc.insert(from.line + 1, added);\n      }\n    } else if (text.length == 1) {\n      update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));\n      doc.remove(from.line + 1, nlines);\n    } else {\n      update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));\n      update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);\n      for (var i = 1, e = text.length - 1, added = []; i < e; ++i)\n        added.push(new Line(text[i], spansFor(i), estimateHeight));\n      if (nlines > 1) doc.remove(from.line + 1, nlines - 1);\n      doc.insert(from.line + 1, added);\n    }\n\n    signalLater(doc, \"change\", doc, change);\n    setSelection(doc, selAfter.anchor, selAfter.head, null, true);\n  }\n\n  function LeafChunk(lines) {\n    this.lines = lines;\n    this.parent = null;\n    for (var i = 0, e = lines.length, height = 0; i < e; ++i) {\n      lines[i].parent = this;\n      height += lines[i].height;\n    }\n    this.height = height;\n  }\n\n  LeafChunk.prototype = {\n    chunkSize: function() { return this.lines.length; },\n    removeInner: function(at, n) {\n      for (var i = at, e = at + n; i < e; ++i) {\n        var line = this.lines[i];\n        this.height -= line.height;\n        cleanUpLine(line);\n        signalLater(line, \"delete\");\n      }\n      this.lines.splice(at, n);\n    },\n    collapse: function(lines) {\n      lines.splice.apply(lines, [lines.length, 0].concat(this.lines));\n    },\n    insertInner: function(at, lines, height) {\n      this.height += height;\n      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));\n      for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;\n    },\n    iterN: function(at, n, op) {\n      for (var e = at + n; at < e; ++at)\n        if (op(this.lines[at])) return true;\n    }\n  };\n\n  function BranchChunk(children) {\n    this.children = children;\n    var size = 0, height = 0;\n    for (var i = 0, e = children.length; i < e; ++i) {\n      var ch = children[i];\n      size += ch.chunkSize(); height += ch.height;\n      ch.parent = this;\n    }\n    this.size = size;\n    this.height = height;\n    this.parent = null;\n  }\n\n  BranchChunk.prototype = {\n    chunkSize: function() { return this.size; },\n    removeInner: function(at, n) {\n      this.size -= n;\n      for (var i = 0; i < this.children.length; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at < sz) {\n          var rm = Math.min(n, sz - at), oldHeight = child.height;\n          child.removeInner(at, rm);\n          this.height -= oldHeight - child.height;\n          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }\n          if ((n -= rm) == 0) break;\n          at = 0;\n        } else at -= sz;\n      }\n      if (this.size - n < 25) {\n        var lines = [];\n        this.collapse(lines);\n        this.children = [new LeafChunk(lines)];\n        this.children[0].parent = this;\n      }\n    },\n    collapse: function(lines) {\n      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);\n    },\n    insertInner: function(at, lines, height) {\n      this.size += lines.length;\n      this.height += height;\n      for (var i = 0, e = this.children.length; i < e; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at <= sz) {\n          child.insertInner(at, lines, height);\n          if (child.lines && child.lines.length > 50) {\n            while (child.lines.length > 50) {\n              var spilled = child.lines.splice(child.lines.length - 25, 25);\n              var newleaf = new LeafChunk(spilled);\n              child.height -= newleaf.height;\n              this.children.splice(i + 1, 0, newleaf);\n              newleaf.parent = this;\n            }\n            this.maybeSpill();\n          }\n          break;\n        }\n        at -= sz;\n      }\n    },\n    maybeSpill: function() {\n      if (this.children.length <= 10) return;\n      var me = this;\n      do {\n        var spilled = me.children.splice(me.children.length - 5, 5);\n        var sibling = new BranchChunk(spilled);\n        if (!me.parent) { // Become the parent node\n          var copy = new BranchChunk(me.children);\n          copy.parent = me;\n          me.children = [copy, sibling];\n          me = copy;\n        } else {\n          me.size -= sibling.size;\n          me.height -= sibling.height;\n          var myIndex = indexOf(me.parent.children, me);\n          me.parent.children.splice(myIndex + 1, 0, sibling);\n        }\n        sibling.parent = me.parent;\n      } while (me.children.length > 10);\n      me.parent.maybeSpill();\n    },\n    iterN: function(at, n, op) {\n      for (var i = 0, e = this.children.length; i < e; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at < sz) {\n          var used = Math.min(n, sz - at);\n          if (child.iterN(at, used, op)) return true;\n          if ((n -= used) == 0) break;\n          at = 0;\n        } else at -= sz;\n      }\n    }\n  };\n\n  var nextDocId = 0;\n  var Doc = CodeMirror.Doc = function(text, mode, firstLine) {\n    if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);\n    if (firstLine == null) firstLine = 0;\n\n    BranchChunk.call(this, [new LeafChunk([new Line(\"\", null)])]);\n    this.first = firstLine;\n    this.scrollTop = this.scrollLeft = 0;\n    this.cantEdit = false;\n    this.history = makeHistory();\n    this.cleanGeneration = 1;\n    this.frontier = firstLine;\n    var start = Pos(firstLine, 0);\n    this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};\n    this.id = ++nextDocId;\n    this.modeOption = mode;\n\n    if (typeof text == \"string\") text = splitLines(text);\n    updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});\n  };\n\n  Doc.prototype = createObj(BranchChunk.prototype, {\n    constructor: Doc,\n    iter: function(from, to, op) {\n      if (op) this.iterN(from - this.first, to - from, op);\n      else this.iterN(this.first, this.first + this.size, from);\n    },\n\n    insert: function(at, lines) {\n      var height = 0;\n      for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;\n      this.insertInner(at - this.first, lines, height);\n    },\n    remove: function(at, n) { this.removeInner(at - this.first, n); },\n\n    getValue: function(lineSep) {\n      var lines = getLines(this, this.first, this.first + this.size);\n      if (lineSep === false) return lines;\n      return lines.join(lineSep || \"\\n\");\n    },\n    setValue: function(code) {\n      var top = Pos(this.first, 0), last = this.first + this.size - 1;\n      makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),\n                        text: splitLines(code), origin: \"setValue\"},\n                 {head: top, anchor: top}, true);\n    },\n    replaceRange: function(code, from, to, origin) {\n      from = clipPos(this, from);\n      to = to ? clipPos(this, to) : from;\n      replaceRange(this, code, from, to, origin);\n    },\n    getRange: function(from, to, lineSep) {\n      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));\n      if (lineSep === false) return lines;\n      return lines.join(lineSep || \"\\n\");\n    },\n\n    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},\n    setLine: function(line, text) {\n      if (isLine(this, line))\n        replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));\n    },\n    removeLine: function(line) {\n      if (line) replaceRange(this, \"\", clipPos(this, Pos(line - 1)), clipPos(this, Pos(line)));\n      else replaceRange(this, \"\", Pos(0, 0), clipPos(this, Pos(1, 0)));\n    },\n\n    getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},\n    getLineNumber: function(line) {return lineNo(line);},\n\n    getLineHandleVisualStart: function(line) {\n      if (typeof line == \"number\") line = getLine(this, line);\n      return visualLine(this, line);\n    },\n\n    lineCount: function() {return this.size;},\n    firstLine: function() {return this.first;},\n    lastLine: function() {return this.first + this.size - 1;},\n\n    clipPos: function(pos) {return clipPos(this, pos);},\n\n    getCursor: function(start) {\n      var sel = this.sel, pos;\n      if (start == null || start == \"head\") pos = sel.head;\n      else if (start == \"anchor\") pos = sel.anchor;\n      else if (start == \"end\" || start === false) pos = sel.to;\n      else pos = sel.from;\n      return copyPos(pos);\n    },\n    somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},\n\n    setCursor: docOperation(function(line, ch, extend) {\n      var pos = clipPos(this, typeof line == \"number\" ? Pos(line, ch || 0) : line);\n      if (extend) extendSelection(this, pos);\n      else setSelection(this, pos, pos);\n    }),\n    setSelection: docOperation(function(anchor, head, bias) {\n      setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), bias);\n    }),\n    extendSelection: docOperation(function(from, to, bias) {\n      extendSelection(this, clipPos(this, from), to && clipPos(this, to), bias);\n    }),\n\n    getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},\n    replaceSelection: function(code, collapse, origin) {\n      makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || \"around\");\n    },\n    undo: docOperation(function() {makeChangeFromHistory(this, \"undo\");}),\n    redo: docOperation(function() {makeChangeFromHistory(this, \"redo\");}),\n\n    setExtending: function(val) {this.sel.extend = val;},\n\n    historySize: function() {\n      var hist = this.history;\n      return {undo: hist.done.length, redo: hist.undone.length};\n    },\n    clearHistory: function() {this.history = makeHistory(this.history.maxGeneration);},\n\n    markClean: function() {\n      this.cleanGeneration = this.changeGeneration(true);\n    },\n    changeGeneration: function(forceSplit) {\n      if (forceSplit)\n        this.history.lastOp = this.history.lastOrigin = null;\n      return this.history.generation;\n    },\n    isClean: function (gen) {\n      return this.history.generation == (gen || this.cleanGeneration);\n    },\n\n    getHistory: function() {\n      return {done: copyHistoryArray(this.history.done),\n              undone: copyHistoryArray(this.history.undone)};\n    },\n    setHistory: function(histData) {\n      var hist = this.history = makeHistory(this.history.maxGeneration);\n      hist.done = histData.done.slice(0);\n      hist.undone = histData.undone.slice(0);\n    },\n\n    markText: function(from, to, options) {\n      return markText(this, clipPos(this, from), clipPos(this, to), options, \"range\");\n    },\n    setBookmark: function(pos, options) {\n      var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),\n                      insertLeft: options && options.insertLeft,\n                      clearWhenEmpty: false};\n      pos = clipPos(this, pos);\n      return markText(this, pos, pos, realOpts, \"bookmark\");\n    },\n    findMarksAt: function(pos) {\n      pos = clipPos(this, pos);\n      var markers = [], spans = getLine(this, pos.line).markedSpans;\n      if (spans) for (var i = 0; i < spans.length; ++i) {\n        var span = spans[i];\n        if ((span.from == null || span.from <= pos.ch) &&\n            (span.to == null || span.to >= pos.ch))\n          markers.push(span.marker.parent || span.marker);\n      }\n      return markers;\n    },\n    findMarks: function(from, to) {\n      from = clipPos(this, from); to = clipPos(this, to);\n      var found = [], lineNo = from.line;\n      this.iter(from.line, to.line + 1, function(line) {\n        var spans = line.markedSpans;\n        if (spans) for (var i = 0; i < spans.length; i++) {\n          var span = spans[i];\n          if (!(lineNo == from.line && from.ch > span.to ||\n                span.from == null && lineNo != from.line||\n                lineNo == to.line && span.from > to.ch))\n            found.push(span.marker.parent || span.marker);\n        }\n        ++lineNo;\n      });\n      return found;\n    },\n    getAllMarks: function() {\n      var markers = [];\n      this.iter(function(line) {\n        var sps = line.markedSpans;\n        if (sps) for (var i = 0; i < sps.length; ++i)\n          if (sps[i].from != null) markers.push(sps[i].marker);\n      });\n      return markers;\n    },\n\n    posFromIndex: function(off) {\n      var ch, lineNo = this.first;\n      this.iter(function(line) {\n        var sz = line.text.length + 1;\n        if (sz > off) { ch = off; return true; }\n        off -= sz;\n        ++lineNo;\n      });\n      return clipPos(this, Pos(lineNo, ch));\n    },\n    indexFromPos: function (coords) {\n      coords = clipPos(this, coords);\n      var index = coords.ch;\n      if (coords.line < this.first || coords.ch < 0) return 0;\n      this.iter(this.first, coords.line, function (line) {\n        index += line.text.length + 1;\n      });\n      return index;\n    },\n\n    copy: function(copyHistory) {\n      var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);\n      doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;\n      doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,\n                 shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};\n      if (copyHistory) {\n        doc.history.undoDepth = this.history.undoDepth;\n        doc.setHistory(this.getHistory());\n      }\n      return doc;\n    },\n\n    linkedDoc: function(options) {\n      if (!options) options = {};\n      var from = this.first, to = this.first + this.size;\n      if (options.from != null && options.from > from) from = options.from;\n      if (options.to != null && options.to < to) to = options.to;\n      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);\n      if (options.sharedHist) copy.history = this.history;\n      (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});\n      copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];\n      return copy;\n    },\n    unlinkDoc: function(other) {\n      if (other instanceof CodeMirror) other = other.doc;\n      if (this.linked) for (var i = 0; i < this.linked.length; ++i) {\n        var link = this.linked[i];\n        if (link.doc != other) continue;\n        this.linked.splice(i, 1);\n        other.unlinkDoc(this);\n        break;\n      }\n      // If the histories were shared, split them again\n      if (other.history == this.history) {\n        var splitIds = [other.id];\n        linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);\n        other.history = makeHistory();\n        other.history.done = copyHistoryArray(this.history.done, splitIds);\n        other.history.undone = copyHistoryArray(this.history.undone, splitIds);\n      }\n    },\n    iterLinkedDocs: function(f) {linkedDocs(this, f);},\n\n    getMode: function() {return this.mode;},\n    getEditor: function() {return this.cm;}\n  });\n\n  Doc.prototype.eachLine = Doc.prototype.iter;\n\n  // The Doc methods that should be available on CodeMirror instances\n  var dontDelegate = \"iter insert remove copy getEditor\".split(\" \");\n  for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)\n    CodeMirror.prototype[prop] = (function(method) {\n      return function() {return method.apply(this.doc, arguments);};\n    })(Doc.prototype[prop]);\n\n  eventMixin(Doc);\n\n  function linkedDocs(doc, f, sharedHistOnly) {\n    function propagate(doc, skip, sharedHist) {\n      if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {\n        var rel = doc.linked[i];\n        if (rel.doc == skip) continue;\n        var shared = sharedHist && rel.sharedHist;\n        if (sharedHistOnly && !shared) continue;\n        f(rel.doc, shared);\n        propagate(rel.doc, doc, shared);\n      }\n    }\n    propagate(doc, null, true);\n  }\n\n  function attachDoc(cm, doc) {\n    if (doc.cm) throw new Error(\"This document is already in use.\");\n    cm.doc = doc;\n    doc.cm = cm;\n    estimateLineHeights(cm);\n    loadMode(cm);\n    if (!cm.options.lineWrapping) computeMaxLength(cm);\n    cm.options.mode = doc.modeOption;\n    regChange(cm);\n  }\n\n  // LINE UTILITIES\n\n  function getLine(chunk, n) {\n    n -= chunk.first;\n    while (!chunk.lines) {\n      for (var i = 0;; ++i) {\n        var child = chunk.children[i], sz = child.chunkSize();\n        if (n < sz) { chunk = child; break; }\n        n -= sz;\n      }\n    }\n    return chunk.lines[n];\n  }\n\n  function getBetween(doc, start, end) {\n    var out = [], n = start.line;\n    doc.iter(start.line, end.line + 1, function(line) {\n      var text = line.text;\n      if (n == end.line) text = text.slice(0, end.ch);\n      if (n == start.line) text = text.slice(start.ch);\n      out.push(text);\n      ++n;\n    });\n    return out;\n  }\n  function getLines(doc, from, to) {\n    var out = [];\n    doc.iter(from, to, function(line) { out.push(line.text); });\n    return out;\n  }\n\n  function updateLineHeight(line, height) {\n    var diff = height - line.height;\n    for (var n = line; n; n = n.parent) n.height += diff;\n  }\n\n  function lineNo(line) {\n    if (line.parent == null) return null;\n    var cur = line.parent, no = indexOf(cur.lines, line);\n    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {\n      for (var i = 0;; ++i) {\n        if (chunk.children[i] == cur) break;\n        no += chunk.children[i].chunkSize();\n      }\n    }\n    return no + cur.first;\n  }\n\n  function lineAtHeight(chunk, h) {\n    var n = chunk.first;\n    outer: do {\n      for (var i = 0, e = chunk.children.length; i < e; ++i) {\n        var child = chunk.children[i], ch = child.height;\n        if (h < ch) { chunk = child; continue outer; }\n        h -= ch;\n        n += child.chunkSize();\n      }\n      return n;\n    } while (!chunk.lines);\n    for (var i = 0, e = chunk.lines.length; i < e; ++i) {\n      var line = chunk.lines[i], lh = line.height;\n      if (h < lh) break;\n      h -= lh;\n    }\n    return n + i;\n  }\n\n  function heightAtLine(cm, lineObj) {\n    lineObj = visualLine(cm.doc, lineObj);\n\n    var h = 0, chunk = lineObj.parent;\n    for (var i = 0; i < chunk.lines.length; ++i) {\n      var line = chunk.lines[i];\n      if (line == lineObj) break;\n      else h += line.height;\n    }\n    for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {\n      for (var i = 0; i < p.children.length; ++i) {\n        var cur = p.children[i];\n        if (cur == chunk) break;\n        else h += cur.height;\n      }\n    }\n    return h;\n  }\n\n  function getOrder(line) {\n    var order = line.order;\n    if (order == null) order = line.order = bidiOrdering(line.text);\n    return order;\n  }\n\n  // HISTORY\n\n  function makeHistory(startGen) {\n    return {\n      // Arrays of history events. Doing something adds an event to\n      // done and clears undo. Undoing moves events from done to\n      // undone, redoing moves them in the other direction.\n      done: [], undone: [], undoDepth: Infinity,\n      // Used to track when changes can be merged into a single undo\n      // event\n      lastTime: 0, lastOp: null, lastOrigin: null,\n      // Used by the isClean() method\n      generation: startGen || 1, maxGeneration: startGen || 1\n    };\n  }\n\n  function attachLocalSpans(doc, change, from, to) {\n    var existing = change[\"spans_\" + doc.id], n = 0;\n    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {\n      if (line.markedSpans)\n        (existing || (existing = change[\"spans_\" + doc.id] = {}))[n] = line.markedSpans;\n      ++n;\n    });\n  }\n\n  function historyChangeFromChange(doc, change) {\n    var from = { line: change.from.line, ch: change.from.ch };\n    var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};\n    attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);\n    linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);\n    return histChange;\n  }\n\n  function addToHistory(doc, change, selAfter, opId) {\n    var hist = doc.history;\n    hist.undone.length = 0;\n    var time = +new Date, cur = lst(hist.done);\n\n    if (cur &&\n        (hist.lastOp == opId ||\n         hist.lastOrigin == change.origin && change.origin &&\n         ((change.origin.charAt(0) == \"+\" && doc.cm && hist.lastTime > time - doc.cm.options.historyEventDelay) ||\n          change.origin.charAt(0) == \"*\"))) {\n      // Merge this change into the last event\n      var last = lst(cur.changes);\n      if (posEq(change.from, change.to) && posEq(change.from, last.to)) {\n        // Optimized case for simple insertion -- don't want to add\n        // new changesets for every character typed\n        last.to = changeEnd(change);\n      } else {\n        // Add new sub-event\n        cur.changes.push(historyChangeFromChange(doc, change));\n      }\n      cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;\n    } else {\n      // Can not be merged, start a new event.\n      cur = {changes: [historyChangeFromChange(doc, change)],\n             generation: hist.generation,\n             anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,\n             anchorAfter: selAfter.anchor, headAfter: selAfter.head};\n      hist.done.push(cur);\n      while (hist.done.length > hist.undoDepth)\n        hist.done.shift();\n    }\n    hist.generation = ++hist.maxGeneration;\n    hist.lastTime = time;\n    hist.lastOp = opId;\n    hist.lastOrigin = change.origin;\n\n    if (!last) signal(doc, \"historyAdded\");\n  }\n\n  function removeClearedSpans(spans) {\n    if (!spans) return null;\n    for (var i = 0, out; i < spans.length; ++i) {\n      if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }\n      else if (out) out.push(spans[i]);\n    }\n    return !out ? spans : out.length ? out : null;\n  }\n\n  function getOldSpans(doc, change) {\n    var found = change[\"spans_\" + doc.id];\n    if (!found) return null;\n    for (var i = 0, nw = []; i < change.text.length; ++i)\n      nw.push(removeClearedSpans(found[i]));\n    return nw;\n  }\n\n  // Used both to provide a JSON-safe object in .getHistory, and, when\n  // detaching a document, to split the history in two\n  function copyHistoryArray(events, newGroup) {\n    for (var i = 0, copy = []; i < events.length; ++i) {\n      var event = events[i], changes = event.changes, newChanges = [];\n      copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,\n                 anchorAfter: event.anchorAfter, headAfter: event.headAfter});\n      for (var j = 0; j < changes.length; ++j) {\n        var change = changes[j], m;\n        newChanges.push({from: change.from, to: change.to, text: change.text});\n        if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\\d+)$/)) {\n          if (indexOf(newGroup, Number(m[1])) > -1) {\n            lst(newChanges)[prop] = change[prop];\n            delete change[prop];\n          }\n        }\n      }\n    }\n    return copy;\n  }\n\n  // Rebasing/resetting history to deal with externally-sourced changes\n\n  function rebaseHistSel(pos, from, to, diff) {\n    if (to < pos.line) {\n      pos.line += diff;\n    } else if (from < pos.line) {\n      pos.line = from;\n      pos.ch = 0;\n    }\n  }\n\n  // Tries to rebase an array of history events given a change in the\n  // document. If the change touches the same lines as the event, the\n  // event, and everything 'behind' it, is discarded. If the change is\n  // before the event, the event's positions are updated. Uses a\n  // copy-on-write scheme for the positions, to avoid having to\n  // reallocate them all on every rebase, but also avoid problems with\n  // shared position objects being unsafely updated.\n  function rebaseHistArray(array, from, to, diff) {\n    for (var i = 0; i < array.length; ++i) {\n      var sub = array[i], ok = true;\n      for (var j = 0; j < sub.changes.length; ++j) {\n        var cur = sub.changes[j];\n        if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }\n        if (to < cur.from.line) {\n          cur.from.line += diff;\n          cur.to.line += diff;\n        } else if (from <= cur.to.line) {\n          ok = false;\n          break;\n        }\n      }\n      if (!sub.copied) {\n        sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);\n        sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);\n        sub.copied = true;\n      }\n      if (!ok) {\n        array.splice(0, i + 1);\n        i = 0;\n      } else {\n        rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);\n        rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);\n      }\n    }\n  }\n\n  function rebaseHist(hist, change) {\n    var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;\n    rebaseHistArray(hist.done, from, to, diff);\n    rebaseHistArray(hist.undone, from, to, diff);\n  }\n\n  // EVENT OPERATORS\n\n  function stopMethod() {e_stop(this);}\n  // Ensure an event has a stop method.\n  function addStop(event) {\n    if (!event.stop) event.stop = stopMethod;\n    return event;\n  }\n\n  function e_preventDefault(e) {\n    if (e.preventDefault) e.preventDefault();\n    else e.returnValue = false;\n  }\n  function e_stopPropagation(e) {\n    if (e.stopPropagation) e.stopPropagation();\n    else e.cancelBubble = true;\n  }\n  function e_defaultPrevented(e) {\n    return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;\n  }\n  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}\n  CodeMirror.e_stop = e_stop;\n  CodeMirror.e_preventDefault = e_preventDefault;\n  CodeMirror.e_stopPropagation = e_stopPropagation;\n\n  function e_target(e) {return e.target || e.srcElement;}\n  function e_button(e) {\n    var b = e.which;\n    if (b == null) {\n      if (e.button & 1) b = 1;\n      else if (e.button & 2) b = 3;\n      else if (e.button & 4) b = 2;\n    }\n    if (mac && e.ctrlKey && b == 1) b = 3;\n    return b;\n  }\n\n  // EVENT HANDLING\n\n  function on(emitter, type, f) {\n    if (emitter.addEventListener)\n      emitter.addEventListener(type, f, false);\n    else if (emitter.attachEvent)\n      emitter.attachEvent(\"on\" + type, f);\n    else {\n      var map = emitter._handlers || (emitter._handlers = {});\n      var arr = map[type] || (map[type] = []);\n      arr.push(f);\n    }\n  }\n\n  function off(emitter, type, f) {\n    if (emitter.removeEventListener)\n      emitter.removeEventListener(type, f, false);\n    else if (emitter.detachEvent)\n      emitter.detachEvent(\"on\" + type, f);\n    else {\n      var arr = emitter._handlers && emitter._handlers[type];\n      if (!arr) return;\n      for (var i = 0; i < arr.length; ++i)\n        if (arr[i] == f) { arr.splice(i, 1); break; }\n    }\n  }\n\n  function signal(emitter, type /*, values...*/) {\n    var arr = emitter._handlers && emitter._handlers[type];\n    if (!arr) return;\n    var args = Array.prototype.slice.call(arguments, 2);\n    for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);\n  }\n\n  var delayedCallbacks, delayedCallbackDepth = 0;\n  function signalLater(emitter, type /*, values...*/) {\n    var arr = emitter._handlers && emitter._handlers[type];\n    if (!arr) return;\n    var args = Array.prototype.slice.call(arguments, 2);\n    if (!delayedCallbacks) {\n      ++delayedCallbackDepth;\n      delayedCallbacks = [];\n      setTimeout(fireDelayed, 0);\n    }\n    function bnd(f) {return function(){f.apply(null, args);};};\n    for (var i = 0; i < arr.length; ++i)\n      delayedCallbacks.push(bnd(arr[i]));\n  }\n\n  function signalDOMEvent(cm, e, override) {\n    signal(cm, override || e.type, cm, e);\n    return e_defaultPrevented(e) || e.codemirrorIgnore;\n  }\n\n  function fireDelayed() {\n    --delayedCallbackDepth;\n    var delayed = delayedCallbacks;\n    delayedCallbacks = null;\n    for (var i = 0; i < delayed.length; ++i) delayed[i]();\n  }\n\n  function hasHandler(emitter, type) {\n    var arr = emitter._handlers && emitter._handlers[type];\n    return arr && arr.length > 0;\n  }\n\n  CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;\n\n  function eventMixin(ctor) {\n    ctor.prototype.on = function(type, f) {on(this, type, f);};\n    ctor.prototype.off = function(type, f) {off(this, type, f);};\n  }\n\n  // MISC UTILITIES\n\n  // Number of pixels added to scroller and sizer to hide scrollbar\n  var scrollerCutOff = 30;\n\n  // Returned or thrown by various protocols to signal 'I'm not\n  // handling this'.\n  var Pass = CodeMirror.Pass = {toString: function(){return \"CodeMirror.Pass\";}};\n\n  function Delayed() {this.id = null;}\n  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};\n\n  // Counts the column offset in a string, taking tabs into account.\n  // Used mostly to find indentation.\n  function countColumn(string, end, tabSize, startIndex, startValue) {\n    if (end == null) {\n      end = string.search(/[^\\s\\u00a0]/);\n      if (end == -1) end = string.length;\n    }\n    for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {\n      if (string.charAt(i) == \"\\t\") n += tabSize - (n % tabSize);\n      else ++n;\n    }\n    return n;\n  }\n  CodeMirror.countColumn = countColumn;\n\n  var spaceStrs = [\"\"];\n  function spaceStr(n) {\n    while (spaceStrs.length <= n)\n      spaceStrs.push(lst(spaceStrs) + \" \");\n    return spaceStrs[n];\n  }\n\n  function lst(arr) { return arr[arr.length-1]; }\n\n  function selectInput(node) {\n    if (ios) { // Mobile Safari apparently has a bug where select() is broken.\n      node.selectionStart = 0;\n      node.selectionEnd = node.value.length;\n    } else {\n      // Suppress mysterious IE10 errors\n      try { node.select(); }\n      catch(_e) {}\n    }\n  }\n\n  function indexOf(collection, elt) {\n    if (collection.indexOf) return collection.indexOf(elt);\n    for (var i = 0, e = collection.length; i < e; ++i)\n      if (collection[i] == elt) return i;\n    return -1;\n  }\n\n  function createObj(base, props) {\n    function Obj() {}\n    Obj.prototype = base;\n    var inst = new Obj();\n    if (props) copyObj(props, inst);\n    return inst;\n  }\n\n  function copyObj(obj, target) {\n    if (!target) target = {};\n    for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];\n    return target;\n  }\n\n  function emptyArray(size) {\n    for (var a = [], i = 0; i < size; ++i) a.push(undefined);\n    return a;\n  }\n\n  function bind(f) {\n    var args = Array.prototype.slice.call(arguments, 1);\n    return function(){return f.apply(null, args);};\n  }\n\n  var nonASCIISingleCaseWordChar = /[\\u00df\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/;\n  function isWordChar(ch) {\n    return /\\w/.test(ch) || ch > \"\\x80\" &&\n      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));\n  }\n\n  function isEmpty(obj) {\n    for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;\n    return true;\n  }\n\n  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]/;\n  function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }\n\n  // DOM UTILITIES\n\n  function elt(tag, content, className, style) {\n    var e = document.createElement(tag);\n    if (className) e.className = className;\n    if (style) e.style.cssText = style;\n    if (typeof content == \"string\") setTextContent(e, content);\n    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);\n    return e;\n  }\n\n  function removeChildren(e) {\n    for (var count = e.childNodes.length; count > 0; --count)\n      e.removeChild(e.firstChild);\n    return e;\n  }\n\n  function removeChildrenAndAdd(parent, e) {\n    return removeChildren(parent).appendChild(e);\n  }\n\n  function setTextContent(e, str) {\n    if (ie_lt9) {\n      e.innerHTML = \"\";\n      e.appendChild(document.createTextNode(str));\n    } else e.textContent = str;\n  }\n\n  function getRect(node) {\n    return node.getBoundingClientRect();\n  }\n  CodeMirror.replaceGetRect = function(f) { getRect = f; };\n\n  // FEATURE DETECTION\n\n  // Detect drag-and-drop\n  var dragAndDrop = function() {\n    // There is *some* kind of drag-and-drop support in IE6-8, but I\n    // couldn't get it to work yet.\n    if (ie_lt9) return false;\n    var div = elt('div');\n    return \"draggable\" in div || \"dragDrop\" in div;\n  }();\n\n  // For a reason I have yet to figure out, some browsers disallow\n  // word wrapping between certain characters *only* if a new inline\n  // element is started between them. This makes it hard to reliably\n  // measure the position of things, since that requires inserting an\n  // extra span. This terribly fragile set of tests matches the\n  // character combinations that suffer from this phenomenon on the\n  // various browsers.\n  function spanAffectsWrapping() { return false; }\n  if (gecko) // Only for \"$'\"\n    spanAffectsWrapping = function(str, i) {\n      return str.charCodeAt(i - 1) == 36 && str.charCodeAt(i) == 39;\n    };\n  else if (safari && !/Version\\/([6-9]|\\d\\d)\\b/.test(navigator.userAgent))\n    spanAffectsWrapping = function(str, i) {\n      return /\\-[^ \\-?]|\\?[^ !\\'\\\"\\),.\\-\\/:;\\?\\]\\}]/.test(str.slice(i - 1, i + 1));\n    };\n  else if (webkit && /Chrome\\/(?:29|[3-9]\\d|\\d\\d\\d)\\./.test(navigator.userAgent))\n    spanAffectsWrapping = function(str, i) {\n      var code = str.charCodeAt(i - 1);\n      return code >= 8208 && code <= 8212;\n    };\n  else if (webkit)\n    spanAffectsWrapping = function(str, i) {\n      if (i > 1 && str.charCodeAt(i - 1) == 45) {\n        if (/\\w/.test(str.charAt(i - 2)) && /[^\\-?\\.]/.test(str.charAt(i))) return true;\n        if (i > 2 && /[\\d\\.,]/.test(str.charAt(i - 2)) && /[\\d\\.,]/.test(str.charAt(i))) return false;\n      }\n      return /[~!#%&*)=+}\\]\\\\|\\\"\\.>,:;][({[<]|-[^\\-?\\.\\u2010-\\u201f\\u2026]|\\?[\\w~`@#$%\\^&*(_=+{[|><]|\\u2026[\\w~`@#$%\\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));\n    };\n\n  var knownScrollbarWidth;\n  function scrollbarWidth(measure) {\n    if (knownScrollbarWidth != null) return knownScrollbarWidth;\n    var test = elt(\"div\", null, null, \"width: 50px; height: 50px; overflow-x: scroll\");\n    removeChildrenAndAdd(measure, test);\n    if (test.offsetWidth)\n      knownScrollbarWidth = test.offsetHeight - test.clientHeight;\n    return knownScrollbarWidth || 0;\n  }\n\n  var zwspSupported;\n  function zeroWidthElement(measure) {\n    if (zwspSupported == null) {\n      var test = elt(\"span\", \"\\u200b\");\n      removeChildrenAndAdd(measure, elt(\"span\", [test, document.createTextNode(\"x\")]));\n      if (measure.firstChild.offsetHeight != 0)\n        zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;\n    }\n    if (zwspSupported) return elt(\"span\", \"\\u200b\");\n    else return elt(\"span\", \"\\u00a0\", null, \"display: inline-block; width: 1px; margin-right: -1px\");\n  }\n\n  // See if \"\".split is the broken IE version, if so, provide an\n  // alternative way to split lines.\n  var splitLines = \"\\n\\nb\".split(/\\n/).length != 3 ? function(string) {\n    var pos = 0, result = [], l = string.length;\n    while (pos <= l) {\n      var nl = string.indexOf(\"\\n\", pos);\n      if (nl == -1) nl = string.length;\n      var line = string.slice(pos, string.charAt(nl - 1) == \"\\r\" ? nl - 1 : nl);\n      var rt = line.indexOf(\"\\r\");\n      if (rt != -1) {\n        result.push(line.slice(0, rt));\n        pos += rt + 1;\n      } else {\n        result.push(line);\n        pos = nl + 1;\n      }\n    }\n    return result;\n  } : function(string){return string.split(/\\r\\n?|\\n/);};\n  CodeMirror.splitLines = splitLines;\n\n  var hasSelection = window.getSelection ? function(te) {\n    try { return te.selectionStart != te.selectionEnd; }\n    catch(e) { return false; }\n  } : function(te) {\n    try {var range = te.ownerDocument.selection.createRange();}\n    catch(e) {}\n    if (!range || range.parentElement() != te) return false;\n    return range.compareEndPoints(\"StartToEnd\", range) != 0;\n  };\n\n  var hasCopyEvent = (function() {\n    var e = elt(\"div\");\n    if (\"oncopy\" in e) return true;\n    e.setAttribute(\"oncopy\", \"return;\");\n    return typeof e.oncopy == 'function';\n  })();\n\n  // KEY NAMING\n\n  var keyNames = {3: \"Enter\", 8: \"Backspace\", 9: \"Tab\", 13: \"Enter\", 16: \"Shift\", 17: \"Ctrl\", 18: \"Alt\",\n                  19: \"Pause\", 20: \"CapsLock\", 27: \"Esc\", 32: \"Space\", 33: \"PageUp\", 34: \"PageDown\", 35: \"End\",\n                  36: \"Home\", 37: \"Left\", 38: \"Up\", 39: \"Right\", 40: \"Down\", 44: \"PrintScrn\", 45: \"Insert\",\n                  46: \"Delete\", 59: \";\", 61: \"=\", 91: \"Mod\", 92: \"Mod\", 93: \"Mod\", 107: \"=\", 109: \"-\", 127: \"Delete\",\n                  173: \"-\", 186: \";\", 187: \"=\", 188: \",\", 189: \"-\", 190: \".\", 191: \"/\", 192: \"`\", 219: \"[\", 220: \"\\\\\",\n                  221: \"]\", 222: \"'\", 63232: \"Up\", 63233: \"Down\", 63234: \"Left\", 63235: \"Right\", 63272: \"Delete\",\n                  63273: \"Home\", 63275: \"End\", 63276: \"PageUp\", 63277: \"PageDown\", 63302: \"Insert\"};\n  CodeMirror.keyNames = keyNames;\n  (function() {\n    // Number keys\n    for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);\n    // Alphabetic keys\n    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);\n    // Function keys\n    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = \"F\" + i;\n  })();\n\n  // BIDI HELPERS\n\n  function iterateBidiSections(order, from, to, f) {\n    if (!order) return f(from, to, \"ltr\");\n    var found = false;\n    for (var i = 0; i < order.length; ++i) {\n      var part = order[i];\n      if (part.from < to && part.to > from || from == to && part.to == from) {\n        f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? \"rtl\" : \"ltr\");\n        found = true;\n      }\n    }\n    if (!found) f(from, to, \"ltr\");\n  }\n\n  function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }\n  function bidiRight(part) { return part.level % 2 ? part.from : part.to; }\n\n  function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }\n  function lineRight(line) {\n    var order = getOrder(line);\n    if (!order) return line.text.length;\n    return bidiRight(lst(order));\n  }\n\n  function lineStart(cm, lineN) {\n    var line = getLine(cm.doc, lineN);\n    var visual = visualLine(cm.doc, line);\n    if (visual != line) lineN = lineNo(visual);\n    var order = getOrder(visual);\n    var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);\n    return Pos(lineN, ch);\n  }\n  function lineEnd(cm, lineN) {\n    var merged, line;\n    while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))\n      lineN = merged.find().to.line;\n    var order = getOrder(line);\n    var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);\n    return Pos(lineN, ch);\n  }\n\n  function compareBidiLevel(order, a, b) {\n    var linedir = order[0].level;\n    if (a == linedir) return true;\n    if (b == linedir) return false;\n    return a < b;\n  }\n  var bidiOther;\n  function getBidiPartAt(order, pos) {\n    bidiOther = null;\n    for (var i = 0, found; i < order.length; ++i) {\n      var cur = order[i];\n      if (cur.from < pos && cur.to > pos) return i;\n      if ((cur.from == pos || cur.to == pos)) {\n        if (found == null) {\n          found = i;\n        } else if (compareBidiLevel(order, cur.level, order[found].level)) {\n          if (cur.from != cur.to) bidiOther = found;\n          return i;\n        } else {\n          if (cur.from != cur.to) bidiOther = i;\n          return found;\n        }\n      }\n    }\n    return found;\n  }\n\n  function moveInLine(line, pos, dir, byUnit) {\n    if (!byUnit) return pos + dir;\n    do pos += dir;\n    while (pos > 0 && isExtendingChar(line.text.charAt(pos)));\n    return pos;\n  }\n\n  // This is somewhat involved. It is needed in order to move\n  // 'visually' through bi-directional text -- i.e., pressing left\n  // should make the cursor go left, even when in RTL text. The\n  // tricky part is the 'jumps', where RTL and LTR text touch each\n  // other. This often requires the cursor offset to move more than\n  // one unit, in order to visually move one unit.\n  function moveVisually(line, start, dir, byUnit) {\n    var bidi = getOrder(line);\n    if (!bidi) return moveLogically(line, start, dir, byUnit);\n    var pos = getBidiPartAt(bidi, start), part = bidi[pos];\n    var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);\n\n    for (;;) {\n      if (target > part.from && target < part.to) return target;\n      if (target == part.from || target == part.to) {\n        if (getBidiPartAt(bidi, target) == pos) return target;\n        part = bidi[pos += dir];\n        return (dir > 0) == part.level % 2 ? part.to : part.from;\n      } else {\n        part = bidi[pos += dir];\n        if (!part) return null;\n        if ((dir > 0) == part.level % 2)\n          target = moveInLine(line, part.to, -1, byUnit);\n        else\n          target = moveInLine(line, part.from, 1, byUnit);\n      }\n    }\n  }\n\n  function moveLogically(line, start, dir, byUnit) {\n    var target = start + dir;\n    if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;\n    return target < 0 || target > line.text.length ? null : target;\n  }\n\n  // Bidirectional ordering algorithm\n  // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm\n  // that this (partially) implements.\n\n  // One-char codes used for character types:\n  // L (L):   Left-to-Right\n  // R (R):   Right-to-Left\n  // r (AL):  Right-to-Left Arabic\n  // 1 (EN):  European Number\n  // + (ES):  European Number Separator\n  // % (ET):  European Number Terminator\n  // n (AN):  Arabic Number\n  // , (CS):  Common Number Separator\n  // m (NSM): Non-Spacing Mark\n  // b (BN):  Boundary Neutral\n  // s (B):   Paragraph Separator\n  // t (S):   Segment Separator\n  // w (WS):  Whitespace\n  // N (ON):  Other Neutrals\n\n  // Returns null if characters are ordered as they appear\n  // (left-to-right), or an array of sections ({from, to, level}\n  // objects) in the order in which they occur visually.\n  var bidiOrdering = (function() {\n    // Character types for codepoints 0 to 0xff\n    var lowTypes = \"bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL\";\n    // Character types for codepoints 0x600 to 0x6ff\n    var arabicTypes = \"rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr\";\n    function charType(code) {\n      if (code <= 0xff) return lowTypes.charAt(code);\n      else if (0x590 <= code && code <= 0x5f4) return \"R\";\n      else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);\n      else if (0x700 <= code && code <= 0x8ac) return \"r\";\n      else return \"L\";\n    }\n\n    var bidiRE = /[\\u0590-\\u05f4\\u0600-\\u06ff\\u0700-\\u08ac]/;\n    var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;\n    // Browsers seem to always treat the boundaries of block elements as being L.\n    var outerType = \"L\";\n\n    return function(str) {\n      if (!bidiRE.test(str)) return false;\n      var len = str.length, types = [];\n      for (var i = 0, type; i < len; ++i)\n        types.push(type = charType(str.charCodeAt(i)));\n\n      // W1. Examine each non-spacing mark (NSM) in the level run, and\n      // change the type of the NSM to the type of the previous\n      // character. If the NSM is at the start of the level run, it will\n      // get the type of sor.\n      for (var i = 0, prev = outerType; i < len; ++i) {\n        var type = types[i];\n        if (type == \"m\") types[i] = prev;\n        else prev = type;\n      }\n\n      // W2. Search backwards from each instance of a European number\n      // until the first strong type (R, L, AL, or sor) is found. If an\n      // AL is found, change the type of the European number to Arabic\n      // number.\n      // W3. Change all ALs to R.\n      for (var i = 0, cur = outerType; i < len; ++i) {\n        var type = types[i];\n        if (type == \"1\" && cur == \"r\") types[i] = \"n\";\n        else if (isStrong.test(type)) { cur = type; if (type == \"r\") types[i] = \"R\"; }\n      }\n\n      // W4. A single European separator between two European numbers\n      // changes to a European number. A single common separator between\n      // two numbers of the same type changes to that type.\n      for (var i = 1, prev = types[0]; i < len - 1; ++i) {\n        var type = types[i];\n        if (type == \"+\" && prev == \"1\" && types[i+1] == \"1\") types[i] = \"1\";\n        else if (type == \",\" && prev == types[i+1] &&\n                 (prev == \"1\" || prev == \"n\")) types[i] = prev;\n        prev = type;\n      }\n\n      // W5. A sequence of European terminators adjacent to European\n      // numbers changes to all European numbers.\n      // W6. Otherwise, separators and terminators change to Other\n      // Neutral.\n      for (var i = 0; i < len; ++i) {\n        var type = types[i];\n        if (type == \",\") types[i] = \"N\";\n        else if (type == \"%\") {\n          for (var end = i + 1; end < len && types[end] == \"%\"; ++end) {}\n          var replace = (i && types[i-1] == \"!\") || (end < len && types[end] == \"1\") ? \"1\" : \"N\";\n          for (var j = i; j < end; ++j) types[j] = replace;\n          i = end - 1;\n        }\n      }\n\n      // W7. Search backwards from each instance of a European number\n      // until the first strong type (R, L, or sor) is found. If an L is\n      // found, then change the type of the European number to L.\n      for (var i = 0, cur = outerType; i < len; ++i) {\n        var type = types[i];\n        if (cur == \"L\" && type == \"1\") types[i] = \"L\";\n        else if (isStrong.test(type)) cur = type;\n      }\n\n      // N1. A sequence of neutrals takes the direction of the\n      // surrounding strong text if the text on both sides has the same\n      // direction. European and Arabic numbers act as if they were R in\n      // terms of their influence on neutrals. Start-of-level-run (sor)\n      // and end-of-level-run (eor) are used at level run boundaries.\n      // N2. Any remaining neutrals take the embedding direction.\n      for (var i = 0; i < len; ++i) {\n        if (isNeutral.test(types[i])) {\n          for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}\n          var before = (i ? types[i-1] : outerType) == \"L\";\n          var after = (end < len ? types[end] : outerType) == \"L\";\n          var replace = before || after ? \"L\" : \"R\";\n          for (var j = i; j < end; ++j) types[j] = replace;\n          i = end - 1;\n        }\n      }\n\n      // Here we depart from the documented algorithm, in order to avoid\n      // building up an actual levels array. Since there are only three\n      // levels (0, 1, 2) in an implementation that doesn't take\n      // explicit embedding into account, we can build up the order on\n      // the fly, without following the level-based algorithm.\n      var order = [], m;\n      for (var i = 0; i < len;) {\n        if (countsAsLeft.test(types[i])) {\n          var start = i;\n          for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}\n          order.push({from: start, to: i, level: 0});\n        } else {\n          var pos = i, at = order.length;\n          for (++i; i < len && types[i] != \"L\"; ++i) {}\n          for (var j = pos; j < i;) {\n            if (countsAsNum.test(types[j])) {\n              if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});\n              var nstart = j;\n              for (++j; j < i && countsAsNum.test(types[j]); ++j) {}\n              order.splice(at, 0, {from: nstart, to: j, level: 2});\n              pos = j;\n            } else ++j;\n          }\n          if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});\n        }\n      }\n      if (order[0].level == 1 && (m = str.match(/^\\s+/))) {\n        order[0].from = m[0].length;\n        order.unshift({from: 0, to: m[0].length, level: 0});\n      }\n      if (lst(order).level == 1 && (m = str.match(/\\s+$/))) {\n        lst(order).to -= m[0].length;\n        order.push({from: len - m[0].length, to: len, level: 0});\n      }\n      if (order[0].level != lst(order).level)\n        order.push({from: len, to: len, level: order[0].level});\n\n      return order;\n    };\n  })();\n\n  // THE END\n\n  CodeMirror.version = \"3.22.0\";\n\n  return CodeMirror;\n})();\n"
  },
  {
    "path": "client/js/lib/codemirror_javascript_mode.js",
    "content": "// TODO actually recognize syntax of TypeScript constructs\n\nCodeMirror.defineMode(\"javascript\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var statementIndent = parserConfig.statementIndent;\n  var jsonldMode = parserConfig.jsonld;\n  var jsonMode = parserConfig.json || jsonldMode;\n  var isTS = parserConfig.typescript;\n\n  // Tokenizer\n\n  var keywords = function(){\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\"), B = kw(\"keyword b\"), C = kw(\"keyword c\");\n    var operator = kw(\"operator\"), atom = {type: \"atom\", style: \"atom\"};\n\n    var jsKeywords = {\n      \"if\": kw(\"if\"), \"while\": A, \"with\": A, \"else\": B, \"do\": B, \"try\": B, \"finally\": B,\n      \"return\": C, \"break\": C, \"continue\": C, \"new\": C, \"delete\": C, \"throw\": C, \"debugger\": C,\n      \"var\": kw(\"var\"), \"const\": kw(\"var\"), \"let\": kw(\"var\"),\n      \"function\": kw(\"function\"), \"catch\": kw(\"catch\"),\n      \"for\": kw(\"for\"), \"switch\": kw(\"switch\"), \"case\": kw(\"case\"), \"default\": kw(\"default\"),\n      \"in\": operator, \"typeof\": operator, \"instanceof\": operator,\n      \"true\": atom, \"false\": atom, \"null\": atom, \"undefined\": atom, \"NaN\": atom, \"Infinity\": atom,\n      \"this\": kw(\"this\"), \"module\": kw(\"module\"), \"class\": kw(\"class\"), \"super\": kw(\"atom\"),\n      \"yield\": C, \"export\": kw(\"export\"), \"import\": kw(\"import\"), \"extends\": C\n    };\n\n    // Extend the 'normal' keywords with the TypeScript language extensions\n    if (isTS) {\n      var type = {type: \"variable\", style: \"variable-3\"};\n      var tsKeywords = {\n        // object-like things\n        \"interface\": kw(\"interface\"),\n        \"extends\": kw(\"extends\"),\n        \"constructor\": kw(\"constructor\"),\n\n        // scope modifiers\n        \"public\": kw(\"public\"),\n        \"private\": kw(\"private\"),\n        \"protected\": kw(\"protected\"),\n        \"static\": kw(\"static\"),\n\n        // types\n        \"string\": type, \"number\": type, \"bool\": type, \"any\": type\n      };\n\n      for (var attr in tsKeywords) {\n        jsKeywords[attr] = tsKeywords[attr];\n      }\n    }\n\n    return jsKeywords;\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|~^]/;\n  var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)\"/;\n\n  function readRegexp(stream) {\n    var escaped = false, next, inSet = false;\n    while ((next = stream.next()) != null) {\n      if (!escaped) {\n        if (next == \"/\" && !inSet) return;\n        if (next == \"[\") inSet = true;\n        else if (inSet && next == \"]\") inSet = false;\n      }\n      escaped = !escaped && next == \"\\\\\";\n    }\n  }\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    } else if (ch == \".\" && stream.match(/^\\d+(?:[eE][+\\-]?\\d+)?/)) {\n      return ret(\"number\", \"number\");\n    } else if (ch == \".\" && stream.match(\"..\")) {\n      return ret(\"spread\", \"meta\");\n    } else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      return ret(ch);\n    } else if (ch == \"=\" && stream.eat(\">\")) {\n      return ret(\"=>\", \"operator\");\n    } else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    } else if (/\\d/.test(ch)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    } else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      } else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      } else if (state.lastType == \"operator\" || state.lastType == \"keyword c\" ||\n               state.lastType == \"sof\" || /^[\\[{}\\(,;:]$/.test(state.lastType)) {\n        readRegexp(stream);\n        stream.eatWhile(/[gimy]/); // 'y' is \"sticky\" option in Mozilla\n        return ret(\"regexp\", \"string-2\");\n      } else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", \"operator\", stream.current());\n      }\n    } else if (ch == \"`\") {\n      state.tokenize = tokenQuasi;\n      return tokenQuasi(stream, state);\n    } else if (ch == \"#\") {\n      stream.skipToEnd();\n      return ret(\"error\", \"error\");\n    } else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", \"operator\", stream.current());\n    } else {\n      stream.eatWhile(/[\\w\\$_]/);\n      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n      return (known && state.lastType != \".\") ? ret(known.type, known.style, word) :\n                     ret(\"variable\", \"variable\", word);\n    }\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next;\n      if (jsonldMode && stream.peek() == \"@\" && stream.match(isJsonldKeyword)){\n        state.tokenize = tokenBase;\n        return ret(\"jsonld-keyword\", \"meta\");\n      }\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) break;\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenQuasi(stream, state) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (!escaped && (next == \"`\" || next == \"$\" && stream.eat(\"{\"))) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return ret(\"quasi\", \"string-2\", stream.current());\n  }\n\n  var brackets = \"([{}])\";\n  // This is a crude lookahead trick to try and notice that we're\n  // parsing the argument patterns for a fat-arrow function before we\n  // actually hit the arrow token. It only works if the arrow is on\n  // the same line as the arguments and there's no strange noise\n  // (comments) in between. Fallback is to only notice when we hit the\n  // arrow, and not declare the arguments as locals for the arrow\n  // body.\n  function findFatArrow(stream, state) {\n    if (state.fatArrowAt) state.fatArrowAt = null;\n    var arrow = stream.string.indexOf(\"=>\", stream.start);\n    if (arrow < 0) return;\n\n    var depth = 0, sawSomething = false;\n    for (var pos = arrow - 1; pos >= 0; --pos) {\n      var ch = stream.string.charAt(pos);\n      var bracket = brackets.indexOf(ch);\n      if (bracket >= 0 && bracket < 3) {\n        if (!depth) { ++pos; break; }\n        if (--depth == 0) break;\n      } else if (bracket >= 3 && bracket < 6) {\n        ++depth;\n      } else if (/[$\\w]/.test(ch)) {\n        sawSomething = true;\n      } else if (sawSomething && !depth) {\n        ++pos;\n        break;\n      }\n    }\n    if (sawSomething && !depth) state.fatArrowAt = pos;\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": true, \"this\": true, \"jsonld-keyword\": true};\n\n  function JSLexical(indented, column, type, align, prev, info) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.prev = prev;\n    this.info = info;\n    if (align != null) this.align = align;\n  }\n\n  function inScope(state, varname) {\n    for (var v = state.localVars; v; v = v.next)\n      if (v.name == varname) return true;\n    for (var cx = state.context; cx; cx = cx.prev) {\n      for (var v = cx.vars; v; v = v.next)\n        if (v.name == varname) return true;\n    }\n  }\n\n  function parseJS(state, style, type, content, stream) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;\n\n    if (!state.lexical.hasOwnProperty(\"align\"))\n      state.lexical.align = true;\n\n    while(true) {\n      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;\n      if (combinator(type, content)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        if (cx.marked) return cx.marked;\n        if (type == \"variable\" && inScope(state, content)) return \"variable-2\";\n        return style;\n      }\n    }\n  }\n\n  // Combinator utils\n\n  var cx = {state: null, column: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n  function register(varname) {\n    function inList(list) {\n      for (var v = list; v; v = v.next)\n        if (v.name == varname) return true;\n      return false;\n    }\n    var state = cx.state;\n    if (state.context) {\n      cx.marked = \"def\";\n      if (inList(state.localVars)) return;\n      state.localVars = {name: varname, next: state.localVars};\n    } else {\n      if (inList(state.globalVars)) return;\n      if (parserConfig.globalVars)\n        state.globalVars = {name: varname, next: state.globalVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: {name: \"arguments\"}};\n  function pushcontext() {\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\n    cx.state.localVars = defaultVars;\n  }\n  function popcontext() {\n    cx.state.localVars = cx.state.context.vars;\n    cx.state.context = cx.state.context.prev;\n  }\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state, indent = state.indented;\n      if (state.lexical.type == \"stat\") indent = state.lexical.indented;\n      state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  poplex.lex = true;\n\n  function expect(wanted) {\n    return function(type) {\n      if (type == wanted) return cont();\n      else if (wanted == \";\") return pass();\n      else return cont(arguments.callee);\n    };\n  }\n\n  function statement(type, value) {\n    if (type == \"var\") return cont(pushlex(\"vardef\", value.length), vardef, expect(\";\"), poplex);\n    if (type == \"keyword a\") return cont(pushlex(\"form\"), expression, statement, poplex);\n    if (type == \"keyword b\") return cont(pushlex(\"form\"), statement, poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    if (type == \";\") return cont();\n    if (type == \"if\") return cont(pushlex(\"form\"), expression, statement, poplex, maybeelse);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), forspec, statement, poplex);\n    if (type == \"variable\") return cont(pushlex(\"stat\"), maybelabel);\n    if (type == \"switch\") return cont(pushlex(\"form\"), expression, pushlex(\"}\", \"switch\"), expect(\"{\"),\n                                      block, poplex, poplex);\n    if (type == \"case\") return cont(expression, expect(\":\"));\n    if (type == \"default\") return cont(expect(\":\"));\n    if (type == \"catch\") return cont(pushlex(\"form\"), pushcontext, expect(\"(\"), funarg, expect(\")\"),\n                                     statement, poplex, popcontext);\n    if (type == \"module\") return cont(pushlex(\"form\"), pushcontext, afterModule, popcontext, poplex);\n    if (type == \"class\") return cont(pushlex(\"form\"), className, objlit, poplex);\n    if (type == \"export\") return cont(pushlex(\"form\"), afterExport, poplex);\n    if (type == \"import\") return cont(pushlex(\"form\"), afterImport, poplex);\n    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    return expressionInner(type, false);\n  }\n  function expressionNoComma(type) {\n    return expressionInner(type, true);\n  }\n  function expressionInner(type, noComma) {\n    if (cx.state.fatArrowAt == cx.stream.start) {\n      var body = noComma ? arrowBodyNoComma : arrowBody;\n      if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(pattern, \")\"), poplex, expect(\"=>\"), body, popcontext);\n      else if (type == \"variable\") return pass(pushcontext, pattern, expect(\"=>\"), body, popcontext);\n    }\n\n    var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"keyword c\") return cont(noComma ? maybeexpressionNoComma : maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, comprehension, expect(\")\"), poplex, maybeop);\n    if (type == \"operator\" || type == \"spread\") return cont(noComma ? expressionNoComma : expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), arrayLiteral, poplex, maybeop);\n    if (type == \"{\") return contCommasep(objprop, \"}\", null, maybeop);\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n  function maybeexpressionNoComma(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expressionNoComma);\n  }\n\n  function maybeoperatorComma(type, value) {\n    if (type == \",\") return cont(expression);\n    return maybeoperatorNoComma(type, value, false);\n  }\n  function maybeoperatorNoComma(type, value, noComma) {\n    var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;\n    var expr = noComma == false ? expression : expressionNoComma;\n    if (value == \"=>\") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);\n    if (type == \"operator\") {\n      if (/\\+\\+|--/.test(value)) return cont(me);\n      if (value == \"?\") return cont(expression, expect(\":\"), expr);\n      return cont(expr);\n    }\n    if (type == \"quasi\") { cx.cc.push(me); return quasi(value); }\n    if (type == \";\") return;\n    if (type == \"(\") return contCommasep(expressionNoComma, \")\", \"call\", me);\n    if (type == \".\") return cont(property, me);\n    if (type == \"[\") return cont(pushlex(\"]\"), maybeexpression, expect(\"]\"), poplex, me);\n  }\n  function quasi(value) {\n    if (value.slice(value.length - 2) != \"${\") return cont();\n    return cont(expression, continueQuasi);\n  }\n  function continueQuasi(type) {\n    if (type == \"}\") {\n      cx.marked = \"string-2\";\n      cx.state.tokenize = tokenQuasi;\n      return cont();\n    }\n  }\n  function arrowBody(type) {\n    findFatArrow(cx.stream, cx.state);\n    if (type == \"{\") return pass(statement);\n    return pass(expression);\n  }\n  function arrowBodyNoComma(type) {\n    findFatArrow(cx.stream, cx.state);\n    if (type == \"{\") return pass(statement);\n    return pass(expressionNoComma);\n  }\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperatorComma, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type, value) {\n    if (type == \"variable\") {\n      cx.marked = \"property\";\n      if (value == \"get\" || value == \"set\") return cont(getterSetter);\n    } else if (type == \"number\" || type == \"string\") {\n      cx.marked = jsonldMode ? \"property\" : (type + \" property\");\n    } else if (type == \"[\") {\n      return cont(expression, expect(\"]\"), afterprop);\n    }\n    if (atomicTypes.hasOwnProperty(type)) return cont(afterprop);\n  }\n  function getterSetter(type) {\n    if (type != \"variable\") return pass(afterprop);\n    cx.marked = \"property\";\n    return cont(functiondef);\n  }\n  function afterprop(type) {\n    if (type == \":\") return cont(expressionNoComma);\n    if (type == \"(\") return pass(functiondef);\n  }\n  function commasep(what, end) {\n    function proceed(type) {\n      if (type == \",\") {\n        var lex = cx.state.lexical;\n        if (lex.info == \"call\") lex.pos = (lex.pos || 0) + 1;\n        return cont(what, proceed);\n      }\n      if (type == end) return cont();\n      return cont(expect(end));\n    }\n    return function(type) {\n      if (type == end) return cont();\n      return pass(what, proceed);\n    };\n  }\n  function contCommasep(what, end, info) {\n    for (var i = 3; i < arguments.length; i++)\n      cx.cc.push(arguments[i]);\n    return cont(pushlex(end, info), commasep(what, end), poplex);\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function maybetype(type) {\n    if (isTS && type == \":\") return cont(typedef);\n  }\n  function typedef(type) {\n    if (type == \"variable\"){cx.marked = \"variable-3\"; return cont();}\n  }\n  function vardef() {\n    return pass(pattern, maybetype, maybeAssign, vardefCont);\n  }\n  function pattern(type, value) {\n    if (type == \"variable\") { register(value); return cont(); }\n    if (type == \"[\") return contCommasep(pattern, \"]\");\n    if (type == \"{\") return contCommasep(proppattern, \"}\");\n  }\n  function proppattern(type, value) {\n    if (type == \"variable\" && !cx.stream.match(/^\\s*:/, false)) {\n      register(value);\n      return cont(maybeAssign);\n    }\n    if (type == \"variable\") cx.marked = \"property\";\n    return cont(expect(\":\"), pattern, maybeAssign);\n  }\n  function maybeAssign(_type, value) {\n    if (value == \"=\") return cont(expressionNoComma);\n  }\n  function vardefCont(type) {\n    if (type == \",\") return cont(vardef);\n  }\n  function maybeelse(type, value) {\n    if (type == \"keyword b\" && value == \"else\") return cont(pushlex(\"form\"), statement, poplex);\n  }\n  function forspec(type) {\n    if (type == \"(\") return cont(pushlex(\")\"), forspec1, expect(\")\"), poplex);\n  }\n  function forspec1(type) {\n    if (type == \"var\") return cont(vardef, expect(\";\"), forspec2);\n    if (type == \";\") return cont(forspec2);\n    if (type == \"variable\") return cont(formaybeinof);\n    return pass(expression, expect(\";\"), forspec2);\n  }\n  function formaybeinof(_type, value) {\n    if (value == \"in\" || value == \"of\") { cx.marked = \"keyword\"; return cont(expression); }\n    return cont(maybeoperatorComma, forspec2);\n  }\n  function forspec2(type, value) {\n    if (type == \";\") return cont(forspec3);\n    if (value == \"in\" || value == \"of\") { cx.marked = \"keyword\"; return cont(expression); }\n    return pass(expression, expect(\";\"), forspec3);\n  }\n  function forspec3(type) {\n    if (type != \")\") cont(expression);\n  }\n  function functiondef(type, value) {\n    if (value == \"*\") {cx.marked = \"keyword\"; return cont(functiondef);}\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(funarg, \")\"), poplex, statement, popcontext);\n  }\n  function funarg(type) {\n    if (type == \"spread\") return cont(funarg);\n    return pass(pattern, maybetype);\n  }\n  function className(type, value) {\n    if (type == \"variable\") {register(value); return cont(classNameAfter);}\n  }\n  function classNameAfter(_type, value) {\n    if (value == \"extends\") return cont(expression);\n  }\n  function objlit(type) {\n    if (type == \"{\") return contCommasep(objprop, \"}\");\n  }\n  function afterModule(type, value) {\n    if (type == \"string\") return cont(statement);\n    if (type == \"variable\") { register(value); return cont(maybeFrom); }\n  }\n  function afterExport(_type, value) {\n    if (value == \"*\") { cx.marked = \"keyword\"; return cont(maybeFrom, expect(\";\")); }\n    if (value == \"default\") { cx.marked = \"keyword\"; return cont(expression, expect(\";\")); }\n    return pass(statement);\n  }\n  function afterImport(type) {\n    if (type == \"string\") return cont();\n    return pass(importSpec, maybeFrom);\n  }\n  function importSpec(type, value) {\n    if (type == \"{\") return contCommasep(importSpec, \"}\");\n    if (type == \"variable\") register(value);\n    return cont();\n  }\n  function maybeFrom(_type, value) {\n    if (value == \"from\") { cx.marked = \"keyword\"; return cont(expression); }\n  }\n  function arrayLiteral(type) {\n    if (type == \"]\") return cont();\n    return pass(expressionNoComma, maybeArrayComprehension);\n  }\n  function maybeArrayComprehension(type) {\n    if (type == \"for\") return pass(comprehension, expect(\"]\"));\n    if (type == \",\") return cont(commasep(expressionNoComma, \"]\"));\n    return pass(commasep(expressionNoComma, \"]\"));\n  }\n  function comprehension(type) {\n    if (type == \"for\") return cont(forspec, comprehension);\n    if (type == \"if\") return cont(expression, comprehension);\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      var state = {\n        tokenize: tokenBase,\n        lastType: \"sof\",\n        cc: [],\n        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, \"block\", false),\n        localVars: parserConfig.localVars,\n        context: parserConfig.localVars && {vars: parserConfig.localVars},\n        indented: 0\n      };\n      if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;\n      return state;\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n        findFatArrow(stream, state);\n      }\n      if (state.tokenize != tokenComment && stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.lastType = type == \"operator\" && (content == \"++\" || content == \"--\") ? \"incdec\" : type;\n      return parseJS(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize == tokenComment) return CodeMirror.Pass;\n      if (state.tokenize != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;\n      // Kludge to prevent 'maybelse' from blocking lexical scope pops\n      for (var i = state.cc.length - 1; i >= 0; --i) {\n        var c = state.cc[i];\n        if (c == poplex) lexical = lexical.prev;\n        else if (c != maybeelse) break;\n      }\n      if (lexical.type == \"stat\" && firstChar == \"}\") lexical = lexical.prev;\n      if (statementIndent && lexical.type == \")\" && lexical.prev.type == \"stat\")\n        lexical = lexical.prev;\n      var type = lexical.type, closing = firstChar == type;\n\n      if (type == \"vardef\") return lexical.indented + (state.lastType == \"operator\" || state.lastType == \",\" ? lexical.info + 1 : 0);\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"form\") return lexical.indented + indentUnit;\n      else if (type == \"stat\")\n        return lexical.indented + (state.lastType == \"operator\" || state.lastType == \",\" ? statementIndent || indentUnit : 0);\n      else if (lexical.info == \"switch\" && !closing && parserConfig.doubleIndentSwitch != false)\n        return lexical.indented + (/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 2 * indentUnit);\n      else if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      else return lexical.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \":{}\",\n    blockCommentStart: jsonMode ? null : \"/*\",\n    blockCommentEnd: jsonMode ? null : \"*/\",\n    lineComment: jsonMode ? null : \"//\",\n    fold: \"brace\",\n\n    helperType: jsonMode ? \"json\" : \"javascript\",\n    jsonldMode: jsonldMode,\n    jsonMode: jsonMode\n  };\n});\n\nCodeMirror.defineMIME(\"text/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"text/ecmascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/ecmascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/json\", {name: \"javascript\", json: true});\nCodeMirror.defineMIME(\"application/x-json\", {name: \"javascript\", json: true});\nCodeMirror.defineMIME(\"application/ld+json\", {name: \"javascript\", jsonld: true});\nCodeMirror.defineMIME(\"text/typescript\", { name: \"javascript\", typescript: true });\nCodeMirror.defineMIME(\"application/typescript\", { name: \"javascript\", typescript: true });\n"
  },
  {
    "path": "client/js/lib/ui-bootstrap-tpls-0.3.0.js",
    "content": "angular.module(\"ui.bootstrap\", [\"ui.bootstrap.tpls\", \"ui.bootstrap.transition\",\"ui.bootstrap.collapse\",\"ui.bootstrap.accordion\",\"ui.bootstrap.alert\",\"ui.bootstrap.buttons\",\"ui.bootstrap.carousel\",\"ui.bootstrap.dialog\",\"ui.bootstrap.dropdownToggle\",\"ui.bootstrap.modal\",\"ui.bootstrap.pagination\",\"ui.bootstrap.position\",\"ui.bootstrap.tooltip\",\"ui.bootstrap.popover\",\"ui.bootstrap.progressbar\",\"ui.bootstrap.rating\",\"ui.bootstrap.tabs\",\"ui.bootstrap.typeahead\"]);\nangular.module(\"ui.bootstrap.tpls\", [\"template/accordion/accordion-group.html\",\"template/accordion/accordion.html\",\"template/alert/alert.html\",\"template/carousel/carousel.html\",\"template/carousel/slide.html\",\"template/dialog/message.html\",\"template/pagination/pagination.html\",\"template/tooltip/tooltip-html-unsafe-popup.html\",\"template/tooltip/tooltip-popup.html\",\"template/popover/popover.html\",\"template/progressbar/bar.html\",\"template/progressbar/progress.html\",\"template/rating/rating.html\",\"template/tabs/pane.html\",\"template/tabs/tabs.html\",\"template/typeahead/typeahead.html\"]);\nangular.module('ui.bootstrap.transition', [])\n\n/**\n * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.\n * @param  {DOMElement} element  The DOMElement that will be animated.\n * @param  {string|object|function} trigger  The thing that will cause the transition to start:\n *   - As a string, it represents the css class to be added to the element.\n *   - As an object, it represents a hash of style attributes to be applied to the element.\n *   - As a function, it represents a function to be called that will cause the transition to occur.\n * @return {Promise}  A promise that is resolved when the transition finishes.\n */\n.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {\n\n  var $transition = function(element, trigger, options) {\n    options = options || {};\n    var deferred = $q.defer();\n    var endEventName = $transition[options.animation ? \"animationEndEventName\" : \"transitionEndEventName\"];\n\n    var transitionEndHandler = function(event) {\n      $rootScope.$apply(function() {\n        element.unbind(endEventName, transitionEndHandler);\n        deferred.resolve(element);\n      });\n    };\n\n    if (endEventName) {\n      element.bind(endEventName, transitionEndHandler);\n    }\n\n    // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur\n    $timeout(function() {\n      if ( angular.isString(trigger) ) {\n        element.addClass(trigger);\n      } else if ( angular.isFunction(trigger) ) {\n        trigger(element);\n      } else if ( angular.isObject(trigger) ) {\n        element.css(trigger);\n      }\n      //If browser does not support transitions, instantly resolve\n      if ( !endEventName ) {\n        deferred.resolve(element);\n      }\n    });\n\n    // Add our custom cancel function to the promise that is returned\n    // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,\n    // i.e. it will therefore never raise a transitionEnd event for that transition\n    deferred.promise.cancel = function() {\n      if ( endEventName ) {\n        element.unbind(endEventName, transitionEndHandler);\n      }\n      deferred.reject('Transition cancelled');\n    };\n\n    return deferred.promise;\n  };\n\n  // Work out the name of the transitionEnd event\n  var transElement = document.createElement('trans');\n  var transitionEndEventNames = {\n    'WebkitTransition': 'webkitTransitionEnd',\n    'MozTransition': 'transitionend',\n    'OTransition': 'oTransitionEnd',\n    'transition': 'transitionend'\n  };\n  var animationEndEventNames = {\n    'WebkitTransition': 'webkitAnimationEnd',\n    'MozTransition': 'animationend',\n    'OTransition': 'oAnimationEnd',\n    'transition': 'animationend'\n  };\n  function findEndEventName(endEventNames) {\n    for (var name in endEventNames){\n      if (transElement.style[name] !== undefined) {\n        return endEventNames[name];\n      }\n    }\n  }\n  $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);\n  $transition.animationEndEventName = findEndEventName(animationEndEventNames);\n  return $transition;\n}]);\n\nangular.module('ui.bootstrap.collapse',['ui.bootstrap.transition'])\n\n// The collapsible directive indicates a block of html that will expand and collapse\n.directive('collapse', ['$transition', function($transition) {\n  // CSS transitions don't work with height: auto, so we have to manually change the height to a\n  // specific value and then once the animation completes, we can reset the height to auto.\n  // Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class\n  // \"collapse\") then you trigger a change to height 0 in between.\n  // The fix is to remove the \"collapse\" CSS class while changing the height back to auto - phew!\n  var fixUpHeight = function(scope, element, height) {\n    // We remove the collapse CSS class to prevent a transition when we change to height: auto\n    element.removeClass('collapse');\n    element.css({ height: height });\n    // It appears that  reading offsetWidth makes the browser realise that we have changed the\n    // height already :-/\n    var x = element[0].offsetWidth;\n    element.addClass('collapse');\n  };\n\n  return {\n    link: function(scope, element, attrs) {\n\n      var isCollapsed;\n      var initialAnimSkip = true;\n      scope.$watch(function (){ return element[0].scrollHeight; }, function (value) {\n        //The listener is called when scollHeight changes\n        //It actually does on 2 scenarios: \n        // 1. Parent is set to display none\n        // 2. angular bindings inside are resolved\n        //When we have a change of scrollHeight we are setting again the correct height if the group is opened\n        if (element[0].scrollHeight !== 0) {\n          if (!isCollapsed) {\n            if (initialAnimSkip) {\n              fixUpHeight(scope, element, element[0].scrollHeight + 'px');\n            } else {\n              fixUpHeight(scope, element, 'auto');\n            }\n          }\n        }\n      });\n      \n      scope.$watch(attrs.collapse, function(value) {\n        if (value) {\n          collapse();\n        } else {\n          expand();\n        }\n      });\n      \n\n      var currentTransition;\n      var doTransition = function(change) {\n        if ( currentTransition ) {\n          currentTransition.cancel();\n        }\n        currentTransition = $transition(element,change);\n        currentTransition.then(\n          function() { currentTransition = undefined; },\n          function() { currentTransition = undefined; }\n        );\n        return currentTransition;\n      };\n\n      var expand = function() {\n        if (initialAnimSkip) {\n          initialAnimSkip = false;\n          if ( !isCollapsed ) {\n            fixUpHeight(scope, element, 'auto');\n          }\n        } else {\n          doTransition({ height : element[0].scrollHeight + 'px' })\n          .then(function() {\n            // This check ensures that we don't accidentally update the height if the user has closed\n            // the group while the animation was still running\n            if ( !isCollapsed ) {\n              fixUpHeight(scope, element, 'auto');\n            }\n          });\n        }\n        isCollapsed = false;\n      };\n      \n      var collapse = function() {\n        isCollapsed = true;\n        if (initialAnimSkip) {\n          initialAnimSkip = false;\n          fixUpHeight(scope, element, 0);\n        } else {\n          fixUpHeight(scope, element, element[0].scrollHeight + 'px');\n          doTransition({'height':'0'});\n        }\n      };\n    }\n  };\n}]);\n\nangular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])\n\n.constant('accordionConfig', {\n  closeOthers: true\n})\n\n.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) {\n  \n  // This array keeps track of the accordion groups\n  this.groups = [];\n\n  // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to\n  this.closeOthers = function(openGroup) {\n    var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;\n    if ( closeOthers ) {\n      angular.forEach(this.groups, function (group) {\n        if ( group !== openGroup ) {\n          group.isOpen = false;\n        }\n      });\n    }\n  };\n  \n  // This is called from the accordion-group directive to add itself to the accordion\n  this.addGroup = function(groupScope) {\n    var that = this;\n    this.groups.push(groupScope);\n\n    groupScope.$on('$destroy', function (event) {\n      that.removeGroup(groupScope);\n    });\n  };\n\n  // This is called from the accordion-group directive when to remove itself\n  this.removeGroup = function(group) {\n    var index = this.groups.indexOf(group);\n    if ( index !== -1 ) {\n      this.groups.splice(this.groups.indexOf(group), 1);\n    }\n  };\n\n}])\n\n// The accordion directive simply sets up the directive controller\n// and adds an accordion CSS class to itself element.\n.directive('accordion', function () {\n  return {\n    restrict:'EA',\n    controller:'AccordionController',\n    transclude: true,\n    replace: false,\n    templateUrl: 'template/accordion/accordion.html'\n  };\n})\n\n// The accordion-group directive indicates a block of html that will expand and collapse in an accordion\n.directive('accordionGroup', ['$parse', '$transition', '$timeout', function($parse, $transition, $timeout) {\n  return {\n    require:'^accordion',         // We need this directive to be inside an accordion\n    restrict:'EA',\n    transclude:true,              // It transcludes the contents of the directive into the template\n    replace: true,                // The element containing the directive will be replaced with the template\n    templateUrl:'template/accordion/accordion-group.html',\n    scope:{ heading:'@' },        // Create an isolated scope and interpolate the heading attribute onto this scope\n    controller: ['$scope', function($scope) {\n      this.setHeading = function(element) {\n        this.heading = element;\n      };\n    }],\n    link: function(scope, element, attrs, accordionCtrl) {\n      var getIsOpen, setIsOpen;\n\n      accordionCtrl.addGroup(scope);\n\n      scope.isOpen = false;\n      \n      if ( attrs.isOpen ) {\n        getIsOpen = $parse(attrs.isOpen);\n        setIsOpen = getIsOpen.assign;\n\n        scope.$watch(\n          function watchIsOpen() { return getIsOpen(scope.$parent); },\n          function updateOpen(value) { scope.isOpen = value; }\n        );\n        \n        scope.isOpen = getIsOpen ? getIsOpen(scope.$parent) : false;\n      }\n\n      scope.$watch('isOpen', function(value) {\n        if ( value ) {\n          accordionCtrl.closeOthers(scope);\n        }\n        if ( setIsOpen ) {\n          setIsOpen(scope.$parent, value);\n        }\n      });\n    }\n  };\n}])\n\n// Use accordion-heading below an accordion-group to provide a heading containing HTML\n// <accordion-group>\n//   <accordion-heading>Heading containing HTML - <img src=\"...\"></accordion-heading>\n// </accordion-group>\n.directive('accordionHeading', function() {\n  return {\n    restrict: 'E',\n    transclude: true,   // Grab the contents to be used as the heading\n    template: '',       // In effect remove this element!\n    replace: true,\n    require: '^accordionGroup',\n    compile: function(element, attr, transclude) {\n      return function link(scope, element, attr, accordionGroupCtrl) {\n        // Pass the heading to the accordion-group controller\n        // so that it can be transcluded into the right place in the template\n        // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]\n        accordionGroupCtrl.setHeading(transclude(scope, function() {}));\n      };\n    }\n  };\n})\n\n// Use in the accordion-group template to indicate where you want the heading to be transcluded\n// You must provide the property on the accordion-group controller that will hold the transcluded element\n// <div class=\"accordion-group\">\n//   <div class=\"accordion-heading\" ><a ... accordion-transclude=\"heading\">...</a></div>\n//   ...\n// </div>\n.directive('accordionTransclude', function() {\n  return {\n    require: '^accordionGroup',\n    link: function(scope, element, attr, controller) {\n      scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {\n        if ( heading ) {\n          element.html('');\n          element.append(heading);\n        }\n      });\n    }\n  };\n});\n\nangular.module(\"ui.bootstrap.alert\", []).directive('alert', function () {\n  return {\n    restrict:'EA',\n    templateUrl:'template/alert/alert.html',\n    transclude:true,\n    replace:true,\n    scope: {\n      type: '=',\n      close: '&'\n    },\n    link: function(scope, iElement, iAttrs, controller) {\n      scope.closeable = \"close\" in iAttrs;\n    }\n  };\n});\n\nangular.module('ui.bootstrap.buttons', [])\n\n  .constant('buttonConfig', {\n    activeClass:'active',\n    toggleEvent:'click'\n  })\n\n  .directive('btnRadio', ['buttonConfig', function (buttonConfig) {\n  var activeClass = buttonConfig.activeClass || 'active';\n  var toggleEvent = buttonConfig.toggleEvent || 'click';\n\n  return {\n\n    require:'ngModel',\n    link:function (scope, element, attrs, ngModelCtrl) {\n\n      var value = scope.$eval(attrs.btnRadio);\n\n      //model -> UI\n      scope.$watch(function () {\n        return ngModelCtrl.$modelValue;\n      }, function (modelValue) {\n        if (angular.equals(modelValue, value)){\n          element.addClass(activeClass);\n        } else {\n          element.removeClass(activeClass);\n        }\n      });\n\n      //ui->model\n      element.bind(toggleEvent, function () {\n        if (!element.hasClass(activeClass)) {\n          scope.$apply(function () {\n            ngModelCtrl.$setViewValue(value);\n          });\n        }\n      });\n    }\n  };\n}])\n\n  .directive('btnCheckbox', ['buttonConfig', function (buttonConfig) {\n\n  var activeClass = buttonConfig.activeClass || 'active';\n  var toggleEvent = buttonConfig.toggleEvent || 'click';\n\n  return {\n    require:'ngModel',\n    link:function (scope, element, attrs, ngModelCtrl) {\n\n      var trueValue = scope.$eval(attrs.btnCheckboxTrue);\n      var falseValue = scope.$eval(attrs.btnCheckboxFalse);\n\n      trueValue = angular.isDefined(trueValue) ? trueValue : true;\n      falseValue = angular.isDefined(falseValue) ? falseValue : false;\n\n      //model -> UI\n      scope.$watch(function () {\n        return ngModelCtrl.$modelValue;\n      }, function (modelValue) {\n        if (angular.equals(modelValue, trueValue)) {\n          element.addClass(activeClass);\n        } else {\n          element.removeClass(activeClass);\n        }\n      });\n\n      //ui->model\n      element.bind(toggleEvent, function () {\n        scope.$apply(function () {\n          ngModelCtrl.$setViewValue(element.hasClass(activeClass) ? falseValue : trueValue);\n        });\n      });\n    }\n  };\n}]);\n/*\n*\n*    AngularJS Bootstrap Carousel \n*\n*      A pure AngularJS carousel.\n*      \n*      For no interval set the interval to non-number, or milliseconds of desired interval\n*      Template: <carousel interval=\"none\"><slide>{{anything}}</slide></carousel>\n*      To change the carousel's active slide set the active attribute to true\n*      Template: <carousel interval=\"none\"><slide active=\"someModel\">{{anything}}</slide></carousel>\n*/\nangular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])\n.controller('CarouselController', ['$scope', '$timeout', '$transition', '$q', function ($scope, $timeout, $transition, $q) {\n  var self = this,\n    slides = self.slides = [],\n    currentIndex = -1,\n    currentTimeout, isPlaying;\n  self.currentSlide = null;\n\n  /* direction: \"prev\" or \"next\" */\n  self.select = function(nextSlide, direction) {\n    var nextIndex = slides.indexOf(nextSlide);\n    //Decide direction if it's not given\n    if (direction === undefined) {\n      direction = nextIndex > currentIndex ? \"next\" : \"prev\";\n    }\n    if (nextSlide && nextSlide !== self.currentSlide) {\n      if ($scope.$currentTransition) {\n        $scope.$currentTransition.cancel();\n        //Timeout so ng-class in template has time to fix classes for finished slide\n        $timeout(goNext);\n      } else {\n        goNext();\n      }\n    }\n    function goNext() {\n      //If we have a slide to transition from and we have a transition type and we're allowed, go\n      if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { \n        //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime\n        nextSlide.$element.addClass(direction);\n        nextSlide.$element[0].offsetWidth = nextSlide.$element[0].offsetWidth; //force reflow\n\n        //Set all other slides to stop doing their stuff for the new transition\n        angular.forEach(slides, function(slide) {\n          angular.extend(slide, {direction: '', entering: false, leaving: false, active: false});\n        });\n        angular.extend(nextSlide, {direction: direction, active: true, entering: true});\n        angular.extend(self.currentSlide||{}, {direction: direction, leaving: true});\n\n        $scope.$currentTransition = $transition(nextSlide.$element, {});\n        //We have to create new pointers inside a closure since next & current will change\n        (function(next,current) {\n          $scope.$currentTransition.then(\n            function(){ transitionDone(next, current); },\n            function(){ transitionDone(next, current); }\n          );\n        }(nextSlide, self.currentSlide));\n      } else {\n        transitionDone(nextSlide, self.currentSlide);\n      }\n      self.currentSlide = nextSlide;\n      currentIndex = nextIndex;\n      //every time you change slides, reset the timer\n      restartTimer();\n    }\n    function transitionDone(next, current) {\n      angular.extend(next, {direction: '', active: true, leaving: false, entering: false});\n      angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false});\n      $scope.$currentTransition = null;\n    }\n  };\n\n  /* Allow outside people to call indexOf on slides array */\n  self.indexOfSlide = function(slide) {\n    return slides.indexOf(slide);\n  };\n\n  $scope.next = function() {\n    var newIndex = (currentIndex + 1) % slides.length;\n    return self.select(slides[newIndex], 'next');\n  };\n\n  $scope.prev = function() {\n    var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1;\n    return self.select(slides[newIndex], 'prev');\n  };\n\n  $scope.select = function(slide) {\n    self.select(slide);\n  };\n\n  $scope.isActive = function(slide) {\n     return self.currentSlide === slide;\n  };\n\n  $scope.slides = function() {\n    return slides;\n  };\n\n  $scope.$watch('interval', restartTimer);\n  function restartTimer() {\n    if (currentTimeout) {\n      $timeout.cancel(currentTimeout);\n    }\n    function go() {\n      if (isPlaying) {\n        $scope.next();\n        restartTimer();\n      } else {\n        $scope.pause();\n      }\n    }\n    var interval = +$scope.interval;\n    if (!isNaN(interval) && interval>=0) {\n      currentTimeout = $timeout(go, interval);\n    }\n  }\n  $scope.play = function() {\n    if (!isPlaying) {\n      isPlaying = true;\n      restartTimer();\n    }\n  };\n  $scope.pause = function() {\n    isPlaying = false;\n    if (currentTimeout) {\n      $timeout.cancel(currentTimeout);\n    }\n  };\n\n  self.addSlide = function(slide, element) {\n    slide.$element = element;\n    slides.push(slide);\n    //if this is the first slide or the slide is set to active, select it\n    if(slides.length === 1 || slide.active) {\n      self.select(slides[slides.length-1]);\n      if (slides.length == 1) {\n        $scope.play();\n      }\n    } else {\n      slide.active = false;\n    }\n  };\n\n  self.removeSlide = function(slide) {\n    //get the index of the slide inside the carousel\n    var index = slides.indexOf(slide);\n    slides.splice(index, 1);\n    if (slides.length > 0 && slide.active) {\n      if (index >= slides.length) {\n        self.select(slides[index-1]);\n      } else {\n        self.select(slides[index]);\n      }\n    }\n  };\n}])\n.directive('carousel', [function() {\n  return {\n    restrict: 'EA',\n    transclude: true,\n    replace: true,\n    controller: 'CarouselController',\n    require: 'carousel',\n    templateUrl: 'template/carousel/carousel.html',\n    scope: {\n      interval: '=',\n      noTransition: '='\n    }\n  };\n}])\n.directive('slide', [function() {\n  return {\n    require: '^carousel',\n    restrict: 'EA',\n    transclude: true,\n    replace: true,\n    templateUrl: 'template/carousel/slide.html',\n    scope: {\n      active: '='\n    },\n    link: function (scope, element, attrs, carouselCtrl) {\n      carouselCtrl.addSlide(scope, element);\n      //when the scope is destroyed then remove the slide from the current slides array\n      scope.$on('$destroy', function() {\n        carouselCtrl.removeSlide(scope);\n      });\n\n      scope.$watch('active', function(active) {\n        if (active) {\n          carouselCtrl.select(scope);\n        }\n      });\n    }\n  };\n}]);\n\n// The `$dialogProvider` can be used to configure global defaults for your\n// `$dialog` service.\nvar dialogModule = angular.module('ui.bootstrap.dialog', ['ui.bootstrap.transition']);\n\ndialogModule.controller('MessageBoxController', ['$scope', 'dialog', 'model', function($scope, dialog, model){\n  $scope.title = model.title;\n  $scope.message = model.message;\n  $scope.buttons = model.buttons;\n  $scope.close = function(res){\n    dialog.close(res);\n  };\n}]);\n\ndialogModule.provider(\"$dialog\", function(){\n\n  // The default options for all dialogs.\n  var defaults = {\n    backdrop: true,\n    dialogClass: 'modal',\n    backdropClass: 'modal-backdrop',\n    transitionClass: 'fade',\n    triggerClass: 'in',\n    dialogOpenClass: 'modal-open',  \n    resolve:{},\n    backdropFade: false,\n    dialogFade:false,\n    keyboard: true, // close with esc key\n    backdropClick: true // only in conjunction with backdrop=true\n    /* other options: template, templateUrl, controller */\n\t};\n\n\tvar globalOptions = {};\n\n  var activeBackdrops = {value : 0};\n\n  // The `options({})` allows global configuration of all dialogs in the application.\n  //\n  //      var app = angular.module('App', ['ui.bootstrap.dialog'], function($dialogProvider){\n  //        // don't close dialog when backdrop is clicked by default\n  //        $dialogProvider.options({backdropClick: false});\n  //      });\n\tthis.options = function(value){\n\t\tglobalOptions = value;\n\t};\n\n  // Returns the actual `$dialog` service that is injected in controllers\n\tthis.$get = [\"$http\", \"$document\", \"$compile\", \"$rootScope\", \"$controller\", \"$templateCache\", \"$q\", \"$transition\", \"$injector\",\n  function ($http, $document, $compile, $rootScope, $controller, $templateCache, $q, $transition, $injector) {\n\n\t\tvar body = $document.find('body');\n\n\t\tfunction createElement(clazz) {\n\t\t\tvar el = angular.element(\"<div>\");\n\t\t\tel.addClass(clazz);\n\t\t\treturn el;\n\t\t}\n\n    // The `Dialog` class represents a modal dialog. The dialog class can be invoked by providing an options object\n    // containing at lest template or templateUrl and controller:\n    //\n    //     var d = new Dialog({templateUrl: 'foo.html', controller: 'BarController'});\n    //\n    // Dialogs can also be created using templateUrl and controller as distinct arguments:\n    //\n    //     var d = new Dialog('path/to/dialog.html', MyDialogController);\n\t\tfunction Dialog(opts) {\n\n      var self = this, options = this.options = angular.extend({}, defaults, globalOptions, opts);\n      this._open = false;\n\n      this.backdropEl = createElement(options.backdropClass);\n      if(options.backdropFade){\n        this.backdropEl.addClass(options.transitionClass);\n        this.backdropEl.removeClass(options.triggerClass);\n      }\n\n      this.modalEl = createElement(options.dialogClass);\n      if(options.dialogFade){\n        this.modalEl.addClass(options.transitionClass);\n        this.modalEl.removeClass(options.triggerClass);\n      }\n\n      this.handledEscapeKey = function(e) {\n        if (e.which === 27) {\n          self.close();\n          e.preventDefault();\n          self.$scope.$apply();\n        }\n      };\n\n      this.handleBackDropClick = function(e) {\n        self.close();\n        e.preventDefault();\n        self.$scope.$apply();\n      };\n\n      this.handleLocationChange = function() {\n        self.close();\n      };\n    }\n\n    // The `isOpen()` method returns wether the dialog is currently visible.\n    Dialog.prototype.isOpen = function(){\n      return this._open;\n    };\n\n    // The `open(templateUrl, controller)` method opens the dialog.\n    // Use the `templateUrl` and `controller` arguments if specifying them at dialog creation time is not desired.\n    Dialog.prototype.open = function(templateUrl, controller){\n      var self = this, options = this.options;\n\n      if(templateUrl){\n        options.templateUrl = templateUrl;\n      }\n      if(controller){\n        options.controller = controller;\n      }\n\n      if(!(options.template || options.templateUrl)) {\n        throw new Error('Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.');\n      }\n\n      this._loadResolves().then(function(locals) {\n        var $scope = locals.$scope = self.$scope = locals.$scope ? locals.$scope : $rootScope.$new();\n\n        self.modalEl.html(locals.$template);\n\n        if (self.options.controller) {\n          var ctrl = $controller(self.options.controller, locals);\n          self.modalEl.children().data('ngControllerController', ctrl);\n        }\n\n        $compile(self.modalEl)($scope);\n        self._addElementsToDom();\n        body.addClass(self.options.dialogOpenClass);\n\n        // trigger tranisitions\n        setTimeout(function(){\n          if(self.options.dialogFade){ self.modalEl.addClass(self.options.triggerClass); }\n          if(self.options.backdropFade){ self.backdropEl.addClass(self.options.triggerClass); }\n        });\n\n        self._bindEvents();\n      });\n\n      this.deferred = $q.defer();\n      return this.deferred.promise;\n    };\n\n    // closes the dialog and resolves the promise returned by the `open` method with the specified result.\n    Dialog.prototype.close = function(result){\n      var self = this;\n      var fadingElements = this._getFadingElements();\n\n      body.removeClass(self.options.dialogOpenClass);\n      if(fadingElements.length > 0){\n        for (var i = fadingElements.length - 1; i >= 0; i--) {\n          $transition(fadingElements[i], removeTriggerClass).then(onCloseComplete);\n        }\n        return;\n      }\n\n      this._onCloseComplete(result);\n\n      function removeTriggerClass(el){\n        el.removeClass(self.options.triggerClass);\n      }\n\n      function onCloseComplete(){\n        if(self._open){\n          self._onCloseComplete(result);\n        }\n      }\n    };\n\n    Dialog.prototype._getFadingElements = function(){\n      var elements = [];\n      if(this.options.dialogFade){\n        elements.push(this.modalEl);\n      }\n      if(this.options.backdropFade){\n        elements.push(this.backdropEl);\n      }\n\n      return elements;\n    };\n\n    Dialog.prototype._bindEvents = function() {\n      if(this.options.keyboard){ body.bind('keydown', this.handledEscapeKey); }\n      if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.bind('click', this.handleBackDropClick); }\n\n      this.$scope.$on('$locationChangeSuccess', this.handleLocationChange);\n    };\n\n    Dialog.prototype._unbindEvents = function() {\n      if(this.options.keyboard){ body.unbind('keydown', this.handledEscapeKey); }\n      if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.unbind('click', this.handleBackDropClick); }\n    };\n\n    Dialog.prototype._onCloseComplete = function(result) {\n      this._removeElementsFromDom();\n      this._unbindEvents();\n\n      this.deferred.resolve(result);\n    };\n\n    Dialog.prototype._addElementsToDom = function(){\n      body.append(this.modalEl);\n\n      if(this.options.backdrop) { \n        if (activeBackdrops.value === 0) {\n          body.append(this.backdropEl); \n        }\n        activeBackdrops.value++;\n      }\n\n      this._open = true;\n    };\n\n    Dialog.prototype._removeElementsFromDom = function(){\n      this.modalEl.remove();\n\n      if(this.options.backdrop) { \n        activeBackdrops.value--;\n        if (activeBackdrops.value === 0) {\n          this.backdropEl.remove(); \n        }\n      }\n      this._open = false;\n    };\n\n    // Loads all `options.resolve` members to be used as locals for the controller associated with the dialog.\n    Dialog.prototype._loadResolves = function(){\n      var values = [], keys = [], templatePromise, self = this;\n\n      if (this.options.template) {\n        templatePromise = $q.when(this.options.template);\n      } else if (this.options.templateUrl) {\n        templatePromise = $http.get(this.options.templateUrl, {cache:$templateCache})\n        .then(function(response) { return response.data; });\n      }\n\n      angular.forEach(this.options.resolve || [], function(value, key) {\n        keys.push(key);\n        values.push(angular.isString(value) ? $injector.get(value) : $injector.invoke(value));\n      });\n\n      keys.push('$template');\n      values.push(templatePromise);\n\n      return $q.all(values).then(function(values) {\n        var locals = {};\n        angular.forEach(values, function(value, index) {\n          locals[keys[index]] = value;\n        });\n        locals.dialog = self;\n        return locals;\n      });\n    };\n\n    // The actual `$dialog` service that is injected in controllers.\n    return {\n      // Creates a new `Dialog` with the specified options.\n      dialog: function(opts){\n        return new Dialog(opts);\n      },\n      // creates a new `Dialog` tied to the default message box template and controller.\n      //\n      // Arguments `title` and `message` are rendered in the modal header and body sections respectively.\n      // The `buttons` array holds an object with the following members for each button to include in the\n      // modal footer section:\n      //\n      // * `result`: the result to pass to the `close` method of the dialog when the button is clicked\n      // * `label`: the label of the button\n      // * `cssClass`: additional css class(es) to apply to the button for styling\n      messageBox: function(title, message, buttons){\n        return new Dialog({templateUrl: 'template/dialog/message.html', controller: 'MessageBoxController', resolve:\n          {model: function() {\n            return {\n              title: title,\n              message: message,\n              buttons: buttons\n            };\n          }\n        }});\n      }\n    };\n  }];\n});\n\n/*\n * dropdownToggle - Provides dropdown menu functionality in place of bootstrap js\n * @restrict class or attribute\n * @example:\n   <li class=\"dropdown\">\n     <a class=\"dropdown-toggle\">My Dropdown Menu</a>\n     <ul class=\"dropdown-menu\">\n       <li ng-repeat=\"choice in dropChoices\">\n         <a ng-href=\"{{choice.href}}\">{{choice.text}}</a>\n       </li>\n     </ul>\n   </li>\n */\n\nangular.module('ui.bootstrap.dropdownToggle', []).directive('dropdownToggle',\n  ['$document', '$location', '$window', function ($document, $location, $window) {\n  var openElement = null,\n      closeMenu   = angular.noop;\n  return {\n    restrict: 'CA',\n    link: function(scope, element, attrs) {\n      scope.$watch('$location.path', function() { closeMenu(); });\n      element.parent().bind('click', function() { closeMenu(); });\n      element.bind('click', function(event) {\n        event.preventDefault();\n        event.stopPropagation();\n        var elementWasOpen = (element === openElement);\n        if (!!openElement) {\n          closeMenu(); }\n        if (!elementWasOpen){\n          element.parent().addClass('open');\n          openElement = element;\n          closeMenu = function (event) {\n            if (event) {\n              event.preventDefault();\n              event.stopPropagation();\n            }\n            $document.unbind('click', closeMenu);\n            element.parent().removeClass('open');\n            closeMenu   = angular.noop;\n            openElement = null;\n          };\n          $document.bind('click', closeMenu);\n        }\n      });\n    }\n  };\n}]);\nangular.module('ui.bootstrap.modal', ['ui.bootstrap.dialog'])\n.directive('modal', ['$parse', '$dialog', function($parse, $dialog) {\n  return {\n    restrict: 'EA',\n    terminal: true,\n    link: function(scope, elm, attrs) {\n      var opts = angular.extend({}, scope.$eval(attrs.uiOptions || attrs.bsOptions || attrs.options));\n      var shownExpr = attrs.modal || attrs.show;\n      var setClosed;\n\n      // Create a dialog with the template as the contents of the directive\n      // Add the current scope as the resolve in order to make the directive scope as a dialog controller scope\n      opts = angular.extend(opts, {\n        template: elm.html(), \n        resolve: { $scope: function() { return scope; } }\n      });\n      var dialog = $dialog.dialog(opts);\n\n      elm.remove();\n\n      if (attrs.close) {\n        setClosed = function() {\n          $parse(attrs.close)(scope);\n        };\n      } else {\n        setClosed = function() {         \n          if (angular.isFunction($parse(shownExpr).assign)) {\n            $parse(shownExpr).assign(scope, false); \n          }\n        };\n      }\n\n      scope.$watch(shownExpr, function(isShown, oldShown) {\n        if (isShown) {\n          dialog.open().then(function(){\n            setClosed();\n          });\n        } else {\n          //Make sure it is not opened\n          if (dialog.isOpen()){\n            dialog.close();\n          }\n        }\n      });\n    }\n  };\n}]);\nangular.module('ui.bootstrap.pagination', [])\n\n.constant('paginationConfig', {\n  boundaryLinks: false,\n  directionLinks: true,\n  firstText: 'First',\n  previousText: 'Previous',\n  nextText: 'Next',\n  lastText: 'Last'\n})\n\n.directive('pagination', ['paginationConfig', function(paginationConfig) {\n  return {\n    restrict: 'EA',\n    scope: {\n      numPages: '=',\n      currentPage: '=',\n      maxSize: '=',\n      onSelectPage: '&'\n    },\n    templateUrl: 'template/pagination/pagination.html',\n    replace: true,\n    link: function(scope, element, attrs) {\n\n      // Setup configuration parameters\n      var boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;\n      var directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$eval(attrs.directionLinks) : paginationConfig.directionLinks;\n      var firstText = angular.isDefined(attrs.firstText) ? attrs.firstText : paginationConfig.firstText;\n      var previousText = angular.isDefined(attrs.previousText) ? attrs.previousText : paginationConfig.previousText;\n      var nextText = angular.isDefined(attrs.nextText) ? attrs.nextText : paginationConfig.nextText;\n      var lastText = angular.isDefined(attrs.lastText) ? attrs.lastText : paginationConfig.lastText;\n\n      // Create page object used in template\n      function makePage(number, text, isActive, isDisabled) {\n        return {\n          number: number,\n          text: text,\n          active: isActive,\n          disabled: isDisabled\n        };\n      }\n\n      scope.$watch('numPages + currentPage + maxSize', function() {\n        scope.pages = [];\n        \n        // Default page limits\n        var startPage = 1, endPage = scope.numPages;\n\n        // recompute if maxSize\n        if ( scope.maxSize && scope.maxSize < scope.numPages ) {\n          startPage = Math.max(scope.currentPage - Math.floor(scope.maxSize/2), 1);\n          endPage   = startPage + scope.maxSize - 1;\n\n          // Adjust if limit is exceeded\n          if (endPage > scope.numPages) {\n            endPage   = scope.numPages;\n            startPage = endPage - scope.maxSize + 1;\n          }\n        }\n\n        // Add page number links\n        for (var number = startPage; number <= endPage; number++) {\n          var page = makePage(number, number, scope.isActive(number), false);\n          scope.pages.push(page);\n        }\n\n        // Add previous & next links\n        if (directionLinks) {\n          var previousPage = makePage(scope.currentPage - 1, previousText, false, scope.noPrevious());\n          scope.pages.unshift(previousPage);\n\n          var nextPage = makePage(scope.currentPage + 1, nextText, false, scope.noNext());\n          scope.pages.push(nextPage);\n        }\n\n        // Add first & last links\n        if (boundaryLinks) {\n          var firstPage = makePage(1, firstText, false, scope.noPrevious());\n          scope.pages.unshift(firstPage);\n\n          var lastPage = makePage(scope.numPages, lastText, false, scope.noNext());\n          scope.pages.push(lastPage);\n        }\n\n\n        if ( scope.currentPage > scope.numPages ) {\n          scope.selectPage(scope.numPages);\n        }\n      });\n      scope.noPrevious = function() {\n        return scope.currentPage === 1;\n      };\n      scope.noNext = function() {\n        return scope.currentPage === scope.numPages;\n      };\n      scope.isActive = function(page) {\n        return scope.currentPage === page;\n      };\n\n      scope.selectPage = function(page) {\n        if ( ! scope.isActive(page) && page > 0 && page <= scope.numPages) {\n          scope.currentPage = page;\n          scope.onSelectPage({ page: page });\n        }\n      };\n    }\n  };\n}]);\nangular.module('ui.bootstrap.position', [])\n\n/**\n * A set of utility methods that can be use to retrieve position of DOM elements.\n * It is meant to be used where we need to absolute-position DOM elements in\n * relation to other, existing elements (this is the case for tooltips, popovers,\n * typeahead suggestions etc.).\n */\n  .factory('$position', ['$document', '$window', function ($document, $window) {\n\n    function getStyle(el, cssprop) {\n      if (el.currentStyle) { //IE\n        return el.currentStyle[cssprop];\n      } else if ($window.getComputedStyle) {\n        return $window.getComputedStyle(el)[cssprop];\n      }\n      // finally try and get inline style\n      return el.style[cssprop];\n    }\n\n    /**\n     * Checks if a given element is statically positioned\n     * @param element - raw DOM element\n     */\n    function isStaticPositioned(element) {\n      return (getStyle(element, \"position\") || 'static' ) === 'static';\n    }\n\n    /**\n     * returns the closest, non-statically positioned parentOffset of a given element\n     * @param element\n     */\n    var parentOffsetEl = function (element) {\n      var docDomEl = $document[0];\n      var offsetParent = element.offsetParent || docDomEl;\n      while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent || docDomEl;\n    };\n\n    return {\n      /**\n       * Provides read-only equivalent of jQuery's position function:\n       * http://api.jquery.com/position/\n       */\n      position: function (element) {\n        var elBCR = this.offset(element);\n        var offsetParentBCR = { top: 0, left: 0 };\n        var offsetParentEl = parentOffsetEl(element[0]);\n        if (offsetParentEl != $document[0]) {\n          offsetParentBCR = this.offset(angular.element(offsetParentEl));\n          offsetParentBCR.top += offsetParentEl.clientTop;\n          offsetParentBCR.left += offsetParentEl.clientLeft;\n        }\n\n        return {\n          width: element.prop('offsetWidth'),\n          height: element.prop('offsetHeight'),\n          top: elBCR.top - offsetParentBCR.top,\n          left: elBCR.left - offsetParentBCR.left\n        };\n      },\n\n      /**\n       * Provides read-only equivalent of jQuery's offset function:\n       * http://api.jquery.com/offset/\n       */\n      offset: function (element) {\n        var boundingClientRect = element[0].getBoundingClientRect();\n        return {\n          width: element.prop('offsetWidth'),\n          height: element.prop('offsetHeight'),\n          top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop),\n          left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft)\n        };\n      }\n    };\n  }]);\n\n/**\n * The following features are still outstanding: animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html tooltips, and selector delegation.\n */\nangular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position' ] )\n\n/**\n * The $tooltip service creates tooltip- and popover-like directives as well as\n * houses global options for them.\n */\n.provider( '$tooltip', function () {\n  // The default options tooltip and popover.\n  var defaultOptions = {\n    placement: 'top',\n    animation: true,\n    popupDelay: 0\n  };\n\n  // Default hide triggers for each show trigger\n  var triggerMap = {\n    'mouseenter': 'mouseleave',\n    'click': 'click',\n    'focus': 'blur'\n  };\n\n  // The options specified to the provider globally.\n  var globalOptions = {};\n  \n  /**\n   * `options({})` allows global configuration of all tooltips in the\n   * application.\n   *\n   *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {\n   *     // place tooltips left instead of top by default\n   *     $tooltipProvider.options( { placement: 'left' } );\n   *   });\n   */\n\tthis.options = function( value ) {\n\t\tangular.extend( globalOptions, value );\n\t};\n\n  /**\n   * This is a helper function for translating camel-case to snake-case.\n   */\n  function snake_case(name){\n    var regexp = /[A-Z]/g;\n    var separator = '-';\n    return name.replace(regexp, function(letter, pos) {\n      return (pos ? separator : '') + letter.toLowerCase();\n    });\n  }\n\n  /**\n   * Returns the actual instance of the $tooltip service.\n   * TODO support multiple triggers\n   */\n  this.$get = [ '$window', '$compile', '$timeout', '$parse', '$document', '$position', function ( $window, $compile, $timeout, $parse, $document, $position ) {\n    return function $tooltip ( type, prefix, defaultTriggerShow ) {\n      var options = angular.extend( {}, defaultOptions, globalOptions );\n\n      /**\n       * Returns an object of show and hide triggers.\n       *\n       * If a trigger is supplied,\n       * it is used to show the tooltip; otherwise, it will use the `trigger`\n       * option passed to the `$tooltipProvider.options` method; else it will\n       * default to the trigger supplied to this directive factory.\n       *\n       * The hide trigger is based on the show trigger. If the `trigger` option\n       * was passed to the `$tooltipProvider.options` method, it will use the\n       * mapped trigger from `triggerMap` or the passed trigger if the map is\n       * undefined; otherwise, it uses the `triggerMap` value of the show\n       * trigger; else it will just use the show trigger.\n       */\n      function setTriggers ( trigger ) {\n        var show, hide;\n       \n        show = trigger || options.trigger || defaultTriggerShow;\n        if ( angular.isDefined ( options.trigger ) ) {\n          hide = triggerMap[options.trigger] || show;\n        } else {\n          hide = triggerMap[show] || show;\n        }\n\n        return {\n          show: show,\n          hide: hide\n        };\n      }\n\n      var directiveName = snake_case( type );\n      var triggers = setTriggers( undefined );\n\n      var template = \n        '<'+ directiveName +'-popup '+\n          'title=\"{{tt_title}}\" '+\n          'content=\"{{tt_content}}\" '+\n          'placement=\"{{tt_placement}}\" '+\n          'animation=\"tt_animation()\" '+\n          'is-open=\"tt_isOpen\"'+\n          '>'+\n        '</'+ directiveName +'-popup>';\n\n      return {\n        restrict: 'EA',\n        scope: true,\n        link: function link ( scope, element, attrs ) {\n          var tooltip = $compile( template )( scope );\n          var transitionTimeout;\n          var popupTimeout;\n          var $body;\n\n          // By default, the tooltip is not open.\n          // TODO add ability to start tooltip opened\n          scope.tt_isOpen = false;\n\n          function toggleTooltipBind () {\n            if ( ! scope.tt_isOpen ) {\n              showTooltipBind();\n            } else {\n              hideTooltipBind();\n            }\n          }\n          \n          // Show the tooltip with delay if specified, otherwise show it immediately\n          function showTooltipBind() {\n            if ( scope.tt_popupDelay ) {\n              popupTimeout = $timeout( show, scope.tt_popupDelay );\n            } else {\n              scope.$apply( show );\n            }\n          }\n\n          function hideTooltipBind () {\n            scope.$apply(function () {\n              hide();\n            });\n          }\n          \n          // Show the tooltip popup element.\n          function show() {\n            var position,\n                ttWidth,\n                ttHeight,\n                ttPosition;\n\n            // Don't show empty tooltips.\n            if ( ! scope.tt_content ) {\n              return;\n            }\n\n            // If there is a pending remove transition, we must cancel it, lest the\n            // tooltip be mysteriously removed.\n            if ( transitionTimeout ) {\n              $timeout.cancel( transitionTimeout );\n            }\n            \n            // Set the initial positioning.\n            tooltip.css({ top: 0, left: 0, display: 'block' });\n            \n            // Now we add it to the DOM because need some info about it. But it's not \n            // visible yet anyway.\n            if ( options.appendToBody ) {\n                $body = $body || $document.find( 'body' );\n                $body.append( tooltip );\n            } else {\n              element.after( tooltip );\n            }\n            \n            // Get the position of the directive element.\n            position = $position.position( element );\n\n            // Get the height and width of the tooltip so we can center it.\n            ttWidth = tooltip.prop( 'offsetWidth' );\n            ttHeight = tooltip.prop( 'offsetHeight' );\n            \n            // Calculate the tooltip's top and left coordinates to center it with\n            // this directive.\n            switch ( scope.tt_placement ) {\n              case 'right':\n                ttPosition = {\n                  top: (position.top + position.height / 2 - ttHeight / 2) + 'px',\n                  left: (position.left + position.width) + 'px'\n                };\n                break;\n              case 'bottom':\n                ttPosition = {\n                  top: (position.top + position.height) + 'px',\n                  left: (position.left + position.width / 2 - ttWidth / 2) + 'px'\n                };\n                break;\n              case 'left':\n                ttPosition = {\n                  top: (position.top + position.height / 2 - ttHeight / 2) + 'px',\n                  left: (position.left - ttWidth) + 'px'\n                };\n                break;\n              default:\n                ttPosition = {\n                  top: (position.top - ttHeight) + 'px',\n                  left: (position.left + position.width / 2 - ttWidth / 2) + 'px'\n                };\n                break;\n            }\n            \n            // Now set the calculated positioning.\n            tooltip.css( ttPosition );\n              \n            // And show the tooltip.\n            scope.tt_isOpen = true;\n          }\n          \n          // Hide the tooltip popup element.\n          function hide() {\n            // First things first: we don't show it anymore.\n            scope.tt_isOpen = false;\n\n            //if tooltip is going to be shown after delay, we must cancel this\n            $timeout.cancel( popupTimeout );\n            \n            // And now we remove it from the DOM. However, if we have animation, we \n            // need to wait for it to expire beforehand.\n            // FIXME: this is a placeholder for a port of the transitions library.\n            if ( angular.isDefined( scope.tt_animation ) && scope.tt_animation() ) {\n              transitionTimeout = $timeout( function () { tooltip.remove(); }, 500 );\n            } else {\n              tooltip.remove();\n            }\n          }\n\n          /**\n           * Observe the relevant attributes.\n           */\n          attrs.$observe( type, function ( val ) {\n            scope.tt_content = val;\n          });\n\n          attrs.$observe( prefix+'Title', function ( val ) {\n            scope.tt_title = val;\n          });\n\n          attrs.$observe( prefix+'Placement', function ( val ) {\n            scope.tt_placement = angular.isDefined( val ) ? val : options.placement;\n          });\n\n          attrs.$observe( prefix+'Animation', function ( val ) {\n            scope.tt_animation = angular.isDefined( val ) ? $parse( val ) : function(){ return options.animation; };\n          });\n\n          attrs.$observe( prefix+'PopupDelay', function ( val ) {\n            var delay = parseInt( val, 10 );\n            scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;\n          });\n\n          attrs.$observe( prefix+'Trigger', function ( val ) {\n            element.unbind( triggers.show );\n            element.unbind( triggers.hide );\n\n            triggers = setTriggers( val );\n\n            if ( triggers.show === triggers.hide ) {\n              element.bind( triggers.show, toggleTooltipBind );\n            } else {\n              element.bind( triggers.show, showTooltipBind );\n              element.bind( triggers.hide, hideTooltipBind );\n            }\n          });\n        }\n      };\n    };\n  }];\n})\n\n.directive( 'tooltipPopup', function () {\n  return {\n    restrict: 'E',\n    replace: true,\n    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/tooltip/tooltip-popup.html'\n  };\n})\n\n.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) {\n  return $tooltip( 'tooltip', 'tooltip', 'mouseenter' );\n}])\n\n.directive( 'tooltipHtmlUnsafePopup', function () {\n  return {\n    restrict: 'E',\n    replace: true,\n    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'\n  };\n})\n\n.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {\n  return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );\n}])\n\n;\n\n\n/**\n * The following features are still outstanding: popup delay, animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html popovers, and selector delegatation.\n */\nangular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )\n.directive( 'popoverPopup', function () {\n  return {\n    restrict: 'EA',\n    replace: true,\n    scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },\n    templateUrl: 'template/popover/popover.html'\n  };\n})\n.directive( 'popover', [ '$compile', '$timeout', '$parse', '$window', '$tooltip', function ( $compile, $timeout, $parse, $window, $tooltip ) {\n  return $tooltip( 'popover', 'popover', 'click' );\n}]);\n\n\nangular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition'])\n\n.constant('progressConfig', {\n  animate: true,\n  autoType: false,\n  stackedTypes: ['success', 'info', 'warning', 'danger']\n})\n\n.controller('ProgressBarController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) {\n\n    // Whether bar transitions should be animated\n    var animate = angular.isDefined($attrs.animate) ? $scope.$eval($attrs.animate) : progressConfig.animate;\n    var autoType = angular.isDefined($attrs.autoType) ? $scope.$eval($attrs.autoType) : progressConfig.autoType;\n    var stackedTypes = angular.isDefined($attrs.stackedTypes) ? $scope.$eval('[' + $attrs.stackedTypes + ']') : progressConfig.stackedTypes;\n\n    // Create bar object\n    this.makeBar = function(newBar, oldBar, index) {\n        var newValue = (angular.isObject(newBar)) ? newBar.value : (newBar || 0);\n        var oldValue =  (angular.isObject(oldBar)) ? oldBar.value : (oldBar || 0);\n        var type = (angular.isObject(newBar) && angular.isDefined(newBar.type)) ? newBar.type : (autoType) ? getStackedType(index || 0) : null;\n\n        return {\n            from: oldValue,\n            to: newValue,\n            type: type,\n            animate: animate\n        };\n    };\n\n    function getStackedType(index) {\n        return stackedTypes[index];\n    }\n\n    this.addBar = function(bar) {\n        $scope.bars.push(bar);\n        $scope.totalPercent += bar.to;\n    };\n\n    this.clearBars = function() {\n        $scope.bars = [];\n        $scope.totalPercent = 0;\n    };\n    this.clearBars();\n}])\n\n.directive('progress', function() {\n    return {\n        restrict: 'EA',\n        replace: true,\n        controller: 'ProgressBarController',\n        scope: {\n            value: '=',\n            onFull: '&',\n            onEmpty: '&'\n        },\n        templateUrl: 'template/progressbar/progress.html',\n        link: function(scope, element, attrs, controller) {\n            scope.$watch('value', function(newValue, oldValue) {\n                controller.clearBars();\n\n                if (angular.isArray(newValue)) {\n                    // Stacked progress bar\n                    for (var i=0, n=newValue.length; i < n; i++) {\n                        controller.addBar(controller.makeBar(newValue[i], oldValue[i], i));\n                    }\n                } else {\n                    // Simple bar\n                    controller.addBar(controller.makeBar(newValue, oldValue));\n                }\n            }, true);\n\n            // Total percent listeners\n            scope.$watch('totalPercent', function(value) {\n              if (value >= 100) {\n                scope.onFull();\n              } else if (value <= 0) {\n                scope.onEmpty();\n              }\n            }, true);\n        }\n    };\n})\n\n.directive('progressbar', ['$transition', function($transition) {\n    return {\n        restrict: 'EA',\n        replace: true,\n        scope: {\n            width: '=',\n            old: '=',\n            type: '=',\n            animate: '='\n        },\n        templateUrl: 'template/progressbar/bar.html',\n        link: function(scope, element) {\n            scope.$watch('width', function(value) {\n                if (scope.animate) {\n                    element.css('width', scope.old + '%');\n                    $transition(element, {width: value + '%'});\n                } else {\n                    element.css('width', value + '%');\n                }\n            });\n        }\n    };\n}]);\nangular.module('ui.bootstrap.rating', [])\n\n.constant('ratingConfig', {\n  max: 5\n})\n\n.directive('rating', ['ratingConfig', '$parse', function(ratingConfig, $parse) {\n  return {\n    restrict: 'EA',\n    scope: {\n      value: '='\n    },\n    templateUrl: 'template/rating/rating.html',\n    replace: true,\n    link: function(scope, element, attrs) {\n\n      var maxRange = angular.isDefined(attrs.max) ? scope.$eval(attrs.max) : ratingConfig.max;\n\n      scope.range = [];\n      for (var i = 1; i <= maxRange; i++) {\n          scope.range.push(i);\n      }\n\n      scope.rate = function(value) {\n          if ( ! scope.readonly ) {\n              scope.value = value;\n          }\n      };\n\n      scope.enter = function(value) {\n          if ( ! scope.readonly ) {\n              scope.val = value;\n          }\n      };\n\n      scope.reset = function() {\n          scope.val = angular.copy(scope.value);\n      };\n      scope.reset();\n\n      scope.$watch('value', function(value) {\n          scope.val = value;\n      });\n\n      scope.readonly = false;\n      if (attrs.readonly) {\n          scope.$parent.$watch($parse(attrs.readonly), function(value) {\n              scope.readonly = !!value;\n          });\n      }\n    }\n  };\n}]);\nangular.module('ui.bootstrap.tabs', [])\n.controller('TabsController', ['$scope', '$element', function($scope, $element) {\n  var panes = $scope.panes = [];\n\n  this.select = $scope.select = function selectPane(pane) {\n    angular.forEach(panes, function(pane) {\n      pane.selected = false;\n    });\n    pane.selected = true;\n  };\n\n  this.addPane = function addPane(pane) {\n    if (!panes.length) {\n      $scope.select(pane);\n    }\n    panes.push(pane);\n  };\n\n  this.removePane = function removePane(pane) { \n    var index = panes.indexOf(pane);\n    panes.splice(index, 1);\n    //Select a new pane if removed pane was selected \n    if (pane.selected && panes.length > 0) {\n      $scope.select(panes[index < panes.length ? index : index-1]);\n    }\n  };\n}])\n.directive('tabs', function() {\n  return {\n    restrict: 'EA',\n    transclude: true,\n    scope: {},\n    controller: 'TabsController',\n    templateUrl: 'template/tabs/tabs.html',\n    replace: true\n  };\n})\n.directive('pane', ['$parse', function($parse) {\n  return {\n    require: '^tabs',\n    restrict: 'EA',\n    transclude: true,\n    scope:{\n      heading:'@'\n    },\n    link: function(scope, element, attrs, tabsCtrl) {\n      var getSelected, setSelected;\n      scope.selected = false;\n      if (attrs.active) {\n        getSelected = $parse(attrs.active);\n        setSelected = getSelected.assign;\n        scope.$watch(\n          function watchSelected() {return getSelected(scope.$parent);},\n          function updateSelected(value) {scope.selected = value;}\n        );\n        scope.selected = getSelected ? getSelected(scope.$parent) : false;\n      }\n      scope.$watch('selected', function(selected) {\n        if(selected) {\n          tabsCtrl.select(scope);\n        }\n        if(setSelected) {\n          setSelected(scope.$parent, selected);\n        }\n      });\n\n      tabsCtrl.addPane(scope);\n      scope.$on('$destroy', function() {\n        tabsCtrl.removePane(scope);\n      });\n    },\n    templateUrl: 'template/tabs/pane.html',\n    replace: true\n  };\n}]);\n\nangular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])\n\n/**\n * A helper service that can parse typeahead's syntax (string provided by users)\n * Extracted to a separate service for ease of unit testing\n */\n  .factory('typeaheadParser', ['$parse', function ($parse) {\n\n  //                      00000111000000000000022200000000000000003333333333333330000000000044000\n  var TYPEAHEAD_REGEXP = /^\\s*(.*?)(?:\\s+as\\s+(.*?))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*))\\s+in\\s+(.*)$/;\n\n  return {\n    parse:function (input) {\n\n      var match = input.match(TYPEAHEAD_REGEXP), modelMapper, viewMapper, source;\n      if (!match) {\n        throw new Error(\n          \"Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_'\" +\n            \" but got '\" + input + \"'.\");\n      }\n\n      return {\n        itemName:match[3],\n        source:$parse(match[4]),\n        viewMapper:$parse(match[2] || match[1]),\n        modelMapper:$parse(match[1])\n      };\n    }\n  };\n}])\n\n  .directive('typeahead', ['$compile', '$parse', '$q', '$document', '$position', 'typeaheadParser', function ($compile, $parse, $q, $document, $position, typeaheadParser) {\n\n  var HOT_KEYS = [9, 13, 27, 38, 40];\n\n  return {\n    require:'ngModel',\n    link:function (originalScope, element, attrs, modelCtrl) {\n\n      var selected;\n\n      //minimal no of characters that needs to be entered before typeahead kicks-in\n      var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;\n\n      //expressions used by typeahead\n      var parserResult = typeaheadParser.parse(attrs.typeahead);\n\n      //should it restrict model values to the ones selected from the popup only?\n      var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;\n\n      var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;\n\n      //pop-up element used to display matches\n      var popUpEl = angular.element(\n        \"<typeahead-popup \" +\n          \"matches='matches' \" +\n          \"active='activeIdx' \" +\n          \"select='select(activeIdx)' \"+\n          \"query='query' \"+\n          \"position='position'>\"+\n        \"</typeahead-popup>\");\n\n      //create a child scope for the typeahead directive so we are not polluting original scope\n      //with typeahead-specific data (matches, query etc.)\n      var scope = originalScope.$new();\n      originalScope.$on('$destroy', function(){\n        scope.$destroy();\n      });\n\n      var resetMatches = function() {\n        scope.matches = [];\n        scope.activeIdx = -1;\n      };\n\n      var getMatchesAsync = function(inputValue) {\n\n        var locals = {$viewValue: inputValue};\n        isLoadingSetter(originalScope, true);\n        $q.when(parserResult.source(scope, locals)).then(function(matches) {\n\n          //it might happen that several async queries were in progress if a user were typing fast\n          //but we are interested only in responses that correspond to the current view value\n          if (inputValue === modelCtrl.$viewValue) {\n            if (matches.length > 0) {\n\n              scope.activeIdx = 0;\n              scope.matches.length = 0;\n\n              //transform labels\n              for(var i=0; i<matches.length; i++) {\n                locals[parserResult.itemName] = matches[i];\n                scope.matches.push({\n                  label: parserResult.viewMapper(scope, locals),\n                  model: matches[i]\n                });\n              }\n\n              scope.query = inputValue;\n              //position pop-up with matches - we need to re-calculate its position each time we are opening a window\n              //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page\n              //due to other elements being rendered\n              scope.position = $position.position(element);\n              scope.position.top = scope.position.top + element.prop('offsetHeight');\n\n            } else {\n              resetMatches();\n            }\n            isLoadingSetter(originalScope, false);\n          }\n        }, function(){\n          resetMatches();\n          isLoadingSetter(originalScope, false);\n        });\n      };\n\n      resetMatches();\n\n      //we need to propagate user's query so we can higlight matches\n      scope.query = undefined;\n\n      //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM\n      //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue\n      modelCtrl.$parsers.push(function (inputValue) {\n\n        resetMatches();\n        if (selected) {\n          return inputValue;\n        } else {\n          if (inputValue && inputValue.length >= minSearch) {\n            getMatchesAsync(inputValue);\n          }\n        }\n\n        return isEditable ? inputValue : undefined;\n      });\n\n      modelCtrl.$render = function () {\n        var locals = {};\n        locals[parserResult.itemName] = selected || modelCtrl.$viewValue;\n        element.val(parserResult.viewMapper(scope, locals) || modelCtrl.$viewValue);\n        selected = undefined;\n      };\n\n      scope.select = function (activeIdx) {\n        //called from within the $digest() cycle\n        var locals = {};\n        locals[parserResult.itemName] = selected = scope.matches[activeIdx].model;\n\n        modelCtrl.$setViewValue(parserResult.modelMapper(scope, locals));\n        modelCtrl.$render();\n      };\n\n      //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n      element.bind('keydown', function (evt) {\n\n        //typeahead is open and an \"interesting\" key was pressed\n        if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {\n          return;\n        }\n\n        evt.preventDefault();\n\n        if (evt.which === 40) {\n          scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;\n          scope.$digest();\n\n        } else if (evt.which === 38) {\n          scope.activeIdx = (scope.activeIdx ? scope.activeIdx : scope.matches.length) - 1;\n          scope.$digest();\n\n        } else if (evt.which === 13 || evt.which === 9) {\n          scope.$apply(function () {\n            scope.select(scope.activeIdx);\n          });\n\n        } else if (evt.which === 27) {\n          evt.stopPropagation();\n\n          resetMatches();\n          scope.$digest();\n        }\n      });\n\n      $document.bind('click', function(){\n        resetMatches();\n        scope.$digest();\n      });\n\n      element.after($compile(popUpEl)(scope));\n    }\n  };\n\n}])\n\n  .directive('typeaheadPopup', function () {\n    return {\n      restrict:'E',\n      scope:{\n        matches:'=',\n        query:'=',\n        active:'=',\n        position:'=',\n        select:'&'\n      },\n      replace:true,\n      templateUrl:'template/typeahead/typeahead.html',\n      link:function (scope, element, attrs) {\n\n        scope.isOpen = function () {\n          return scope.matches.length > 0;\n        };\n\n        scope.isActive = function (matchIdx) {\n          return scope.active == matchIdx;\n        };\n\n        scope.selectActive = function (matchIdx) {\n          scope.active = matchIdx;\n        };\n\n        scope.selectMatch = function (activeIdx) {\n          scope.select({activeIdx:activeIdx});\n        };\n      }\n    };\n  })\n\n  .filter('typeaheadHighlight', function() {\n\n    function escapeRegexp(queryToEscape) {\n      return queryToEscape.replace(/([.?*+^$[\\]\\\\(){}|-])/g, \"\\\\$1\");\n    }\n\n    return function(matchItem, query) {\n      return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : query;\n    };\n  });\nangular.module(\"template/accordion/accordion-group.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/accordion/accordion-group.html\",\n    \"<div class=\\\"accordion-group\\\">\\n\" +\n    \"  <div class=\\\"accordion-heading\\\" ><a class=\\\"accordion-toggle\\\" ng-click=\\\"isOpen = !isOpen\\\" accordion-transclude=\\\"heading\\\">{{heading}}</a></div>\\n\" +\n    \"  <div class=\\\"accordion-body\\\" collapse=\\\"!isOpen\\\">\\n\" +\n    \"    <div class=\\\"accordion-inner\\\" ng-transclude></div>  </div>\\n\" +\n    \"</div>\");\n}]);\n\nangular.module(\"template/accordion/accordion.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/accordion/accordion.html\",\n    \"<div class=\\\"accordion\\\" ng-transclude></div>\");\n}]);\n\nangular.module(\"template/alert/alert.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/alert/alert.html\",\n    \"<div class='alert' ng-class='type && \\\"alert-\\\" + type'>\\n\" +\n    \"    <button ng-show='closeable' type='button' class='close' ng-click='close()'>&times;</button>\\n\" +\n    \"    <div ng-transclude></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/carousel/carousel.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/carousel/carousel.html\",\n    \"<div ng-mouseenter=\\\"pause()\\\" ng-mouseleave=\\\"play()\\\" class=\\\"carousel\\\">\\n\" +\n    \"    <ol class=\\\"carousel-indicators\\\" ng-show=\\\"slides().length > 1\\\">\\n\" +\n    \"        <li ng-repeat=\\\"slide in slides()\\\" ng-class=\\\"{active: isActive(slide)}\\\" ng-click=\\\"select(slide)\\\"></li>\\n\" +\n    \"    </ol>\\n\" +\n    \"    <div class=\\\"carousel-inner\\\" ng-transclude></div>\\n\" +\n    \"    <a ng-click=\\\"prev()\\\" class=\\\"carousel-control left\\\" ng-show=\\\"slides().length > 1\\\">&lsaquo;</a>\\n\" +\n    \"    <a ng-click=\\\"next()\\\" class=\\\"carousel-control right\\\" ng-show=\\\"slides().length > 1\\\">&rsaquo;</a>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/carousel/slide.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/carousel/slide.html\",\n    \"<div ng-class=\\\"{\\n\" +\n    \"    'active': leaving || (active && !entering),\\n\" +\n    \"    'prev': (next || active) && direction=='prev',\\n\" +\n    \"    'next': (next || active) && direction=='next',\\n\" +\n    \"    'right': direction=='prev',\\n\" +\n    \"    'left': direction=='next'\\n\" +\n    \"  }\\\" class=\\\"item\\\" ng-transclude></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/dialog/message.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/dialog/message.html\",\n    \"<div class=\\\"modal-header\\\">\\n\" +\n    \"\t<h1>{{ title }}</h1>\\n\" +\n    \"</div>\\n\" +\n    \"<div class=\\\"modal-body\\\">\\n\" +\n    \"\t<p>{{ message }}</p>\\n\" +\n    \"</div>\\n\" +\n    \"<div class=\\\"modal-footer\\\">\\n\" +\n    \"\t<button ng-repeat=\\\"btn in buttons\\\" ng-click=\\\"close(btn.result)\\\" class=btn ng-class=\\\"btn.cssClass\\\">{{ btn.label }}</button>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/pagination/pagination.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/pagination/pagination.html\",\n    \"<div class=\\\"pagination\\\"><ul>\\n\" +\n    \"  <li ng-repeat=\\\"page in pages\\\" ng-class=\\\"{active: page.active, disabled: page.disabled}\\\"><a ng-click=\\\"selectPage(page.number)\\\">{{page.text}}</a></li>\\n\" +\n    \"  </ul>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/tooltip/tooltip-html-unsafe-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/tooltip/tooltip-html-unsafe-popup.html\",\n    \"<div class=\\\"tooltip {{placement}}\\\" ng-class=\\\"{ in: isOpen(), fade: animation() }\\\">\\n\" +\n    \"  <div class=\\\"tooltip-arrow\\\"></div>\\n\" +\n    \"  <div class=\\\"tooltip-inner\\\" ng-bind-html-unsafe=\\\"content\\\"></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/tooltip/tooltip-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/tooltip/tooltip-popup.html\",\n    \"<div class=\\\"tooltip {{placement}}\\\" ng-class=\\\"{ in: isOpen(), fade: animation() }\\\">\\n\" +\n    \"  <div class=\\\"tooltip-arrow\\\"></div>\\n\" +\n    \"  <div class=\\\"tooltip-inner\\\" ng-bind=\\\"content\\\"></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/popover/popover.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/popover/popover.html\",\n    \"<div class=\\\"popover {{placement}}\\\" ng-class=\\\"{ in: isOpen(), fade: animation() }\\\">\\n\" +\n    \"  <div class=\\\"arrow\\\"></div>\\n\" +\n    \"\\n\" +\n    \"  <div class=\\\"popover-inner\\\">\\n\" +\n    \"      <h3 class=\\\"popover-title\\\" ng-bind=\\\"title\\\" ng-show=\\\"title\\\"></h3>\\n\" +\n    \"      <div class=\\\"popover-content\\\" ng-bind=\\\"content\\\"></div>\\n\" +\n    \"  </div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/progressbar/bar.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/progressbar/bar.html\",\n    \"<div class=\\\"bar\\\" ng-class='type && \\\"bar-\\\" + type'></div>\");\n}]);\n\nangular.module(\"template/progressbar/progress.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/progressbar/progress.html\",\n    \"<div class=\\\"progress\\\"><progressbar ng-repeat=\\\"bar in bars\\\" width=\\\"bar.to\\\" old=\\\"bar.from\\\" animate=\\\"bar.animate\\\" type=\\\"bar.type\\\"></progressbar></div>\");\n}]);\n\nangular.module(\"template/rating/rating.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/rating/rating.html\",\n    \"<span ng-mouseleave=\\\"reset()\\\">\\n\" +\n    \"\t<i ng-repeat=\\\"number in range\\\" ng-mouseenter=\\\"enter(number)\\\" ng-click=\\\"rate(number)\\\" ng-class=\\\"{'icon-star': number <= val, 'icon-star-empty': number > val}\\\"></i>\\n\" +\n    \"</span>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/tabs/pane.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/tabs/pane.html\",\n    \"<div class=\\\"tab-pane\\\" ng-class=\\\"{active: selected}\\\" ng-show=\\\"selected\\\" ng-transclude></div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/tabs/tabs.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/tabs/tabs.html\",\n    \"<div class=\\\"tabbable\\\">\\n\" +\n    \"  <ul class=\\\"nav nav-tabs\\\">\\n\" +\n    \"    <li ng-repeat=\\\"pane in panes\\\" ng-class=\\\"{active:pane.selected}\\\">\\n\" +\n    \"      <a ng-click=\\\"select(pane)\\\">{{pane.heading}}</a>\\n\" +\n    \"    </li>\\n\" +\n    \"  </ul>\\n\" +\n    \"  <div class=\\\"tab-content\\\" ng-transclude></div>\\n\" +\n    \"</div>\\n\" +\n    \"\");\n}]);\n\nangular.module(\"template/typeahead/match.html\", []).run([\"$templateCache\", function($templateCache){\n  $templateCache.put(\"template/typeahead/match.html\",\n    \"<a tabindex=\\\"-1\\\" ng-bind-html-unsafe=\\\"match.label | typeaheadHighlight:query\\\"></a>\");\n}]);\n\nangular.module(\"template/typeahead/typeahead.html\", []).run([\"$templateCache\", function($templateCache) {\n  $templateCache.put(\"template/typeahead/typeahead.html\",\n    \"<ul class=\\\"typeahead dropdown-menu\\\" ng-style=\\\"{display: isOpen()&&'block' || 'none', top: position.top+'px', left: position.left+'px'}\\\">\\n\" +\n    \"    <li ng-repeat=\\\"match in matches\\\" ng-class=\\\"{active: isActive($index) }\\\" ng-mouseenter=\\\"selectActive($index)\\\">\\n\" +\n    \"        <a tabindex=\\\"-1\\\" ng-click=\\\"selectMatch($index)\\\" ng-bind-html-unsafe=\\\"match.label | typeaheadHighlight:query\\\"></a>\\n\" +\n    \"    </li>\\n\" +\n    \"</ul>\");\n}]);\n"
  },
  {
    "path": "client/js/lib/utils.js",
    "content": "\n//Array.find polyfill\nif (!Array.prototype.find) {\n  Object.defineProperty(Array.prototype, 'find', {\n    enumerable: false,\n    configurable: false,\n    writable: false,\n    value: function(predicate) {\n      for (var i=0; i < this.length; i++) {\n        if (predicate(this[i], i, this)) {\n          return this[i];\n        }\n      }\n      return void 0;\n    }\n  });\n}"
  },
  {
    "path": "client/js/lib/walk.js",
    "content": "// AST walker module for Mozilla Parser API compatible trees\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") return mod(exports); // CommonJS\n  if (typeof define == \"function\" && define.amd) return define([\"exports\"], mod); // AMD\n  mod((this.acorn || (this.acorn = {})).walk = {}); // Plain browser env\n})(function(exports) {\n  \"use strict\";\n\n  // A simple walk is one where you simply specify callbacks to be\n  // called on specific nodes. The last two arguments are optional. A\n  // simple use would be\n  //\n  //     walk.simple(myTree, {\n  //         Expression: function(node) { ... }\n  //     });\n  //\n  // to do something with all expressions. All Parser API node types\n  // can be used to identify node types, as well as Expression,\n  // Statement, and ScopeBody, which denote categories of nodes.\n  //\n  // The base argument can be used to pass a custom (recursive)\n  // walker, and state can be used to give this walked an initial\n  // state.\n  exports.simple = function(node, visitors, base, state) {\n    if (!base) base = exports.base;\n    function c(node, st, override) {\n      var type = override || node.type;\n      var found = visitors[type];\n      base[type](node, st, c);\n      if (found) found(node, st);\n    }\n    c(node, state);\n  };\n\n  // An ancestor walk builds up an array of ancestor nodes (including\n  // the current node) and passes them to the callback as the state parameter.\n  exports.ancestor = function(node, visitors, base, state) {\n    if (!base) base = exports.base;\n    if (!state) state = [];\n    function c(node, st, override) {\n      var type = override || node.type, found = visitors[type];\n      if (node != st[st.length - 1]) {\n        st = st.slice();\n        st.push(node);\n      }\n      base[type](node, st, c);\n      if (found) found(node, st);\n    }\n    c(node, state);\n  };\n\n  // A recursive walk is one where your functions override the default\n  // walkers. They can modify and replace the state parameter that's\n  // threaded through the walk, and can opt how and whether to walk\n  // their child nodes (by calling their third argument on these\n  // nodes).\n  exports.recursive = function(node, state, funcs, base) {\n    var visitor = funcs ? exports.make(funcs, base) : base;\n    function c(node, st, override) {\n      visitor[override || node.type](node, st, c);\n    }\n    c(node, state);\n  };\n\n  function makeTest(test) {\n    if (typeof test == \"string\")\n      return function(type) { return type == test; };\n    else if (!test)\n      return function() { return true; };\n    else\n      return test;\n  }\n\n  function Found(node, state) { this.node = node; this.state = state; }\n\n  // Find a node with a given start, end, and type (all are optional,\n  // null can be used as wildcard). Returns a {node, state} object, or\n  // undefined when it doesn't find a matching node.\n  exports.findNodeAt = function(node, start, end, test, base, state) {\n    test = makeTest(test);\n    try {\n      if (!base) base = exports.base;\n      var c = function(node, st, override) {\n        var type = override || node.type;\n        if ((start == null || node.start <= start) &&\n          (end == null || node.end >= end))\n          base[type](node, st, c);\n        if (test(type, node) &&\n          (start == null || node.start == start) &&\n          (end == null || node.end == end))\n          throw new Found(node, st);\n      };\n      c(node, state);\n    } catch (e) {\n      if (e instanceof Found) return e;\n      throw e;\n    }\n  };\n\n  // Find the innermost node of a given type that contains the given\n  // position. Interface similar to findNodeAt.\n  exports.findNodeAround = function(node, pos, test, base, state) {\n    test = makeTest(test);\n    try {\n      if (!base) base = exports.base;\n      var c = function(node, st, override) {\n        var type = override || node.type;\n        if (node.start > pos || node.end < pos) return;\n        base[type](node, st, c);\n        if (test(type, node)) throw new Found(node, st);\n      };\n      c(node, state);\n    } catch (e) {\n      if (e instanceof Found) return e;\n      throw e;\n    }\n  };\n\n  // Find the outermost matching node after a given position.\n  exports.findNodeAfter = function(node, pos, test, base, state) {\n    test = makeTest(test);\n    try {\n      if (!base) base = exports.base;\n      var c = function(node, st, override) {\n        if (node.end < pos) return;\n        var type = override || node.type;\n        if (node.start >= pos && test(type, node)) throw new Found(node, st);\n        base[type](node, st, c);\n      };\n      c(node, state);\n    } catch (e) {\n      if (e instanceof Found) return e;\n      throw e;\n    }\n  };\n\n  // Find the outermost matching node before a given position.\n  exports.findNodeBefore = function(node, pos, test, base, state) {\n    test = makeTest(test);\n    if (!base) base = exports.base;\n    var max;\n    var c = function(node, st, override) {\n      if (node.start > pos) return;\n      var type = override || node.type;\n      if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))\n        max = new Found(node, st);\n      base[type](node, st, c);\n    };\n    c(node, state);\n    return max;\n  };\n\n  // Used to create a custom walker. Will fill in all missing node\n  // type properties with the defaults.\n  exports.make = function(funcs, base) {\n    if (!base) base = exports.base;\n    var visitor = {};\n    for (var type in base) visitor[type] = base[type];\n    for (var type in funcs) visitor[type] = funcs[type];\n    return visitor;\n  };\n\n  function skipThrough(node, st, c) { c(node, st); }\n  function ignore(_node, _st, _c) {}\n\n  // Node walkers.\n\n  var base = exports.base = {};\n  base.Program = base.BlockStatement = function(node, st, c) {\n    for (var i = 0; i < node.body.length; ++i)\n      c(node.body[i], st, \"Statement\");\n  };\n  base.Statement = skipThrough;\n  base.EmptyStatement = ignore;\n  base.ExpressionStatement = function(node, st, c) {\n    c(node.expression, st, \"Expression\");\n  };\n  base.IfStatement = function(node, st, c) {\n    c(node.test, st, \"Expression\");\n    c(node.consequent, st, \"Statement\");\n    if (node.alternate) c(node.alternate, st, \"Statement\");\n  };\n  base.LabeledStatement = function(node, st, c) {\n    c(node.body, st, \"Statement\");\n  };\n  base.BreakStatement = base.ContinueStatement = ignore;\n  base.WithStatement = function(node, st, c) {\n    c(node.object, st, \"Expression\");\n    c(node.body, st, \"Statement\");\n  };\n  base.SwitchStatement = function(node, st, c) {\n    c(node.discriminant, st, \"Expression\");\n    for (var i = 0; i < node.cases.length; ++i) {\n      var cs = node.cases[i];\n      if (cs.test) c(cs.test, st, \"Expression\");\n      for (var j = 0; j < cs.consequent.length; ++j)\n        c(cs.consequent[j], st, \"Statement\");\n    }\n  };\n  base.ReturnStatement = function(node, st, c) {\n    if (node.argument) c(node.argument, st, \"Expression\");\n  };\n  base.ThrowStatement = function(node, st, c) {\n    c(node.argument, st, \"Expression\");\n  };\n  base.TryStatement = function(node, st, c) {\n    c(node.block, st, \"Statement\");\n    if (node.handler) c(node.handler.body, st, \"ScopeBody\");\n    if (node.finalizer) c(node.finalizer, st, \"Statement\");\n  };\n  base.WhileStatement = function(node, st, c) {\n    c(node.test, st, \"Expression\");\n    c(node.body, st, \"Statement\");\n  };\n  base.DoWhileStatement = base.WhileStatement;\n  base.ForStatement = function(node, st, c) {\n    if (node.init) c(node.init, st, \"ForInit\");\n    if (node.test) c(node.test, st, \"Expression\");\n    if (node.update) c(node.update, st, \"Expression\");\n    c(node.body, st, \"Statement\");\n  };\n  base.ForInStatement = function(node, st, c) {\n    c(node.left, st, \"ForInit\");\n    c(node.right, st, \"Expression\");\n    c(node.body, st, \"Statement\");\n  };\n  base.ForInit = function(node, st, c) {\n    if (node.type == \"VariableDeclaration\") c(node, st);\n    else c(node, st, \"Expression\");\n  };\n  base.DebuggerStatement = ignore;\n\n  base.FunctionDeclaration = function(node, st, c) {\n    c(node, st, \"Function\");\n  };\n  base.VariableDeclaration = function(node, st, c) {\n    for (var i = 0; i < node.declarations.length; ++i) {\n      var decl = node.declarations[i];\n      if (decl.init) c(decl.init, st, \"Expression\");\n    }\n  };\n\n  base.Function = function(node, st, c) {\n    c(node.body, st, \"ScopeBody\");\n  };\n  base.ScopeBody = function(node, st, c) {\n    c(node, st, \"Statement\");\n  };\n\n  base.Expression = skipThrough;\n  base.ThisExpression = ignore;\n  base.ArrayExpression = function(node, st, c) {\n    for (var i = 0; i < node.elements.length; ++i) {\n      var elt = node.elements[i];\n      if (elt) c(elt, st, \"Expression\");\n    }\n  };\n  base.ObjectExpression = function(node, st, c) {\n    for (var i = 0; i < node.properties.length; ++i)\n      c(node.properties[i].value, st, \"Expression\");\n  };\n  base.FunctionExpression = base.FunctionDeclaration;\n  base.SequenceExpression = function(node, st, c) {\n    for (var i = 0; i < node.expressions.length; ++i)\n      c(node.expressions[i], st, \"Expression\");\n  };\n  base.UnaryExpression = base.UpdateExpression = function(node, st, c) {\n    c(node.argument, st, \"Expression\");\n  };\n  base.BinaryExpression = base.AssignmentExpression = base.LogicalExpression = function(node, st, c) {\n    c(node.left, st, \"Expression\");\n    c(node.right, st, \"Expression\");\n  };\n  base.ConditionalExpression = function(node, st, c) {\n    c(node.test, st, \"Expression\");\n    c(node.consequent, st, \"Expression\");\n    c(node.alternate, st, \"Expression\");\n  };\n  base.NewExpression = base.CallExpression = function(node, st, c) {\n    c(node.callee, st, \"Expression\");\n    if (node.arguments) for (var i = 0; i < node.arguments.length; ++i)\n      c(node.arguments[i], st, \"Expression\");\n  };\n  base.MemberExpression = function(node, st, c) {\n    c(node.object, st, \"Expression\");\n    if (node.computed) c(node.property, st, \"Expression\");\n  };\n  base.Identifier = base.Literal = ignore;\n\n  // A custom walker that keeps track of the scope chain and the\n  // variables defined in it.\n  function makeScope(prev, isCatch) {\n    return {vars: Object.create(null), prev: prev, isCatch: isCatch};\n  }\n  function normalScope(scope) {\n    while (scope.isCatch) scope = scope.prev;\n    return scope;\n  }\n  exports.scopeVisitor = exports.make({\n    Function: function(node, scope, c) {\n      var inner = makeScope(scope);\n      for (var i = 0; i < node.params.length; ++i)\n        inner.vars[node.params[i].name] = {type: \"argument\", node: node.params[i]};\n      if (node.id) {\n        var decl = node.type == \"FunctionDeclaration\";\n        (decl ? normalScope(scope) : inner).vars[node.id.name] =\n        {type: decl ? \"function\" : \"function name\", node: node.id};\n      }\n      c(node.body, inner, \"ScopeBody\");\n    },\n    TryStatement: function(node, scope, c) {\n      c(node.block, scope, \"Statement\");\n      if (node.handler) {\n        var inner = makeScope(scope, true);\n        inner.vars[node.handler.param.name] = {type: \"catch clause\", node: node.handler.param};\n        c(node.handler.body, inner, \"ScopeBody\");\n      }\n      if (node.finalizer) c(node.finalizer, scope, \"Statement\");\n    },\n    VariableDeclaration: function(node, scope, c) {\n      var target = normalScope(scope);\n      for (var i = 0; i < node.declarations.length; ++i) {\n        var decl = node.declarations[i];\n        target.vars[decl.id.name] = {type: \"var\", node: decl.id};\n        if (decl.init) c(decl.init, scope, \"Expression\");\n      }\n    }\n  });\n\n});"
  },
  {
    "path": "client/js/locationctrl.js",
    "content": "\"use strict\";\n\nscanjsModule.controller('LocationCtrl', ['$scope', '$location', function LocationCtrl($scope, $location) {\n  $scope.tabBtnClass = function (page) {\n    var current = $location.path().substring(1) || 'scan';\n    //console.log(\"l\", $location.hash(), \"ls\", $location.hash().substring(2))\n    return page === current ? 'active' : '';\n  }\n}]);"
  },
  {
    "path": "client/js/main.js",
    "content": "\"use strict\";\n\nvar scanjsModule = angular.module('scanjs', ['ui.bootstrap', 'ngRoute']);\n\nscanjsModule.config(['$routeProvider',\n  function($routeProvider) {\n    $routeProvider.\n      when('/scan', {\n        templateUrl: 'partials/scan.html',\n        controller: 'ScanCtrl'\n      }).\n      when('/rules', {\n        templateUrl: 'partials/rules.html',\n        controller: 'RuleListCtrl'\n      }).\n      when('/experiment', {\n        templateUrl: 'partials/experiment.html',\n        controller: 'ExperimentCtrl'\n      }).\n      otherwise({\n        redirectTo: '/scan'\n      });\n  }]);"
  },
  {
    "path": "client/js/rulesctrl.js",
    "content": "\"use strict\";\n\nscanjsModule.controller('RuleListCtrl', ['$scope', 'ScanSvc', function RuleListCtrl($scope, ScanSvc) {\n  $scope.rulesFile = \"../common/rules.json\";\n  $scope.rules = []; //JSON rules object\n\n  document.getElementById(\"rule-file-input\").addEventListener(\"change\", function (evt) {\n    $scope.handleFileUpload(this.files);\n  });\n\n  function loadRulesFile(rulesFile) {\n    //TODO rewrite with $http()\n    var request = new XMLHttpRequest();\n    request.open('GET', rulesFile);\n\n    request.onload = function () {\n      if (request.status >= 200 && request.status < 400) {\n        $scope.rules = JSON.parse(request.responseText);\n\n        ScanSvc.loadRules($scope.rules);\n      } else {\n        console.log('Error loading ' + rules)\n      }\n      $scope.$apply();\n    };\n\n    request.onerror = function () {\n      console.log('Connection error while loading ' + rulesFile)\n    };\n    request.send();\n  }\n\n  $scope.handleFileUpload = function handleFileUpload(fileList) {\n\n    $scope.rulesFile = fileList[0].name;\n\n    var reader = new FileReader();\n    reader.onload = function () {\n      $scope.rules = JSON.parse(this.result);\n      ScanSvc.loadRules($scope.rules);\n      $scope.$apply();\n    }\n\n    reader.readAsText(fileList[0])\n  };\n\n  loadRulesFile($scope.rulesFile);\n}]);\n"
  },
  {
    "path": "client/js/scanctrl.js",
    "content": "\"use strict\";\n\nscanjsModule.controller('ScanCtrl', ['$scope', 'ScanSvc', function ScanCtrl($scope, ScanSvc) {\n  if (!document.getElementById(\"codeMirrorDiv\").children.length) {\n  $scope.codeMirror = new CodeMirror(document.getElementById('codeMirrorDiv'), {\n    mode: 'javascript',\n    lineNumbers: true,\n    theme: 'mdn-like',\n    value: \"\",\n    readOnly:true,\n    tabsize: 2,\n    styleActiveLine: true\n  });\n  }\n  $scope.codeMirrorManual = undefined;\n  $scope.inputFiles = [];\n  $scope.results=[];\n  $scope.errors=[];\n  $scope.filteredResults=[];\n  $scope.inputFilename=\"\";\n  $scope.issueList=[];\n  $scope.throbInput = false;\n  $scope.throbOutput = false;\n\n  var pending = 0;\n  var selectedFile = 0;\n  var codeMirror_index = 0;\n\n  document.getElementById(\"scan-file-input\").addEventListener(\"change\", function(evt) {\n    $scope.handleFileUpload(this.files);\n  });\n\n  $scope.run = function (source, filename) {\n    //empty last scan\n    $scope.results=[];\n    $scope.errors=[];\n    $scope.inputFiles.forEach(function (scriptFile, i) {\n      if (document.getElementById('doScan_'+i).checked) {\n        pending++;\n        $scope.throbOutput = true;\n        ScanSvc.newScan(scriptFile.name,scriptFile.asText());\n      }\n    });\n\n    //update UI\n    document.querySelector(\"#scan-input\").classList.toggle(\"hidden\",true);\n    document.querySelector(\"#scan-results\").classList.toggle(\"hidden\",false);\n    document.querySelector(\"#scan-output-rules\").classList.toggle(\"hidden\", false);\n    document.querySelector(\"#scan-output-files\").classList.toggle(\"hidden\", false);\n\n    //update navbar\n    document.querySelector(\"#scan-input-nav\").classList.toggle(\"active\",false);\n    document.querySelector(\"#scan-output-nav\").classList.toggle(\"active\",true);\n  }\n\n  $scope.updateIssueList = function(){\n    $scope.issueList = $scope.results.reduce(function(p, c) {\n      if ((c.type == 'finding') && (typeof p !== \"undefined\")) {\n        if (p.indexOf(c.rule.name) < 0) {\n          p.push(c.rule.name);\n        }\n        return p;\n      }\n    }, []);\n  }\n\n  $scope.filterResults=function(issue) {\n    if (!issue) {\n      $scope.filteredResults=$scope.results;\n    }\n    else {\n      if (typeof issue.name != \"undefined\") {\n        $scope.filteredResults = $scope.results.filter(function(result) {\n          return result.filename === issue.name;\n        });\n      } else {\n        $scope.filteredResults = $scope.results.filter(function(result) {\n          return result.rule.name == issue;\n        });\n      }\n    }\n  }\n\n  $scope.navShowInput = function () {\n    //show input tab, hide results\n    document.querySelector(\"#scan-input\").classList.toggle(\"hidden\", false);\n    document.querySelector(\"#scan-results\").classList.toggle(\"hidden\", true);\n    document.querySelector(\"#scan-output-rules\").classList.toggle(\"hidden\", true);\n    document.querySelector(\"#scan-output-files\").classList.toggle(\"hidden\", true);\n    //make input the active nav element\n    document.querySelector(\"#scan-input-nav\").classList.toggle(\"active\", true);\n    document.querySelector(\"#scan-output-nav\").classList.toggle(\"active\", false);\n  }\n\n  $scope.navShowOutput = function (filterIssue) {\n    //show input tab, hide results\n    document.querySelector(\"#scan-input\").classList.toggle(\"hidden\", true);\n    document.querySelector(\"#scan-results\").classList.toggle(\"hidden\", false);\n    document.querySelector(\"#scan-output-rules\").classList.toggle(\"hidden\", false);\n    document.querySelector(\"#scan-output-files\").classList.toggle(\"hidden\", false);\n    //make input the active nav element\n    document.querySelector(\"#scan-input-nav\").classList.toggle(\"active\", false);\n    document.querySelector(\"#scan-output-nav\").classList.toggle(\"active\", true);\n    $scope.filterResults(filterIssue);\n  }\n\n  $scope.handleFileUpload = function handleFileUpload(fileList) {\n    function handleMaybeZip() {\n      //packaged app case\n      var reader = new FileReader();\n      $scope.inputFilename = fileList[0].name;\n      reader.onload = function () {\n        var magic = new DataView(this.result).getUint32(0, true /* LE */);\n        if (magic !== 0x04034b50) { // magic marker per spec.\n          handleList();\n          return;\n        }\n        reader.onload = function() {\n          var zip = new JSZip(this.result);\n          $scope.inputFiles = zip.file(/\\.js$/);\n          $scope.$apply();\n        };\n        reader.readAsArrayBuffer(fileList[0]);\n      };\n      reader.readAsArrayBuffer(fileList[0].slice(0, 4));\n    };\n\n    function handleList() {\n      //uploading individual js file(s) case\n      $scope.inputFilename=\"Multiple files\";\n      var jsType = /(text\\/javascript|application\\/javascript|application\\/x-javascript)/;\n      var zip = new JSZip(); //create a jszip to manage the files\n\n      for (var i = 0; i < fileList.length; i++) {\n        var file = fileList[i];\n        console.log('adding file:',file.name)\n        if (!file.type.match(jsType)) {\n          console.log(\"Ignoring non-js file:\" + file.name + \"(\" + file.type + \")\")\n        }\n        var reader = new FileReader();\n        reader.readAsText(file);\n\n        reader.onload = (function (file) {\n          var fileName = file.name;\n          return function(e){\n            //add file to zip\n            zip.file(fileName, e.target.result)\n            $scope.inputFiles = zip.file(/.*/); //returns an array of files\n            $scope.$apply();\n\n          };\n        })(file)\n\n        reader.onerror = function (e) {\n          $scope.error = \"Could not read file\";\n          $scope.$apply();\n        }\n      }\n    };\n    $scope.throbInput = true;\n    $scope.$apply();\n    //enable fileselect div\n    //document.querySelector(\"#scan-intro\").classList.toggle(\"hidden\",true);\n    document.querySelector(\"#scan-files-selected\").classList.toggle(\"hidden\",false);\n\n    if (fileList.length === 1) {\n      handleMaybeZip();\n    }\n    else {\n      handleList();\n    }\n    $scope.throbInput = false;\n    $scope.$apply();\n  }\n\n  $scope.showFile = function (index) {\n    document.querySelector(\"#code-mirror-wrapper\").classList.toggle(\"hidden\",false);\n    if($scope.inputFiles.length<1){\n      return;\n    }\n    if(!index){\n      index=0;\n    }\n    if ($scope.inputFiles.length > 0) {\n      $scope.codeMirror.setValue($scope.inputFiles[index].asText());\n    }\n    codeMirror_index = index;\n    document.querySelector(\"#filename-badge\").textContent = $scope.inputFiles[index].name;\n  }\n\n  $scope.showResult = function (filename,line, col) {\n    document.querySelector(\"#code-mirror-wrapper\").classList.toggle(\"hidden\",false);\n    document.querySelector(\"#filename-badge\").textContent = filename;\n    var file = $scope.inputFiles.find(function(f){return f.name === filename});\n    $scope.codeMirror.setValue(file.asText());\n    $scope.codeMirror.setCursor(line - 1, col || 0);\n    $scope.codeMirror.focus();\n  };\n\n  $scope.saveState = function() {\n    var includedAttributes = ['line','filename','rule', 'desc', 'name', 'rec','type'];\n    /* A list of attributes we want include. Example:\n    line: ..\n    filename: ..\n    rule: {\n      desc: ..\n      name: ..\n      rec: ..\n      type: ..\n      }\n    }\n     */\n    var serializedResults = JSON.stringify($scope.results, includedAttributes);\n    localforage.setItem('results', serializedResults, function() { });\n\n    var serializedErrors = JSON.stringify($scope.errors);\n    localforage.setItem('errors', serializedErrors, function() { });\n\n    var serializedInputFiles = $scope.inputFiles.map( function(el) { return {data: el.asText(), name: el.name }; });\n    localforage.setItem(\"inputFiles\", JSON.stringify(serializedInputFiles), function(r) { });\n\n    var checkboxes = [];\n    for (var i=0; i < $scope.inputFiles.length; i++) {\n      checkboxes.push(document.getElementById(\"doScan_\" + i).checked);\n    }\n    localforage.setItem(\"checkboxes\", JSON.stringify(checkboxes));\n    localforage.setItem(\"cm_index\", JSON.stringify(codeMirror_index));\n  };\n\n  //TODO loadstate isn't called anymore, need to make it work with new workflow\n  //TODO -> call loadState() around in main.js, line 36 (using the scanCtrlScope) and expose \"reset\" button in the UI.\n  $scope.restoreState = function() {\n    var apply = false;\n    localforage.getItem('results', function (results_storage) {\n      $scope.results = JSON.parse(results_storage);\n      apply = true;\n      });\n    localforage.getItem('errors', function (errors_storage) {\n      if (errors_storage) {\n        $scope.errors = JSON.parse(errors_storage);\n        apply = true;\n      }\n    });\n    // restore files, by creating JSZip things :)\n    localforage.getItem(\"inputFiles\", function(inputFiles_storage) {\n      // mimic behavior from handleFileUpload\n      var files = JSON.parse(inputFiles_storage);\n      var zip = new JSZip();\n      files.forEach(function(file) {\n        zip.file(file.name, file.data);\n      });\n      $scope.inputFiles = zip.file(/.*/);\n\n      // nest checkbox import into the one for files, so we ensure the \"inputFiles.length\" check succeeds.\n      localforage.getItem(\"checkboxes\", function (checkboxes_storage) {\n        var checkboxes = JSON.parse(checkboxes_storage);\n\n        var ln=$scope.inputFiles.length\n        for (var i=0; i < ln; i++) {\n          document.getElementById(\"doScan_\" + i).checked = checkboxes[i];\n        }\n      });\n      apply = true;\n    });\n    if (apply) { $scope.$apply(); }\n  };\n\n  $scope.selectAll = function () {\n    var element;\n    var i = $scope.inputFiles.length-1;\n    while (element=document.getElementById('doScan_'+i)) {\n      element.checked = true;\n      i--;\n    }\n  };\n  $scope.selectNone = function () {\n    var element;\n    var i = $scope.inputFiles.length-1;\n    while (element=document.getElementById('doScan_'+i)) {\n      element.checked = false;\n      i--;\n    }\n  };\n  $scope.getSnippet = function (filename,line,numLines) {\n    var file = $scope.inputFiles.find(function (f) {\n      return f.name === filename\n    });\n    var content=file.asText();\n    return content.split('\\n').splice(line,line+numLines).join('\\n');\n  };\n\n  $scope.$on('NewResults', function (event, result) {\n    if (--pending <= 0) { $scope.throbOutput = false; }\n    if (Object.keys(result).length === 0) {\n      $scope.error = \"Empty result set (this can also be a good thing, if you test a simple file)\";\n      return\n    }\n    $scope.results=$scope.results.concat(result.findings);\n    $scope.filteredResults=$scope.results;\n    $scope.error = \"\";\n    $scope.updateIssueList();\n    /* this is likely a bug in angular or how we use it: the HTML template sometimes does not update\n       when we change the $scope variables without it noticing. $scope.$apply() enforces this. */\n    $scope.$apply();\n    $scope.saveState();\n  });\n\n  $scope.$on('ScanError', function (event, exception) {\n    if (--pending <= 0) { $scope.throbOutput = false; }\n    $scope.errors.push(exception);\n    $scope.updateIssueList();\n    $scope.$apply();\n    $scope.saveState();\n  });\n\n}]);\n"
  },
  {
    "path": "client/js/scanservice.js",
    "content": "\"use strict\";\n\nscanjsModule.factory('ScanSvc', ['$rootScope', '$http', function($rootScope, $http) {\n  var ScanService = {\n    //results:[],\n    ready:false,\n    rules:null,\n    init:function(rules){\n      this.rules=rules;\n      this.ready=true;\n    },\n    newScan: function(file,source) {\n      var fileName = file || 'inline';\n      this.scanWorker.postMessage({call: 'scan', arguments: [source, fileName]});\n    },\n    addResults: function(results) {\n      $rootScope.$broadcast('NewResults', results);\n    },\n    loadRules:function(ruleData){\n      this.rules=ruleData;\n      this.scanWorker.postMessage({call: 'updateRules', rules: ruleData});\n    }\n  };\n  ScanService.scanWorker = new Worker(\"js/scanworker.js\");\n  ScanService.scanWorker.addEventListener(\"message\", function (evt) {\n    if (('findings' in evt.data) && ('filename' in evt.data)) {\n      if (evt.data.findings.length > 0) {\n        if (evt.data.findings[0].type == 'error') {\n          $rootScope.$broadcast('ScanError', evt.data.findings[0])\n          return;\n        }\n      }\n      ScanService.addResults(evt.data);\n    }\n    else if ('error' in evt.data) {\n      // This is for errors in the worker, not in the scanning.\n      // Exceptions (like SyntaxErrors) when scanning files\n      // are in the findings.\n      var exception = evt.data.error;\n      if (e instanceof SyntaxError) {\n        $rootScope.$broadcast('ScanError', {filename: evt.data.filename, name: exception.name, loc: exception.loc, message: exception.message })\n      } else {\n        throw e; // keep throwing unexpected things.\n      }\n    }\n  });\n\n  ScanService.scanWorker.onerror = function (e) { console.log('ScanWorker Error: ', e) };\n\n  $http({method: 'GET', url: \"../common/rules.json\"}).\n    success(function(data, status, headers, config) {\n      ScanService.loadRules(data);\n    });\n\n  return ScanService;\n}]);\n"
  },
  {
    "path": "client/js/scanworker.js",
    "content": "\"use strict\";\n\n/* this makes sure that console.log can be used, even if it is undefined.\n   We won't see the message though, since this kind of postMessage isn't handled in scanservice.js  */\nif (typeof console === \"undefined\") {\n  console = {};\n  console.log = function consoleShim(mesg) {\n    postMessage({'type':'log', 'message': mesg});\n  }\n}\n\nimportScripts('lib/acorn.js',\n  'lib/walk.js',\n  'lib/acorn_loose.js',\n  '../../common/scan.js');\n\n//load default rules\n//ScanJS.loadRulesFile(\"../../common/rules.json\")\n\nonmessage = function (evt) {\n  if (evt.data.call === 'scan') {\n    var args = evt.data.arguments;\n    var source = args[0];\n    var rules;\n\n    var file = args[1];\n\n    var ast = acorn.parse(source, {locations: true});\n\n    var findings = ScanJS.scan(ast,file);\n    postMessage({\"filename\": file, \"findings\": findings});\n  }\n  else if(evt.data.call === 'updateRules'){\n    console.log('scanworker.js: Loaded '+evt.data.rules.length+\" rules.\")\n    ScanJS.loadRules(evt.data.rules)\n  }\n};\n"
  },
  {
    "path": "client/partials/experiment.html",
    "content": "<div id=\"experiment-wrapper\" class=\"panel\" ng-controller=\"ExperimentCtrl\">\n    <div class=\"col-md-5\">\n        <br>\n        <div class=\"codeMirror\" id=\"experiment-mirror\" ng-keyup=\"lastScan()\"></div>\n        <br>\n        <div class=\"row\">\n            <div class=\"col-md-6\">\n                <div class=\"input-group\">\n                    <input placeholder=\"custom rule: e.g., eval()\" ng-model=\"rule\" class=\"ng-pristine ng-valid form-control\" ng-keyup=\"runManualScan()\" type=\"text\">\n            <span class=\"input-group-btn\">\n                <button class=\"btn btn-default\" ng-click=\"add_placeholder_char()\"><span title=\"Paste a placeholder char to the form field.\">$_any</span></button>\n                <button class=\"btn btn-default\" ng-click=\"runManualScan()\">Scan with Custom Rule</button>\n            </span>\n                </div>\n            </div>\n            <div class=\"col-md-4 pull-right\">\n                <button class=\"btn btn-primary\" ng-click=\"runScan()\">Scan with Default Ruleset</button>\n            </div>\n        </div>\n    </div>\n    <div id=\"manual-results-wrapper\" class=\"col-md-6\" >\n        <h4>\n            Results\n        </h4>\n        <div ng-if=\"error\" id=\"parse-error\">\n            <div class=\"alert alert-danger\" role=\"alert\">\n                <h4>\n                    <a href=\"\" ng-click=\"showResult('', error.loc.line, error.loc.column)\">line {{error.loc.line}}</a>\n                    ::\n                    {{error.name}}\n                </h4>\n                {{error.message}}\n            </div>\n        </div>\n        <table class=\"table table-striped\" >\n            <thead>\n            <tr>\n                <th><a href=\"\" ng-click=\"predicate = 'line'; reverse=!reverse\">Line</a></th>\n                <th><a href=\"\" ng-click=\"predicate = 'rule.name'; reverse=!reverse\">Rule</a></th>\n                <th>Source</th>\n                <th>Description of Issue</th>\n            </tr>\n            </thead>\n            <tr ng-repeat='result in results| orderBy:predicate:reverse' title={{result.rule.rec}}>\n                <td><a ng-click=\"showResult(result.filename,result.line, result.col)\">Line {{result.line}}</a>\n                <td>{{result.rule.name }}</td>\n                <td>{{result.rule.source }}</td>\n                <td>{{result.rule.desc}}</a>\n                </td>\n            </tr>\n        </table>\n    </div>\n</div>"
  },
  {
    "path": "client/partials/rules.html",
    "content": "<div id=\"rules-wrapper\" class=\"panel container-fluid\">\n    <div id=\"rules-div\" class=\"col-md-12\">\n        <div ng-controller='RuleListCtrl'>\n\n\n            <div class=\"jumbotron\">\n                <h4>Load new rules</h4>\n                Load a JSON rules file to change rules:\n                <input type=\"file\" id=\"rule-file-input\" accept=\"application/json\">\n                <h4>Current rules</h4>\n                <span class=\"badge pull-right\">Number of Rules: {{rules.length}}</span>\n                <div class=\"table-responsive\">\n                    <table class=\"table table-striped\">\n                        <thead>\n                        <tr>\n                            <th>Rule Name</th>\n                            <th>Rule Description</th>\n                            <th>Rule Definition</th>\n                        </tr>\n                        </thead>\n                        <tbody>\n                        <tr ng-repeat='rule in rules' title={{rule.name}} id={{rule.name}}>\n                            <td>{{rule.name}}</td>\n                            <td>{{rule.desc}}</td>\n\n                            <td>\n                                <pre class=\"prettyprint lang-js\">{{rule.source}}</pre>\n                            </td>\n                        </tr>\n                        </tbody>\n                    </table>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "client/partials/scan.html",
    "content": "<div ng-controller=\"ScanCtrl\" id=\"scan-wrapper\" class=\"ng-scope panel panel-default\">\n    <!-- sidebar -->\n    <div class=\"col-md-2 sidebar\">\n        <ul class=\"nav nav-sidebar\">\n            <li id=\"scan-input-nav\" ng-click=\"navShowInput()\" class=\"active\">\n                <a>Input\n                    <span class=\"badge pull-right\">{{inputFiles.length}}</span>\n\t    <span ng-show=\"throbInput\" class=\"pull-right\">\n\t      <i class=\"rotating fa fa-spinner icon-throb\"></i>\n\t    </span>\n                </a>\n            </li>\n            <li id=\"scan-output-nav\">\n                <a ng-click=\"navShowOutput()\">Output\n                    <span class=\"badge pull-right\">{{results.length}}</span>\n\t    <span ng-show=\"throbOutput\" class=\"pull-right\">\n\t      <i class=\"rotating fa fa-spinner icon-throb\"></i>\n\t    </span>\n                </a>\n                <div id=\"scan-output-rules\" class=\"hidden\">\n                    <div class=\"bg-info\">Rules</div>\n                    <ul>\n                        <li ng-repeat=\"issue in issueList\">\n                            <a ng-click=\"navShowOutput(issue)\">{{issue}}</a>\n                        </li>\n                    </ul>\n                </div>\n                <div id=\"scan-output-files\" class=\"hidden\">\n                    <p class=\"bg-info\">Files</p>\n                    <ul>\n                        <li ng-repeat=\"file in inputFiles\">\n                            <a title=\"{{file.name}}\" ng-click=\"navShowOutput(file)\">{{file.name}}</a>\n                        </li>\n                    </ul>\n                </div>\n            </li>\n        </ul>\n    </div> <!-- sidebar -->\n\n    <div class=\"col-md-4 col-md-offset-2\">\n\n        <div id=\"scan-input\">\n            <div id=\"scan-intro\" >\n                <h4>Choose files to scan</h4>\n                <p>Select a list of .js files, or a zip file containing .js files.</p>\n                <input type=\"file\" id=\"scan-file-input\" multiple></p>\n\n                <div id=\"scan-files-selected\" class=\"hidden\">\n                    <p>\n                        Select files below, then <button class=\"btn btn-primary left-block\" ng-click='run()'>Scan</button>\n                    </p>\n                    <table class=\"table table-striped\">\n                        <thead>\n                        <tr>\n                            <th>Filename</th>\n                            <th>Enable (<a class=\"small\" ng-click=\"selectAll()\">Select All </a>,\n                                <a class=\"small\" ng-click=\"selectNone()\"> Select\n                                    None</a>)\n                            </th>\n                        </tr>\n                        </thead>\n                        <tbody>\n                        <tr ng-repeat=\"file in inputFiles track by $index\">\n                            <td><a href=\"#\" ng-click=\"showFile($index)\" title=\"Examine file in preview\">{{file.name}}</a>\n                            </td>\n                            <td><input type=\"checkbox\" id=\"doScan_{{ $index }}\"\n                                       title=\"Set this checkbox if you want the file included in your scans\" checked/></td>\n                        </tr>\n                        </tbody>\n                    </table>\n                </div>\n            </div>\n        </div>\n\n        <div id=\"scan-results\" class=\"hidden\">\n            <h4>Results <span class=\"badge pull-right\">{{filteredResults.length}}</span></h4>\n            <div id=\"results-wrapper\" ng-show=\"((results.length == 0) && (errors.length == 0))\">\n                Scan results will be loaded here.\n            </div>\n            <div id=\"results-wrapper\" ng-show=\"results\">\n                <table id=\"results-table\" class=\"table table-striped\">\n                    <thead>\n                    <tr>\n                        <th><a href=\"\" ng-click=\"predicate = 'filename'; reverse=!reverse\">Filename</a></th>\n                        <th><a href=\"\" ng-click=\"predicate = 'line'; reverse=!reverse\">Line</a></th>\n                        <th><a href=\"\" ng-click=\"predicate = 'rule.name'; reverse=!reverse\">Rule</a></th>\n                        <!--<th>Description of Issue</th>-->\n                    </tr>\n                    </thead>\n                    <tr ng-repeat='result in filteredResults| orderBy:predicate:reverse' title={{result.rule.rec}}>\n                        <td>{{result.filename}}</td>\n                        <td><a ng-click=\"showResult(result.filename,result.line, result.col)\">Line {{result.line}}</a></td>\n                        <td>{{result.rule.name }}</td>\n                        <!-- <td>{{result.rule.desc}}</a>-->\n                        </td>\n                    </tr>\n                </table>\n            </div>\n            <h4>Errors <span class=\"badge pull-right\">{{errors.length}}</span></h4>\n            <div id=\"error-wrapper\" ng-show=\"(errors.length > 0)\">\n                <table id=\"error-table\" class=\"table table-striped\">\n                    <thead>\n                    <tr>\n                        <th><a href=\"\" ng-click=\"predicate_e = 'filename'; reverse=!reverse\">Filename</a></th>\n                        <th><a href=\"\" ng-click=\"predicate_e = 'loc.line'; reverse=!reverse\">Line</a></th>\n                        <th><a href=\"\" ng-click=\"predicate_e = 'name'; reverse=!reverse\">Name</a></th>\n                        <th><a href=\"\" ng-click=\"predicate_e = 'message'; reverse=!reverse\">Message</a></th>\n                    </tr>\n                    </thead>\n                    <tr ng-repeat='error in errors| orderBy:predicate_e:reverse'>\n                        <td>{{ error.filename }}</td>\n                        <td><a ng-click=\"showResult(error.filename, error.loc.line, error.loc.col)\">Line {{error.loc.line }}</a></td>\n                        <td>{{ error.name }}</td>\n                        <td>{{ error.message }}</td>\n                        </td>\n                    </tr>\n                </table>\n            </div>\n\n        </div>\n\n    </div>\n    <div id=\"code-mirror-wrapper\" class=\"col-md-6\">\n        <div class=\"fixed\">\n        <h4>File Viewer <span id=\"filename-badge\" class=\"badge pull-right\"></span></h4>\n        <div class=\"codeMirrorDiv\" id=\"codeMirrorDiv\"></div>\n        </div>\n    </div>\n\n</div>"
  },
  {
    "path": "client/rules.readme.md",
    "content": "Rules maintained here:\nhttps://docs.google.com/a/mozilla.com/spreadsheets/d/1T14mvMMAspnvhKXxPNRBiV0x6QKZsXr8_b7eXJvEf_A/edit?alt=json#gid=0\n\nConverted to JSON with http://shancarter.github.io/mr-data-converter/\n\n"
  },
  {
    "path": "common/rules.json",
    "content": "[\n  {\n    \"name\": \"eval\",\n    \"source\": \"eval()\",\n    \"testhit\": \"eval('jsCode'+usercontrolledVal )\",\n    \"testmiss\": \"eval\",\n    \"desc\": \"Controlling of the first argument to eval(...) results in direct script execution.\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"global.eval\",\n    \"source\": \"$_any.eval()\",\n    \"testhit\": \"window.eval('jsCode'+usercontrolledVal )\",\n    \"testmiss\": \"eval\",\n    \"desc\": \"Controlling of the first argument to eval(...) results in direct script execution.\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"new Function\",\n    \"source\": \"new Function()\",\n    \"testhit\": \"new Function('jsCode'+usercontrolledVal ) ;\\n new Function('arg','arg2','jsCode'+usercontrolledVal )\",\n    \"testmiss\": \"Function\",\n    \"desc\": \"Controlling of the first argument to Function(...) results in direct script execution.\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"call Function\",\n    \"source\": \"Function()\",\n    \"testhit\": \"Function('jsCode'+usercontrolledVal ) ;\\n Function('arg','arg2','jsCode'+usercontrolledVal )\",\n    \"testmiss\": \"Function\",\n    \"desc\": \"Controlling of the first argument to Function(...) results in direct script execution.\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"setTimeout\",\n    \"source\": \"setTimeout()\",\n    \"testhit\": \"setTimeout('jsCode'+usercontrolledVal ,timeMs)\",\n    \"testmiss\": \"setTimeout\",\n    \"desc\": \"Calling setTimeout with a first argument as string (or string concatenation) with user input may lead to XSS\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"global.setTimeout\",\n    \"source\": \"$_any.setTimeout()\",\n    \"testhit\": \"global.setTimeout('jsCode'+usercontrolledVal ,timeMs)\",\n    \"testmiss\": \"setTimeout\",\n    \"desc\": \"Calling setTimeout with a first argument as string (or string concatenation) with user input may lead to XSS\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"setInterval\",\n    \"source\": \"setInterval()\",\n    \"testhit\": \"setInterval('jsCode'+usercontrolledVal ,timMs)\",\n    \"testmiss\": \"setInterval\",\n    \"desc\": \"Calling setInterval with a first argument as string (or string concatenation) with user input may lead to XSS\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"global.setInterval\",\n    \"source\": \"$_any.setInterval()\",\n    \"testhit\": \"global.setInterval('jsCode'+usercontrolledVal ,timMs)\",\n    \"testmiss\": \"setInterval\",\n    \"desc\": \"Calling setInterval with a first argument as string (or string concatenation) with user input may lead to XSS\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"setImmediate\",\n    \"source\": \"setImmediate()\",\n    \"testhit\": \"setImmediate('jsCode'+usercontrolledVal )\",\n    \"testmiss\": \"setImmediate\",\n    \"desc\": \"Calling setImmediate with a first argument as string (or string concatenation) with user input may lead to XSS\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"global.setImmediate\",\n    \"source\": \"$_any.setImmediate()\",\n    \"testhit\": \"global.setImmediate('jsCode'+usercontrolledVal )\",\n    \"testmiss\": \"setImmediate\",\n    \"desc\": \"Calling setImmediate with a first argument as string (or string concatenation) with user input may lead to XSS\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"execScript\",\n    \"source\": \"execScript()\",\n    \"testhit\": \"execScript('jsCode'+usercontrolledVal ,'JScript')\",\n    \"testmiss\": \"execSript\",\n    \"desc\": \"Using execScript with user input leads to Cross Site Scripting (Internet Explorer only)\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"crypto.generateCRMFRequest\",\n    \"source\": \"crypto.generateCRMFRequest()\",\n    \"testhit\": \"crypto.generateCRMFRequest('CN=0',0,0,null,'jsCode'+usercontrolledVal,384,null,'rsa-dual-use')\",\n    \"testmiss\": \"crypto.generateCRMFRequest\",\n    \"desc\": \"Due to a bug in Firefox, this function may be used as an obfuscated way to call execute scripts from strings (like eval). This may lead to Cross-Site-Scripting.\",\n    \"threat\": \"Execution Sink\"\n  },\n  {\n    \"name\": \"document.write \",\n    \"source\": \"document.write()\",\n    \"testhit\": \"document.write('test')\",\n    \"testmiss\": \"document.write\",\n    \"desc\": \"Writing user specified HTML to the DOM may lead to Cross-Site Scripting\",\n    \"threat\": \"HTMLElement Sink\"\n  },\n  {\n    \"name\": \"document.writeln\",\n    \"source\": \"document.writeln()\",\n    \"testhit\": \"document.writeln('test')\",\n    \"testmiss\": \"document.writeln\",\n    \"desc\": \"Writing user specified HTML to the DOM may lead to Cross-Site Scripting\",\n    \"threat\": \"HTMLElement Sink\"\n  },\n  {\n    \"name\": \".innerHTML \",\n    \"source\": \"$_any.innerHTML=$_unsafe\",\n    \"testhit\": \"a.innerHTML=foo;a.innerHTML=foo+'bar'\",\n    \"testmiss\": \"a.innerHTML='foo';a.innerHTML='foo'+'bar'\",\n    \"desc\": \"Writing user specified HTML to the DOM may lead to Cross-Site Scripting\",\n    \"threat\": \"HTMLElement Sink\"\n  },\n  {\n    \"name\": \".outerHTML \",\n    \"source\": \"$_any.outerHTML=$_unsafe\",\n    \"testhit\": \"a.outerHTML=foo\",\n    \"testmiss\": \"outerHTML\",\n    \"desc\": \"Writing user specified HTML to the DOM may lead to Cross-Site Scripting\",\n    \"threat\": \"HTMLElement Sink\"\n  },\n  {\n    \"name\": \"insertAdjacentHTML()\",\n    \"source\": \"insertAdjacentHTML()\",\n    \"testhit\": \"insertAdjacentHTML(foo)\",\n    \"testmiss\": \"insertAdjacentHTML\",\n    \"desc\": \"Writing user specified HTML to the DOM may lead to Cross-Site Scripting\",\n    \"threat\": \"HTMLElement Sink\"\n  },\n  {\n    \"name\": \"$_any.createContextualFragment\",\n    \"source\": \"$_any.createContextualFragment\",\n    \"testhit\": \"foo.createContextualFragment\",\n    \"testmiss\": \"createContextualFragment\",\n    \"desc\": \"\",\n    \"threat\": \"HTMLElement Sink\"\n  },\n  {\n    \"name\": \"$_any.location=\",\n    \"source\": \"$_any.location=$_unsafe\",\n    \"testhit\": \"foo.location=bar\",\n    \"testmiss\": \"foo.location==bar\",\n    \"desc\": \"Assignments to the document's location may lead to spoofing and unexpected redirects. Furthermore, it can cause Cross-Site Scripting, when javascipt: URIs are used\",\n    \"threat\": \"Location Sink\"\n  },\n  {\n    \"name\": \"$_any.href=\",\n    \"source\": \"$_any.href=$_unsafe\",\n    \"testhit\": \"foo.href=bar\",\n    \"testmiss\": \"foo.href==bar\",\n    \"desc\": \"Assignments to the document's location may lead to spoofing and unexpected redirects. Furthermore, it can cause Cross-Site Scripting, when javascipt: URIs are used\",\n    \"threat\": \"Location Sink\"\n  },\n  {\n    \"name\": \"$_any.pathname=\",\n    \"source\": \"$_any.pathname=$_unsafe\",\n    \"testhit\": \"foo.pathname=bar\",\n    \"testmiss\": \"foo.pathname==bar\",\n    \"desc\": \"Assignments to the document's location may lead to spoofing and unexpected redirects.\",\n    \"threat\": \"Location Sink\"\n  },\n  {\n    \"name\": \"$_any.search=\",\n    \"source\": \"$_any.search=$_unsafe\",\n    \"testhit\": \"foo.search=bar\",\n    \"testmiss\": \"foo.search==bar\",\n    \"desc\": \"Assignments to the document's location may lead to spoofing and unexpected redirects.\",\n    \"threat\": \"Location Sink\"\n  },\n  {\n    \"name\": \"$_any.protocol=\",\n    \"source\": \"$_any.protocol=$_unsafe\",\n    \"testhit\": \"foo.protocol=bar\",\n    \"testmiss\": \"foo.protocol==bar\",\n    \"desc\": \"Assignments to the document's location may lead to spoofing and unexpected redirects.\",\n    \"threat\": \"Location Sink\"\n  },\n  {\n    \"name\": \"$_any.hostname=\",\n    \"source\": \"$_any.hostname=$_unsafe\",\n    \"testhit\": \"foo.hostname=bar\",\n    \"testmiss\": \"foo.hostname==bar\",\n    \"desc\": \"Assignments to the document's location may lead to spoofing and unexpected redirects.\",\n    \"threat\": \"Location Sink\"\n  },\n  {\n    \"name\": \"$_any.src=\",\n    \"source\": \"$_any.src=$_unsafe\",\n    \"testhit\": \"bar.src=foo\",\n    \"testmiss\": \"src.bar\",\n    \"desc\": \"Assignments to the document's location may lead to spoofing and unexpected redirects. It may also lead to script execution, depending on the affected HTML Tag (i.e. object)\",\n    \"threat\": \"Location Sink\"\n  },\n  {\n    \"name\": \"parseFromString()\",\n    \"source\": \"parseFromString()\",\n    \"testhit\": \"parseFromString(bar+'bar')\",\n    \"testmiss\": \"parseFromString\",\n    \"desc\": \"This function creates a DOM from strings. Depending on their source it is likely important to sanitize it before an insertion into the DOM happens\",\n    \"threat\": \"Interesting Function\"\n  },\n  {\n    \"name\": \"addEventListener()\",\n    \"source\": \"$_any.addEventListener()\",\n    \"testhit\": \"foo.addEventListener(bar+'bar')\",\n    \"testmiss\": \"addEventListener\",\n    \"desc\": \"Certain events (like message) may cause untrusted third party data\",\n    \"threat\": \"Input Sink\"\n  },\n  {\n    \"name\": \"message handler\",\n    \"source\": \"$_any.addEventListener('message')\",\n    \"testhit\": \"window.addEventListener('message', receiveMessage, false); \",\n    \"testmiss\": \"window.addEventListener('notmessage', receiveMessage, false); \",\n    \"desc\": \"Check to make sure message handler validates to protect against malicious cross-origin message.\",\n    \"threat\": \"Input Validation\"\n  },\n  {\n    \"name\": \"onmessage=\",\n    \"source\": \"onmessage=$_any\",\n    \"testhit\": \"onmessage=bar\",\n    \"testmiss\": \"onmessage\",\n    \"desc\": \"Check to make sure message handler validates to protect against malicious cross-origin message.\",\n    \"threat\": \"Input Validation\"\n  },\n  {\n    \"name\": \"Indexeddb\",\n    \"source\": \"indexedDB\",\n    \"testhit\": \"indexedDB.open('MyTestDatabase');\",\n    \"testmiss\": \" 'indexeddb'\",\n    \"desc\": \"Client-side data storage.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"localStorage\",\n    \"source\": \"localStorage\",\n    \"testhit\": \"localStorage.setItem('name', 'user1'); \",\n    \"testmiss\": \" 'localStorage'\",\n    \"desc\": \"Client-side data storage.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"sessionStorage\",\n    \"source\": \"sessionStorage\",\n    \"testhit\": \"sessionStorage.setItem('name', 'user1'); \",\n    \"testmiss\": \" 'sessionStorage'\",\n    \"desc\": \"Client-side data storage.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"Indexeddb\",\n    \"source\": \"$_any.indexedDB\",\n    \"testhit\": \"window.indexedDB.open('MyTestDatabase');\",\n    \"testmiss\": \" 'indexeddb'\",\n    \"desc\": \"Client-side data storage.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"localStorage\",\n    \"source\": \"$_any.localStorage\",\n    \"testhit\": \"window.localStorage.setItem('name', 'user1'); \",\n    \"testmiss\": \" 'localStorage'\",\n    \"desc\": \"Client-side data storage.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"sessionStorage\",\n    \"source\": \"$_any.sessionStorage\",\n    \"testhit\": \"window.sessionStorage.setItem('name', 'user1'); \",\n    \"testmiss\": \" 'sessionStorage'\",\n    \"desc\": \"Client-side data storage.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"DomParser\",\n    \"source\": \"$_any.parseFromString()\",\n    \"testhit\": \"window.doc = parser.parseFromString(someVar, 'text/html'); \",\n    \"testmiss\": \"parseFromString()\",\n    \"desc\": \"Writing user specified HTML to the DOM may lead to Cross-Site Scripting\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"start mozActivity\",\n    \"source\": \"new MozActivity()\",\n    \"testhit\": \"new MozActivity({type:'pick'})\",\n    \"testmiss\": \"MozActivity +1\",\n    \"desc\": \"This function creates new Web Activities and can transfer data from one app to another\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"handle mozActivity\",\n    \"source\": \"$_any.mozSetMessageHandler('activity')\",\n    \"testhit\": \"navigator.mozSetMessageHandler('activity',callback)\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function allows registering message handlers for Web Activities.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"handle system message\",\n    \"source\": \"$_any.mozSetMessageHandler()\",\n    \"testhit\": \"navigator.mozSetMessageHandler()\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function allows registering message handlers for Web Activities.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"access datastore\",\n    \"source\": \"navigator.getDataStores\",\n    \"testhit\": \"navigator.getDataStores()\",\n    \"testmiss\": \"\",\n    \"desc\": \"This API allows access to datastores that may be used to serve or retrieve data from third party apps\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"Make InterAppCommunication\",\n    \"source\": \"$_any.connect()\",\n    \"testhit\": \"app.connect('bluetoothTransfercomms')\",\n    \"testmiss\": \"\",\n    \"desc\": \"\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"Recieve InterAppCommunication\",\n    \"source\": \"$_any.setMessageHandler('connect')\",\n    \"testhit\": \" navigator.setMessageHandler('connect',callback)\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function sets a handler for inter app communication messages. In general, mozSetMessageHandler allows handling WebActivities. The origin of the activity and its data might be untrusted.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"alarms permission\",\n    \"source\": \"navigator.mozAlarms\",\n    \"testhit\": \"navigator.mozAlarms\",\n    \"testmiss\": \"MozAlarms\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications and allows setting and editing alarms. Frequent alarms might prevent power saving and drain the battery.\",\n    \"threat\": \"Privileged API\"\n  },\n  {\n    \"name\": \"attention permission\",\n    \"source\": \"window.open($_any, $_any, 'attention')\",\n    \"testhit\": \"window.open('oncall.html', '', 'attention');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Attention popups fill the whole display. URLs pointing to javascript: and data: protocols can lead to XSS. Popups can also confuse and misdirect users.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-capture permission\",\n    \"source\": \"navigator.getUserMedia\",\n    \"testhit\": \"navigator.getUserMedia({audio:true});\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function allows prompting for audio and video recording.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-alarm permission\",\n    \"source\": \"$_any.mozAudioChannelType=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannelType = 'alarm'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-content permission\",\n    \"source\": \"$_any.mozAudioChannelType=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannelType = 'content'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-normal permission\",\n    \"source\": \"$_any.mozAudioChannelType=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannelType = 'normal'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-notification permission\",\n    \"source\": \"$_any.mozAudioChannelType=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannelType = 'notification'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-publicnotification permission\",\n    \"source\": \"$_any.mozAudioChannelType=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannelType = 'publicnotification'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-ringer permission\",\n    \"source\": \"$_any.mozAudioChannelType=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannelType = 'ringer'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-telephony permission\",\n    \"source\": \"$_any.mozAudioChannelType=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannelType = 'telephony'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-content permission\",\n    \"source\": \"$_any.mozAudioChannel=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannel = 'content';\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-alarm permission\",\n    \"source\": \"$_any.mozAudioChannel=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannel = 'alarm'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-normal permission\",\n    \"source\": \"$_any.mozAudioChannel=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannel = 'normal'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-notification permission\",\n    \"source\": \"$_any.mozAudioChannel=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannel = 'notification'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-publicnotification permission\",\n    \"source\": \"$_any.mozAudioChannel=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannel = 'publicnotification'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-ringer permission\",\n    \"source\": \"$_any.mozAudioChannel=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannel = 'ringer'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"audio-channel-telephony permission\",\n    \"source\": \"$_any.mozAudioChannel=$_any\",\n    \"testhit\": \"ringtonePlayer.mozAudioChannel = 'telephony'\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"background-sensors permission\",\n    \"source\": \"$_any.addEventListener('deviceproximity', callback)\",\n    \"testhit\": \"window.addEventListener('deviceproximity', callback)\",\n    \"testmiss\": \"\",\n    \"desc\": \"This exercizes the proximity API to check whether the phone is close to something (i.e. held to the ear).\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"bluetooth permission\",\n    \"source\": \"navigator.mozBluetooth\",\n    \"testhit\": \"window.navigator.mozBluetooth\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"browser permission\",\n    \"source\": \"$_any.setAttribute('mozbrowser')\",\n    \"testhit\": \"iframe.setAttribute('mozbrowser', true);\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications. MozBrowser frames have specific, elevated permissions.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"camera permission\",\n    \"source\": \"$_any.mozCameras\",\n    \"testhit\": \"this.mozCameras[0].onShutter = this.onShutter;\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function allows reading and modifying camera settings and is only available to higher privileged Firefox OS application.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"cellbroadcast permission\",\n    \"source\": \"$_any.addEventListener('cellbroadcastmsgchanged')\",\n    \"testhit\": \"window.addEventListener('cellbroadcastmsgchanged', callback)\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"contacts permission\",\n    \"source\": \"$_any.mozContacts\",\n    \"testhit\": \"navigator.mozContacts.oncontactchange = callback\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function allows reading and modifying the phone's contacts. It is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"desktop-notification permission\",\n    \"source\": \"new Notification()\",\n    \"testhit\": \"var notification = new Notification(title, {body: body, icon: iconURL});\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function generate notifications from the app. It is only available to higher privileged Firefox OS applications. \",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"device-storage catch-all\",\n    \"source\": \"$_any.getDeviceStorage\",\n    \"testhit\": \"apps = navigator.getDeviceStorage('apps');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"device-storage:apps permission\",\n    \"source\": \"$_any.getDeviceStorage('apps')\",\n    \"testhit\": \"apps = navigator.getDeviceStorage('apps');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"device-storage:crashes permission\",\n    \"source\": \"$_any.getDeviceStorage('crashes')\",\n    \"testhit\": \"crashes = navigator.getDeviceStorage('crashes');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"device-storage:music permission\",\n    \"source\": \"$_any.getDeviceStorage('music')\",\n    \"testhit\": \"storage = navigator.getDeviceStorage('music');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"device-storage:pictures permission\",\n    \"source\": \"$_any.getDeviceStorage('pictures')\",\n    \"testhit\": \"this.image = navigator.getDeviceStorage('pictures');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"device-storage:sdcard permission\",\n    \"source\": \"$_any.getDeviceStorage('sdcard')\",\n    \"testhit\": \"var storage = navigator.getDeviceStorage('sdcard');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"device-storage:videos permission\",\n    \"source\": \"$_any.getDeviceStorage('videos')\",\n    \"testhit\": \"this.video = navigator.getDeviceStorage('videos');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"downloads permission\",\n    \"source\": \"navigator.mozDownloadManager\",\n    \"testhit\": \"navigator.mozDownloadManager\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"embed-apps permission\",\n    \"source\": \"$_any.setAttribute('mozapp')\",\n    \"testhit\": \"browser.setAttribute('mozapp', config.manifestURL);\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"fmradio permission\",\n    \"source\": \"navigator.mozFMRadio\",\n    \"testhit\": \"navigator.mozFMRadio\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"geolocation permission\",\n    \"source\": \"navigator.geolocation\",\n    \"testhit\": \"var geolocation = navigator.geolocation;\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function gives access to information about the user's location.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"idle permission\",\n    \"source\": \"navigator.addIdleObserver\",\n    \"testhit\": \"navigator.addIdleObserver\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"input permission\",\n    \"source\": \"navigator.mozInputMethod\",\n    \"testhit\": \"window.navigator.mozInputMethod\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"input-manage permission\",\n    \"source\": \"$_any.mgmt.hide()\",\n    \"testhit\": \"navigator.mozInputMethod.mgmt.hide()\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"mobileconnection permission\",\n    \"source\": \"navigator.mozMobileConnections\",\n    \"testhit\": \"navigator.mozMobileConnections\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"mobilenetwork permission\",\n    \"source\": \"$_any.lastKnownHomeNetwork\",\n    \"testhit\": \"connection.lastKnownHomeNetwork && connection.lastKnownNetwork\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"mobilenetwork permission\",\n    \"source\": \"$_any.lastKnownNetwork\",\n    \"testhit\": \"connection.lastKnownHomeNetwork && connection.lastKnownNetwork\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"network-events permission\",\n    \"source\": \"$_any.addEventListener('moznetworkupload')\",\n    \"testhit\": \"window.addEventListener('moznetworkupload', uploadHandler);\",\n    \"testmiss\": \"window.addEventListener('moznetworkdownload', downloadHandler);\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"network-events permission\",\n    \"source\": \"$_any.addEventListener('moznetworkdownload')\",\n    \"testhit\": \"window.addEventListener('moznetworkdownload', downloadHandler);\",\n    \"testmiss\": \"window.addEventListener('moznetworkupload', uploadHandler);\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"networkstats-manage permission\",\n    \"source\": \"navigator.mozNetworkStats\",\n    \"testhit\": \"var networks = navigator.mozNetworkStats.getAvailableNetworks();\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"nfc permission\",\n    \"source\": \"navigator.mozNfc\",\n    \"testhit\": \"navigator.mozNfc\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"open-remote-window permission\",\n    \"source\": \"window.open($_any,$_any, 'remote=true');\",\n    \"testhit\": \"window.open(target.dataset.url, '_blank', 'remote=true');\",\n    \"testmiss\": \"\",\n    \"desc\": \"Not sure if testhit example is right here..\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"permissions permission\",\n    \"source\": \"navigator.mozPermissionSettings\",\n    \"testhit\": \"var mozPerms = navigator.mozPermissionSettings;\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications. It allows managing and revoking apps permissions.\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"phonenumberservice permission\",\n    \"source\": \"navigator.mozPhoneNumberService\",\n    \"testhit\": \"var service = navigator.mozPhoneNumberService;\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"power permission\",\n    \"source\": \"navigator.mozPower\",\n    \"testhit\": \"navigator.mozPower\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications. It allows access to power management features.\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"settings permission\",\n    \"source\": \"navigator.mozSettings\",\n    \"testhit\": \"window.navigator.mozSettings\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensThis function is only available to higher privileged Firefox OS applications. It allows access to the phone's settingsitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"sms permission\",\n    \"source\": \"navigator.mozMobileMessage\",\n    \"testhit\": \"navigator.mozMobileMessage\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"speaker-control permission\",\n    \"source\": \"new MozSpeakerManager()\",\n    \"testhit\": \"var mgr = new MozSpeakerManager();\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"systemXHR permission\",\n    \"source\": \"new XMLHttpRequest({mozSystem: true});\",\n    \"testhit\": \"var xhr = new XMLHttpRequest({mozSystem: true});\",\n    \"testmiss\": \"\",\n    \"desc\": \"XMLHttpRequests of type system may contact and read data from third party origins\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"tcp-socket permission\",\n    \"source\": \"navigator.mozTCPSocket;\",\n    \"testhit\": \"var TCPSocket = navigator.mozTCPSocket;\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function allows creating connections and communicating with remote servers.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"telephony permission\",\n    \"source\": \"navigator.mozTelephony\",\n    \"testhit\": \"navigator.mozTelephony.stopTone(this.serviceId);\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"time permission\",\n    \"source\": \"navigator.mozTime\",\n    \"testhit\": \"_mozTime = window.navigator.mozTime;\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"video-capture permission\",\n    \"source\": \"navigator.getUserMedia\",\n    \"testhit\": \"navigator.getUserMedia({video:true});\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function allows prompting for audio and video recording.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"voicemail permission\",\n    \"source\": \"navigator.mozVoicemail\",\n    \"testhit\": \"var voicemail = navigator.mozVoicemail;\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications. It allows controlling the phone's Voicemail features.\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"wappush permission\",\n    \"source\": \"$_any.mozSetMessageHandler('wappush-received')\",\n    \"testhit\": \"window.navigator.mozSetMessageHandler('wappush-received', wpm_onWapPushReceived);\",\n    \"testmiss\": \"\",\n    \"desc\": \"This specifies a handler for WAP Push notifications. In general, mozSetMessageHandler allows handling WebActivities. The origin of the activity and its data might be untrusted.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"webapps manage\",\n    \"source\": \"$_any.mgmt\",\n    \"testhit\": \"var req = navigator.mozApps.mgmt.getAll();\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications. It allows managing the phone's app.\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"wifi-manage permission\",\n    \"source\": \"navigator.mozWifiManager\",\n    \"testhit\": \"navigator.mozWifiManager\",\n    \"testmiss\": \"\",\n    \"desc\": \"This function is only available to higher privileged Firefox OS applications. It allows managing the Wifi features of the phone.\",\n    \"threat\": \"Certified API\"\n  },\n  {\n    \"name\": \"mozkeyboard\",\n    \"source\": \"navigator.mozKeyboard\",\n    \"testhit\": \"var keyboard = navigator.mozKeyboard || navigator.mozInputMethod;\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"cell broadcasts\",\n    \"source\": \"navigator.mozCellBroadcast\",\n    \"testhit\": \"navigator.mozCellBroadcast.onreceived = this.show.bind(this);\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"mobile connection api\",\n    \"source\": \"navigator.mozMobileConnection\",\n    \"testhit\": \"var conn = window.navigator.mozMobileConnection || window.navigator.mozMobileConnections\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"notification api\",\n    \"source\": \"navigator.mozNotification\",\n    \"testhit\": \"var notification = navigator.mozNotification.createNotification(title, body, icon);\",\n    \"testmiss\": \"\",\n    \"desc\": \"Usage of sensitive API\",\n    \"threat\": \"\"\n  },\n  {\n    \"name\": \"assignment typo\",\n    \"source\": \"if($_contains('AssignmentExpression'));\",\n    \"testhit\": \"if(x=y){};\",\n    \"testmiss\": \"if(x==y){x=0;}\",\n    \"desc\": \"Unintended use of AssignmentExpression in If Statement\",\n    \"threat\": \"Typo\"\n  }\n]"
  },
  {
    "path": "common/scan.js",
    "content": "(function (mod) {\n\n  // CommonJS\n  if (typeof exports == \"object\" && typeof module == \"object\")\n    return mod(\n      exports,\n      require('../client/js/lib/walk.js')\n    );\n\n  // AMD\n  if (typeof define == \"function\" && define.amd)\n    return define([\n      \"exports\",\n      \"../client/js/lib/walk.js\"\n    ], mod);\n\n  // Plain browser env\n  mod(this.ScanJS || (this.ScanJS = {}), this.acorn.walk);\n})(function (exports, walk) {\n  \"use strict\";\n\n  // Default parser, override this object to change*\n  // needs parser.parse to produce an AST\n  // and parser.walk the walk.js lib\n\n  var parser = {};\n  if (typeof acorn !== 'undefined' && acorn ){\n    parser = acorn;\n  }\n\n\n  var rules = {};\n  var results = [];\n\n  var aw_found = function (rule, node) {\n\n    results.push({\n      type: 'finding',\n      rule: rule,\n      filename: results.filename,\n      line: node.loc.start.line,\n      col: node.loc.start.col\n    });\n\n    aw_found_callback(rule, node);\n  };\n  var aw_found_callback = function () {\n  };\n\n  var templateRules = {\n    identifier: {\n      nodeType: \"Identifier\",\n      test: function (testNode, node) {\n        if (node.type == \"Identifier\" && node.name == testNode.name) {\n          return true;\n        }\n      }\n    },\n    property: {\n      nodeType: \"MemberExpression\",\n      test: function (testNode, node) {\n        // foo.bar & foo['bar'] create different AST but mean the same thing\n\n        var testName = testNode.property.type == 'Identifier' ? testNode.property.name : testNode.property.value;\n        if (node.property && (node.property.name == testName || node.property.value == testName)) {\n          return true;\n        }\n      }\n    },\n    object: {\n      nodeType: \"MemberExpression\",\n      test: function (testNode, node) {\n        // foo.bar & foo['bar'] create different AST but mean the same thing\n        if (node.object.name == testNode.object.name) {\n          return true;\n        }\n      }\n    },\n    objectproperty: {\n      nodeType: \"MemberExpression\",\n      test: function (testNode, node) {\n        // foo.bar & foo['bar'] create different AST but mean the same thing\n        var testName = testNode.property.type == 'Identifier' ? testNode.property.name : testNode.property.value;\n\n        if ((node.property && (node.property.name == testName || node.property.value == testName)) &&\n          (node.object.name == testNode.object.name ||  // this matches the foo in foo.bar\n            (node.object.property && node.object.property.name == testNode.object.name)  )) { //this matches foo in nested objects e.g. baz.foo.bar\n          return true;\n        }\n      }\n    },\n    new: {\n      nodeType: \"NewExpression\",\n      test: function (testNode, node) {\n        if (node.callee.name == testNode.callee.name) {\n          return true;\n        }\n      }\n    },\n    call: {\n      nodeType: \"CallExpression\",\n      test: function (testNode, node) {\n        // matches foo()\n        if (node.callee.type == 'Identifier' &&\n          node.callee.name == testNode.callee.name) {\n          return true;\n        }\n      }\n    },\n    propertycall: {\n      nodeType: \"CallExpression\",\n      test: function (testNode, node) {\n        if (templateRules.property.test(testNode.callee, node.callee)) {\n          return true;\n        }\n      }\n    },\n    objectpropertycall: {\n      nodeType: \"CallExpression\",\n      test: function (testNode, node) {\n        if (templateRules.objectproperty.test(testNode.callee, node.callee)) {\n          return true;\n        }\n      }\n    },\n    matchArgs: function (testNode, node) {\n      var matching = node.arguments.length > 0;\n      var index = 0;\n      while (matching && index < testNode.arguments.length) {\n        var testArg = testNode.arguments[index];\n        //ensure each literal argument matches\n        if (testArg.type == \"Literal\") {\n          if (typeof node.arguments[index] == 'undefined' || node.arguments[index].type != \"Literal\" || testArg.value != node.arguments[index].value) {\n            matching = false;\n          }\n        }\n        index++;\n      }\n      if (matching) {\n        return true;\n      }\n    },\n    callargs: {\n      nodeType: \"CallExpression\",\n      test: function (testNode, node) {\n        if (templateRules.call.test(testNode, node) &&\n          templateRules.matchArgs(testNode, node)) {\n          return true;\n        }\n      }\n    },\n    propertycallargs: {\n      nodeType: \"CallExpression\",\n      test: function (testNode, node) {\n        if (templateRules.propertycall.test(testNode, node) &&\n          templateRules.matchArgs(testNode, node)) {\n          return true;\n        }\n      }\n    },\n    objectpropertycallargs: {\n      nodeType: \"CallExpression\",\n      test: function (testNode, node) {\n        if (templateRules.objectpropertycall.test(testNode, node) &&\n          templateRules.matchArgs(testNode, node)) {\n          return true;\n        }\n      }\n    },\n    assignment: {\n      nodeType: \"AssignmentExpression\",\n      test: function (testNode, node) {\n        if (templateRules.identifier.test(testNode.left, node.left)) {\n          //support $_unsafe for RHS of assignment\n          var unsafe = true;\n          if (testNode.right.type == \"Identifier\" && testNode.right.name == \"$_unsafe\") {\n            unsafe = templateRules.$_contains(node.right, \"Identifier\")\n          }\n          return unsafe;\n        }\n      }\n    },\n    propertyassignment: {\n      nodeType: \"AssignmentExpression\",\n      test: function (testNode, node) {\n        //support $_unsafe for RHS of assignment\n        var unsafe = true;\n        if (testNode.right.type == \"Identifier\" && testNode.right.name == \"$_unsafe\") {\n          unsafe = templateRules.$_contains(node.right, \"Identifier\")\n        }\n\n        if (templateRules.property.test(testNode.left, node.left) && unsafe) {\n          return true;\n        }\n      }\n    },\n    objectpropertyassignment: {\n      nodeType: \"AssignmentExpression\",\n      test: function (testNode, node) {\n\n        //support $_unsafe for RHS of assignment\n        var unsafe = true;\n        if (testNode.right.type == \"Identifier\" && testNode.right.name == \"$_unsafe\") {\n          unsafe = templateRules.$_contains(node.right, \"Identifier\")\n        }\n\n        if (templateRules.objectproperty.test(testNode.left, node.left) && unsafe) {\n          return true;\n        }\n      }\n    },\n    $_contains: function (node, typestring) {\n      var foundnode = walk.findNodeAt(node, null, null, typestring);\n      return typeof foundnode != 'undefined'\n    },\n    ifstatement: {\n      nodeType: \"IfStatement\",\n      test: function (testNode, node) {\n        if (testNode.test.type == \"CallExpression\" && testNode.test.callee.name == \"$_contains\") {\n          if (testNode.test.arguments[0].type == \"Literal\") {\n            if (templateRules.$_contains(node.test, testNode.test.arguments[0].value)) {\n              return true;\n            }\n          }\n        }\n      }\n    }\n  };\n\n  function aw_loadRulesFile(rulesFile, callback) {\n\n    var request = new XMLHttpRequest();\n\n    request.open('GET', rulesFile, false);\n\n    request.onload = function () {\n      if (request.status >= 200 && request.status < 400) {\n        rulesData = JSON.parse(request.responseText);\n        aw_loadRules(rulesData);\n        if (typeof callback == 'function')\n          callback(rules);\n      } else {\n        console.log('Error loading ' + rules)\n      }\n    };\n\n    request.onerror = function () {\n      console.log('Connection error while loading ' + rulesFile)\n    };\n    request.send();\n  }\n\n\n  function aw_parseRule(rule) {\n    try {\n      var program = parser.parse(rule.source);\n      //each rule must contain exactly one javascript statement\n      if (program.body.length != 1) {\n        throw ('Rule ' + rule.name + 'contains too many statements, skipping: ' + rule.source);\n\n      }\n      rule.statement = program.body[0]\n    } catch (e) {\n      throw('Can\\'t parse rule:' + rule.name );\n    }\n\n    if (rule.statement.type == \"IfStatement\") {\n      return 'ifstatement';\n    }\n\n    //identifier\n    if (rule.statement.expression.type == \"Identifier\") {\n      return 'identifier';\n    }\n\n    if (rule.statement.expression.type == \"NewExpression\") {\n      return 'new';\n    }\n\n    //property, objectproperty\n    if (rule.statement.expression.type == \"MemberExpression\") {\n      if (rule.statement.expression.object.name == \"$_any\") {\n        //rule is $_any.foo, this is a property rule\n        return 'property';\n      } else if (rule.statement.expression.property.name == \"$_any\") {\n        return 'object';\n      }\n      else {\n        return 'objectproperty';\n      }\n    }\n    //call, propertycall,objectpropertycall ( + args variants)\n    if (rule.statement.expression.type == \"CallExpression\") {\n      var args = '';\n      if (rule.statement.expression.arguments.length > 0) {\n        args = 'args';\n      }\n\n      if (rule.statement.expression.callee.type == \"Identifier\") {\n        return 'call' + args;\n      } else if (rule.statement.expression.callee.type == \"MemberExpression\") {\n        if (rule.statement.expression.callee.object.name == \"$_any\") {\n          return 'propertycall' + args;\n        } else {\n          return 'objectpropertycall' + args;\n        }\n      }\n    }\n\n    //assignment, propertyassignment, objectpropertyassignment\n    if (rule.statement.expression.type == \"AssignmentExpression\") {\n      if (rule.statement.expression.left.type == \"MemberExpression\") {\n        if (rule.statement.expression.left.object.name == \"$_any\") {\n          return 'propertyassignment';\n        } else {\n          return 'objectpropertyassignment';\n        }\n      } else {\n        return 'assignment';\n      }\n    }\n\n\n    //if we get to here we couldn't find a matching template for the rule.source\n    throw (\"No matching template\")\n  }\n\n  function aw_loadRules(rulesData) {\n\n    var nodeTests = {};\n    //each node type may have multiple tests, so first create arrays of test funcs\n    for (var i in rulesData) {\n      var rule = rulesData[i];\n      //parse rule source\n      var template;\n      try {\n        template = templateRules[aw_parseRule(rule)];\n      } catch (e) {\n        console.log(\"Error parsing rule \" + rule.name, rule.source)\n        break;\n      }\n\n      if (typeof template == 'undefined') {\n        console.log(\"Should never get here.\")\n        break;\n      }\n\n      if (!nodeTests[template.nodeType]) {\n        nodeTests[template.nodeType] = [];\n      }\n      nodeTests[template.nodeType].push(function (template, rule, node) {\n        if (rule.statement.expression) {\n          if (template.test(rule.statement.expression, node)) {\n            aw_found(rule, node);\n          }\n        }\n        else {\n          if (template.test(rule.statement, node)) {\n            aw_found(rule, node);\n          }\n        }\n      }.bind(undefined, template, rule));\n    }\n\n\n    rules = {};\n    //create a single function for each nodeType, which calls all the test functions\n    for (var nodeType in nodeTests) {\n      rules[nodeType] = function (tests, node) {\n        tests.forEach(function (test) {\n          test.call(this, node);\n        });\n      }.bind(undefined, nodeTests[nodeType]);\n    }\n  }\n\n  function aw_scan(ast, filename) {\n    results = [];\n    results.filename = \"Manual input\"\n\n    if (typeof filename != 'undefined') {\n      results.filename = filename;\n    }\n    if (!rules) {\n      return [\n        {\n          type: 'error',\n          name: 'RulesError',\n          pos: 0,\n          loc: { column: 0, line: 0 },\n          message: \"Could not scan with no rules loaded.\",\n          filename: filename\n        }\n      ];\n    }\n      walk.simple(ast, rules);\n\n    return results;\n  }\n\n  function aw_setCallback(found_callback) {\n    aw_found_callback = found_callback;\n  }\n\n  function aw_setParser(newParser){\n    parser = newParser;\n  }\n\n  exports.rules = rules;\n  exports.scan = aw_scan;\n  exports.loadRulesFile = aw_loadRulesFile;\n  exports.loadRules = aw_loadRules;\n  exports.parseRule = aw_parseRule;\n  exports.setResultCallback = aw_setCallback;\n  exports.parser = aw_setParser;\n\n});\n"
  },
  {
    "path": "common/template_rules.json",
    "content": "[\n  {\n    \"name\": \"identifier\",\n    \"source\": \"foo\",\n    \"testhit\": \"foo;\",\n    \"testmiss\": \"'foo';\",\n    \"desc\": \"Matches identifier with same name.\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"property\",\n    \"source\": \"$_any.foo\",\n    \"testhit\": \"a.foo; a.b.foo; this['foo'];this['bar'].foo;\",\n    \"testmiss\": \"foo;\",\n    \"desc\": \"Matches object with property of same name.\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"objectproperty\",\n    \"source\": \"foo.bar\",\n    \"testhit\": \"foo.bar; a.foo.bar; foo['bar'];\",\n    \"testmiss\": \"foo.foo;bar.bar;\",\n    \"desc\": \"Matches object name and property name.\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"call\",\n    \"source\": \"foo()\",\n    \"testhit\": \"foo();\",\n    \"testmiss\": \"foo;\",\n    \"desc\": \"Matches funtion where callee has a given name.\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"propertycall\",\n    \"source\": \"$_any.foo()\",\n    \"testhit\": \"a.foo(); a.b.foo(); this['foo']();\",\n    \"testmiss\": \"foo();foo;a.foo;\",\n    \"desc\": \"Find function, where callee is a member object, matching property name only\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"objectpropertycall\",\n    \"source\": \"foo.bar()\",\n    \"testhit\": \"foo.bar(); a.foo.bar(); foo['bar']();\",\n    \"testmiss\": \"foo.foo();bar.bar();foo.bar;\",\n    \"desc\": \"Match function, where callee is a member object, matching object name and propertyname\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"callargs\",\n    \"source\": \"foo('test',ignored,42)\",\n    \"testhit\": \"foo('test',foo,42); foo('test',foo,42,'extra'); \",\n    \"testmiss\": \"foo; foo(); a.foo('test',foo,42); foo('wrong',foo,42); foo('test',foo,41); foo('test',41); foo(foo,'test', foo,42)\",\n    \"desc\": \"Same as for call, expect this allow makes sure that any supplied literal arguments are matching (both in value, and in position)\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"propertycallargs\",\n    \"source\": \"$_any.foo('test',ignored,42)\",\n    \"testhit\": \"$_any.foo('test',foo,42); $_any.foo('test',foo,42,'extra'); $_any.a.foo('test',foo,42); $_any.a[foo]('test',foo,42); $_any.a['b'].foo('test',bar,42);\",\n    \"testmiss\": \"foo('test',foo,42); a.foo('miss',foo,42); a.foo('test',foo); a[foo]('test',foo,41); a['b'].foo('test',42); foo('miss');   a[foo](foo,41);\",\n    \"desc\": \"Same as for propertycall, expect this allow makes sure that any supplied literal arguments are matching (both in value, and in position)\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"objectpropertycallargs\",\n    \"source\": \"foo.bar('test',ignored,42)\",\n    \"testhit\": \"foo.bar('test',foo,42); foo.bar('test',foo,42,'extra'); a.foo.bar('test',foo,42); a[foo]['bar']('test',foo,42); a['b'].foo.bar('test',bar,42);\",\n    \"testmiss\": \"foo; foo(); foo('miss',foo,42); foo.foo('test',foo,42); bar.bar('test',foo,42)\",\n    \"desc\": \"Same as for objectpropoertycall, expect this allow makes sure that any supplied literal arguments are matching (both in value, and in position)\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"assignment\",\n    \"source\": \"foo=$_any\",\n    \"testhit\": \"foo=bar;\",\n    \"testmiss\": \"foo; foo\",\n    \"desc\": \"Assigning to identifier with given name\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"propertyassignment\",\n    \"source\": \"$_any.foo=$_any\",\n    \"testhit\": \"a.foo=bar; a.b.foo=bar; this['foo']=bar;\",\n    \"testmiss\": \"foo=bar\",\n    \"desc\": \"Assigning to a object property with a given name\",\n    \"threat\": \"example\"\n  },\n  {\n    \"name\": \"objectpropertyassignment\",\n    \"source\": \"foo.bar=$_any\",\n    \"testhit\": \"foo.bar=a; a.foo.bar=b; foo['bar']=c;a.foo['bar']=c;\",\n    \"testmiss\": \"bar.bar=a;foo.foo=b;\",\n    \"desc\": \"Assigning to a object property matching both object name and property name\",\n    \"threat\": \"example\"\n  }\n]\n"
  },
  {
    "path": "deploy-ghpages.sh",
    "content": "#!/bin/bash\n\n# This makes sure, that we don't deploy pull requests to gh-pages :-)\nif [ $TRAVIS_PULL_REQUEST != false ];\nthen\n  echo \"Not deploying test-run for a pull request\"\n  exit 0\nfi\n\n(\n git init\n git config user.name \"Travis-CI\"\n git config user.email \"travis@nodemeatspace.com\"\n git add -v .\n git commit -v -m \"Deployed to Github Pages\"\n git push --force --quiet \"https://${GH_TOKEN}@${GH_REF}\" master:gh-pages > /dev/null 2>&1\n)\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"scanjs\",\n  \"version\": \"0.0.2\",\n  \"description\": \"Static analysis tool for javascript codebases\",\n  \"main\": \"scanner.js\",\n  \"bin\": {\n    \"scanjs\": \"./scanner.js\",\n    \"scanjs-server\": \"./server.js\"\n  },\n  \"preferGlobal\": true,\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/mozilla/scanjs.git\"\n  },\n  \"keywords\": [\n    \"scanjs\",\n    \"code-analysis\",\n    \"javascript\",\n    \"static-analysis\"\n  ],\n  \"author\": \"Paul Theriault, Frederik Braun, Rob Fletcher\",\n  \"license\": \"MPL\",\n  \"dependencies\": {\n    \"acorn\": \"~0.3.0\",\n    \"tern\": \"~0.5.0\",\n    \"optimist\": \"~0.5.2\",\n    \"jszip\": \"~2.2.0\",\n    \"node-static\": \"~0.7.3\",\n    \"js-beautify\":\"~1.4.2\"\n  },\n  \"devDependencies\": {\n    \"mocha\": \"*\",\n    \"chai\": \"*\"\n  },\n  \"scripts\": {\n    \"test\": \"cd tests && mocha -r mocha-includes cases/placeholders.js cases/test_ruletests.js cases/production_ruletests.js && mocha -r mocha-includes cases/innerhtml.js cases/CustomEvent.js cases/addIdleObserver.js cases/createContextualFragment.js cases/crypto.generateCRMFRequest.js cases/document.write.js cases/document.writeln.js cases/eval.js cases/geolocation.js cases/href.js cases/indexedDB.js cases/localStorage.js cases/message.js cases/newFunction.js cases/outerHTML.js cases/parseFromString.js cases/sessionStorage.js cases/setInterval.js cases/setTimeout.js cases/src.js cases/getDeviceStorage.js cases/moz/moz.js\"\n  }\n}\n"
  },
  {
    "path": "scanner.js",
    "content": "#!/usr/bin/env node\n/*jshint node:true*/\n\n// This script is for using scanjs server side\n\nvar fs = require('fs');\nvar path = require('path');\nvar beautify = require('js-beautify').js_beautify;\n\nvar parser = require(__dirname+ '/client/js/lib/acorn.js');\nvar ScanJS = require(__dirname + '/common/scan');\n\nvar signatures = JSON.parse(fs.readFileSync(__dirname + \"/common/rules.json\", \"utf8\"));\n\nScanJS.parser(parser);\nScanJS.loadRules(signatures);\n\nvar argv = require('optimist').usage('Usage: $node scan.js -t [path/to/app] -o [resultFile.json]').demand(['t']).argv;\n\nvar dive = function(dir, action) {\n  if( typeof action !== 'function') {\n    action = function(error, file) {\n      console.log(\">\" + file)\n    };\n  }\n  list = fs.readdirSync(dir);\n  list.forEach(function(file) {\n    var fullpath = dir + '/' + file;\n    try {\n      var stat = fs.statSync(fullpath);\n    } catch(e) {\n      console.log(\"SKIPPING FILE: Could not stat \" + fullpath);\n    }\n    if(stat && stat.isDirectory()) {\n      dive(fullpath, action);\n    } else {\n      action(file, fullpath);\n    }\n  });\n};\nvar writeReport = function(results, name) {\n  if(fs.existsSync(name)) {\n    console.log(\"Error:output file already exists (\" + name + \"). Supply a different name using: -o [filename]\")\n  }\n  fs.writeFile(name, JSON.stringify(results), function(err) {\n    if(err) {\n      console.log(err);\n    } else {\n      console.log(\"The scan results were saved to \" + name);\n    }\n  });\n};\n\n\nif( typeof process != 'undefined' && process.argv[2]) {\n  results = {};\n  reportname = argv.o ? argv.o : 'scanresults';\n  reportdir = reportname + \"_files\";\n  if(fs.existsSync(reportname) || fs.existsSync(reportdir)) {\n    console.log(\"Error:output file or dir already exists (\" + reportname + \"). Supply a different name using: -o [filename]\")\n\n  } \n  else {\n    fs.mkdirSync(reportdir);\n    dive(argv.t, function(file, fullpath) {\n      var ext = path.extname(file.toString());\n\n      if(ext == '.js') {\n        var content = fs.readFileSync(fullpath, 'utf8');\n        //beautify source so result snippet is meaningful\n        var content = beautify(content, { indent_size: 2 });\n\n        var ast = parser.parse(content, { locations: true });\n\n        var scanresult = ScanJS.scan(ast, fullpath);\n        if (scanresult.type == 'error') {\n          console.log(\"SKIPPING FILE: Error in \"+ fullpath+\", at Line \"+ scanresult.error.loc.line +\", Column \"+scanresult.error.loc.column+ \": \" + scanresult.error.message);\n        }\n        results[fullpath] = scanresult;\n      }\n    });\n    // Flatten report file to remove files with no findings and tests with no results (i.e. empty arr)\n    // TODO: Don't even store empty unless --overly-verbose or so..\n    for (var testedFile in results) {\n      for (var testCase in results[testedFile]) {\n        if (results[testedFile][testCase].length == 0) {\n          delete(results[testedFile][testCase]);\n        }\n      }\n      if (Object.keys(results[testedFile]).length == 0) {\n        delete(results[testedFile]);\n      }\n    }\n    writeReport(results, reportname + '.JSON');\n  }\n} else {\n  console.log('usage: $ node scan.js path/to/app ')\n}\n"
  },
  {
    "path": "server.js",
    "content": "#!/usr/bin/env node\nvar static = require(\"node-static\");\nvar file = new static.Server('.', {\n  headers: {\n    \"Content-Security-Policy\": \"default-src 'self'; object-src 'none'; img-src 'self' data:; script-src 'self' 'unsafe-eval'\",\n  }\n});\n\nconst PORT = process.env.PORT || 4000;\nrequire ('http').createServer(function (req, res) {\n  req.addListener('end', function () {\n    file.serve(req, res);\n  }).resume();\n}).listen(PORT);\n\nconsole.log(\"> node-static is listening on http://127.0.0.1:\"+PORT);\n"
  },
  {
    "path": "stackato.yml",
    "content": "name: ScanJS\nframework:\n        type: node\n        runtime: node010\n           \nurl:\n        - scanjs.paas.allizom.org\n\nprocesses:\n        web: node server.js\n"
  },
  {
    "path": "tests/TESTING",
    "content": "TESTING\n======\n\nTo run tests, just use one of the following commands.\n\nEquivalent to visiting test/index.html in the browser:\n  mocha -r mocha-includes cases/placeholders.js cases/test_ruletests.js cases/production_ruletests.js\n\nEquivalent to visiting test/advanced.html in the browser:\n  mocha -r mocha-includes cases/innerhtml.js cases/CustomEvent.js cases/addIdleObserver.js cases/createContextualFragment.js cases/crypto.generateCRMFRequest.js cases/document.write.js cases/document.writeln.js cases/eval.js cases/geolocation.js cases/href.js cases/indexedDB.js cases/localStorage.js cases/message.js cases/newFunction.js cases/outerHTML.js cases/parseFromString.js cases/sessionStorage.js cases/setInterval.js cases/setTimeout.js cases/src.js cases/getDeviceStorage.js cases/moz/moz.js\n\nSee disbaled tests in JS format below\n\nList of tests in JS format:\n--------------------------------------------------------------------------------\n\n\nvar disabledTests = [\"action.js\",\n\"addEventListener.js\",\n\"data.js\",\n\"escapeHTML.js\",\n\"window.open.js\"]\n\n\nvar standardTests = [\"placeholders.js\",\n    \"test_ruletests.js\",\n    \"production_ruletests.js\"]\n\nvar advancedTests = [\"innerhtml.js\",\n  \"CustomEvent.js\",\n  \"addIdleObserver.js\",\n  \"createContextualFragment.js\",\n  \"crypto.generateCRMFRequest.js\",\n  \"document.write.js\",\n  \"document.writeln.js\",\n  \"eval.js\",\n  \"geolocation.js\",\n  \"href.js\",\n  \"indexedDB.js\",\n  \"localStorage.js\",\n  \"message.js\",\n  \"newFunction.js\",\n  \"outerHTML.js\",\n  \"parseFromString.js\",\n  \"sessionStorage.js\",\n  \"setInterval.js\",\n  \"setTimeout.js\",\n  \"src.js\",\n  \"getDeviceStorage.js\",\n  \"moz/moz.js\"]\n\nvar allTests = disabledTests+standardTests+advancedTests;\n\n\n"
  },
  {
    "path": "tests/advanced.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"content-security-policy\" content=\"default-src 'self'; object-src 'none'; img-src 'self' data:; script-src 'self' 'unsafe-eval'\">\n  <title>Scan.js Tests</title>\n  <!-- Third-party libs -->\n  <script src='../client/js/lib/jquery-2.1.0.min.js'></script>\n  <script src='../client/js/lib/acorn.js'></script>\n  <script src='../client/js/lib/walk.js'></script>\n  <script src='../client/js/lib/acorn_loose.js'></script>\n  <!-- CommonJS modules -->\n  <script src='../common/scan.js'></script>\n\n  <!-- Testing framework files -->\n  <link href='css/mocha.css' rel='stylesheet' media='screen'>\n  <script src='js/mocha.js'></script>\n  <script src='js/chai.js'></script>\n  <script src='js/main.js'></script>\n  <!-- loads rules since new scanner uses rules.json instead of rules.js -->\n  <script src='js/loadrules.js'></script>\n</head>\n<body>\n  <div id=\"mocha\"><p><h1><b>Scan.js Mocha Unit Tests</b></h1></p></div>\n  <div id=\"messages\"></div>\n  <div id=\"fixtures\"></div>\n\n\n  <!-- rule test cases -->\n  <script src='cases/ruletests.js'></script>\n\n  <!-- Test cases -->\n  <script src='cases/innerhtml.js'></script>\n  <script src='cases/CustomEvent.js'></script>\n  <!-- removing these since they arent in the default rule set\n  Too broad: <script src='cases/addEventListener.js'></script>\n  Too broad: <script src='cases/data.js'></script>\n  non-standard: <script src='cases/escapeHTML.js'></script>\n  Too broad: <script src='cases/window.open.js'></script>\n\n  -->\n  <script src='cases/addIdleObserver.js'></script>\n  <script src='cases/createContextualFragment.js'></script>\n  <script src='cases/crypto.generateCRMFRequest.js'></script>\n\n  <script src='cases/document.write.js'></script>\n  <script src='cases/document.writeln.js'></script>\n\n  <script src='cases/eval.js'></script>\n  <script src='cases/geolocation.js'></script>\n  <script src='cases/href.js'></script>\n  <script src='cases/indexedDB.js'></script>\n  <script src='cases/localStorage.js'></script>\n  <script src='cases/message.js'></script>\n  <script src='cases/newFunction.js'></script>\n  <script src='cases/outerHTML.js'></script>\n  <script src='cases/parseFromString.js'></script>\n  <script src='cases/sessionStorage.js'></script>\n  <script src='cases/setInterval.js'></script>\n  <script src='cases/setTimeout.js'></script>\n  <script src='cases/src.js'></script>\n  <script src='cases/getDeviceStorage.js'></script>\n\n\n\n  <!-- mozilla specific tests -->\n  <script src='cases/moz/moz.js'></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "tests/cases/CustomEvent.js",
    "content": "(function () {\n  describe('CustomEvent tests - future rule?', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"CustomEvent\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'good.CustomEvent = \"CustomEvent\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'obj.addEventListener(\"cat\", function(e) { process(e.detail) }); var event = new CustomEvent(\"cat\",  {\"detail\":{\"hazcheeseburger\":true}});  obj.dispatchEvent(event);';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/action.js",
    "content": "(function () {\n  describe('action attribute (mainly for forms) test', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var action = \"static string\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'var a=document.createElement(\"form\"); a.action=\"demo_form.asp\"; document.body.appendChild(a);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 73 - https://github.com/mozilla/scanjs/issues/73\n        var bad = 'var a=document.createElement(\"form\"); a.setAttribute(\"action\", \"demo_form.asp\"); document.body.appendChild(a);';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 74 - https://github.com/mozilla/scanjs/issues/74\n        var bad = 'var a=document.createElement(\"div\"); a.innerHTML=\"<form action=\\'demo.asp\\'></form>\"; document.body.appendChild(a);';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/addEventListener.js",
    "content": "(function () {\n  describe('addEventListener tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"addEventListener\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good =  'var addEventListener = \"variable with name\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'var el = document.getElementById(\"outside\");el.addEventListener(\"click\", modifyText, false);' ;\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'addEventListener(\"click\", errorPageEventHandler, true, false);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'tab.linkedBrowser.addEventListener(\"load\", function (event) {console.log(1);});';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/addIdleObserver.js",
    "content": "(function () {\n  describe('addIdleObserver tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"addIdleObserver()\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'addIdleObserver = \"static string\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'something.addIdleObserver = \"static string\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'navigator.addIdleObserver(IdleObserver);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations:true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/createContextualFragment.js",
    "content": "(function () {\n  describe('createContextualFragment tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"createContextualFragment()\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var createContextualFragment = \"static string\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'var documentFragment = range.createContextualFragment(\"<h1>bad</h1>\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations:true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/crypto.generateCRMFRequest.js",
    "content": "(function () {\n  describe('generateCRMFRequest tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'generateCRMFRequest = \"static string\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var a = \"generateCRMFRequest\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'crypto.generateCRMFRequest(\"CN=0\", 0, 0, null, \"console.log(1)\", 384, null, \"rsa-dual-use\");;';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 76 - https://github.com/mozilla/scanjs/issues/76\n        var bad = 'var a = crypto; a.generate = crypto.generateCRMFRequest; a.generate(\"CN=0\", 0, 0, null, \"console.log(1)\", 384, null, \"rsa-dual-use\");';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/data.js",
    "content": "(function () {\n  describe('data attribute tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"something.data\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(good, \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var data = \"something\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(good, \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'form.data = \"mystring\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(good, \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'var a = event.data;';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(bad, \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'readPipe(event.something.data.pipe, a, b);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(bad, \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'readPipe(event.data.pipe, a, b);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(bad, \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/document.write.js",
    "content": "(function () {\n  describe('document.write tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'good.write = \"static string\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'good = \"document.write\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'document.write(\"Hello World!\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'window.document.write(\"Hello World!\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 76 - https://github.com/mozilla/scanjs/issues/76\n        var bad = 'var a = window.document; a.b = document.write; a.b(\"<h1>bad</h1>\");';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/document.writeln.js",
    "content": "(function () {\n  describe('document.writeln tests', function () {\n    describe('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'good.writeln = \"static string\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'good = \"document.writeln\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    describe('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'document.writeln(\"Hello World!\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'window.document.writeln(\"Hello World!\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 76 - https://github.com/mozilla/scanjs/issues/76\n        var bad = 'var a = window.document; a.b = document.writeln; a.b(\"<h1>bad</h1>\");';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/escapeHTML.js",
    "content": "(function () {\n  describe('escapeHTML tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"escapeHTML\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(good, \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var escapeHTML = \"just a string\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(good, \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'var nodeName = escapeHTML(node.name);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(bad, \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/eval.js",
    "content": "(function() {\n  describe('eval tests', function() {\n    context('ignores safe patterns', function() {\n      context(null, function() {\n\tvar good = 'var a = \"eval(alert(1));\";';\n\tit(good, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n\t});\n      });\n      context(null, function() {\n\tvar good = 'var a = {}; a.eval = \"somstring\";';\n\tit(good, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n\t});\n      });\n    });\n    context('detects dangerous patterns', function() {\n      context(null, function() {\n\tvar bad = 'eval(\"alert(0);\");;';\n\tit(bad, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n\t});\n      });\n      context(null, function() {\n\t// issue 76 - https://github.com/mozilla/scanjs/issues/76\n\tvar bad = 'var a = eval; a(\"alert(0);\");';\n\tit.skip(bad, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n\t});\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/geolocation.js",
    "content": "(function() {\n  describe('geolocation tests', function() {\n    context('ignores safe patterns', function() {\n      context(null, function () {\n\tvar good = 'var a  = \"navigator.geolocation.getCurrentPosition(success, error);\";';\n\tit(good, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n\t});\n      });\n    });\n    context('detects dangerous patterns', function() {\n      context(null, function () {\n\tvar bad = 'navigator.geolocation.getCurrentPosition(showPosition);';\n\tit(bad, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n\t});\n      });\n      context(null, function () {\n\tvar bad = 'var a = navigator.geolocation; a.getCurrentPosition(showPosition);';\n\tit(bad, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n\t});\n      });\n      context(null, function () {\n\tvar bad = 'var a = navigator; a.geolocation.getCurrentPosition(showPosition);';\n\tit.skip(bad, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n\t});\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/getDeviceStorage.js",
    "content": "(function() {\n  describe('getDeviceStorage tests', function() {\n    context('ignores safe patterns', function() {\n      context(null, function () {\n        var good = 'var a  = \"navigator.getDeviceStorage(storageName)\";';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function() {\n      context(null, function () {\n        var bad = 'var instanceOfDeviceStorage = navigator.getDeviceStorage(storageName);';\n        it(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n          var bad = 'var a = navigator; a.getDeviceStorage(storageName);';\n          it(bad, function(){\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}),  \"/tests/\")).not.to.be.empty;\n          });\n      });\n      context(null, function () {\n        // issue 82 - https://github.com/mozilla/scanjs/issues/82\n        var bad = 'window[\"navigator\"][\"getDeviceStorage\"](storageName);';\n        it.skip(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/href.js",
    "content": "(function() {\n  describe('href tests', function() {\n    context('ignores safe patterns', function() {\n      context(null, function () {\n        var good = 'var href = \"static string\";';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var a = document.createElement(\"a\"); a.setAttribute(\"href\", \"http://mozilla.org\"); document.body.appendChild(a);';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var a = document.createElement(\"a\"); a.setAttribute(\"href\", 1); document.body.appendChild(a);';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function() {\n      /* deactivated, failing test.\n      context(null, function () {\n        var bad = 'a.href =\"javascript:alert(0);\";';\n        it(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n      */\n      context(null, function () {\n        // issue 73 - https://github.com/mozilla/scanjs/issues/73\n        var bad = 'var a = document.createElement(\"a\"); a.setAttribute(\"href\", \"javascript:alert(0)\"); document.body.appendChild(a);';\n        it.skip(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/indexedDB.js",
    "content": "(function() {\n  describe('indexedDB tests', function() {\n    context('ignores safe patterns', function() {\n      context(null, function() {\n\tvar good = 'var a  = \"indexedDB.open(abase)\";';\n\tit(good, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n\t});\n      });\n    });\n    context('detects dangerous patterns', function() {\n      context(null, function() {\n\tvar bad = 'var request = indexedDB.open(\"MyTestDatabase\");';\n\tit(bad, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n\t});\n      });\n      context(null, function() {\n\t// issue 82 - https://github.com/mozilla/scanjs/issues/82\n\tvar bad = 'var a = \"indexedDB\"; window[a].open(3);';\n\tit.skip(bad, function(){\n\t  chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n\t});\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/innerhtml.js",
    "content": "(function () {\n  describe('innerHTML tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'good.innerHTML = \"static string\";';\n        it.skip(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var a = document.createElement(\"div\"); a.setAttribute(\"innerHTML\", \"<h1>bad</h1>\"); document.body.appendChild(a);';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var getInnerHtml = document.getElementById(\"node\").innerHTML;';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = '//div.innerHTML = this is a comment';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'div.innerHTML = 1';\n        it.skip(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        //issue 71 - https://github.com/mozilla/scanjs/issues/71\n        var good = 'var a = 1; div.innerHTML = a';\n        it.skip(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'dangerous.innerHTML=document.location;';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'div.innerHTML = \"static string\" + someVariable;';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/localStorage.js",
    "content": "(function() {\n  describe('localStorage tests', function() {\n    context('ignores safe patterns', function() {\n      context(null, function() {\n        var good = 'var a  = \"localStorage.open(abase)\";';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function() {\n        var good = 'var localStorage  = \"asdf\";';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function() {\n      context(null, function() {\n        var bad = 'localStorage.setItem(\"name\", \"user1\");';\n        it(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function() {\n        // issue 82 - https://github.com/mozilla/scanjs/issues/82\n        var bad = 'var a = \"localStorage\"; window[a].setItem(\"name\", \"user1\");';\n        it.skip(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/message.js",
    "content": "(function() {\n  describe('message tests', function() {\n    context('ignores safe patterns', function() {\n      context(null, function () {\n        var good = 'var a = \"message\";';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var message = \"static string\";';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'function receiveMessage() { console.log(1); }';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'function message() { console.log(1); }';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function() {\n      context(null, function () {\n        var bad = 'window.addEventListener(\"message\", receiveMessage, false);';\n        it(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations:true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/moz/moz.js",
    "content": "(function () {\n  describe('Mozilla specific tests', function () {\n    context('MozActivity', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"static MozActivity\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n        context(null, function () {\n          var good = 'var MozActivity = \"static MozActivity\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var activity = new MozActivity({ name: \"pick\",data: {type: \"image/jpeg\"}});';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('.mozAlarms', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var mozAlarms = \"just a string, not .mozAlarms\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var bad = window.navigator.mozAlarms;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozApps.mgmt', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var getAll = \"mozApps.mgmt.getAll()\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var stuffs = navigator.mozApps.mgmt;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        context(null, function () {\n          var bad = 'var stuffs = navigator.mozApps.mgmt.getAll()';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('.mozBluetooth', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var mozBluetooth = \"just a string, not .mozBluetooth\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var bad = window.navigator.mozBluetooth;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozCameras', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var mozCameras = \"just a string, not mozCameras\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var bad = window.navigator.mozCameras;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var bad = window.navigator.mozCellBroadcast;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozChromeEvent', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"string mozChromeEvent\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n        context(null, function () {\n          var good = 'var mozChromeEvent = \"string mozChromeEvent\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'window.addEventListener(\"mozChromeEvent\", function (e) {console.log(\"mozilla rocks!\") });';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('.mozContacts', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var mozContacts = \"just a string, not .mozContacts\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var bad = window.navigator.mozContacts;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozFMRadio', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"string mozFMRadio;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var WebFM = navigator.mozFMRadio;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozKeyboard', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"mozKeyboard\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        /* deactivated, failing test.\n        context(null, function () {\n          var bad = 'mozKeyboard.onfocuschange = alert(0);';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        */\n      });\n    });\n\n    context('mozMobileConnection', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"mozMobileConnection\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        /* deactivated, failing test.\n         context(null, function () {\n          var bad = 'MozMobileConnection.sendMMI()';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        */\n      });\n    });\n\n    context('.mozNotification', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var mozNotification = \".mozNotification, this is just a string\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = \"if (window.webkitNotifications) { _popup = window; } else if (navigator.mozNotification) { console.log (1); }\";\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozPermissionSettings', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"just a string, not mozPermissionSettings\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n        context(null, function () {\n          var good = 'var mozPermissionSettings = \"just a string, not mozPermissionSettings\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var permissions = window.navigator.mozPermissionSettings;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozPower', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"just a string, window.navigator.mozPower;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n        context(null, function () {\n          var good = 'var mozPower = \"just a string, window.navigator.mozPower;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var power = window.navigator.mozPower;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozSetMessageHandler', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"static mozSetMessageHandler\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'navigator.mozSetMessageHandler(type, handler);';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozSettings', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"window.navigator.mozSettings;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n        context(null, function () {\n          var good = 'var mozSettings = \"window.navigator.mozSettings;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var settings = window.navigator.mozSettings;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozSms', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"window.navigator.mozSms;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n        context(null, function () {\n          var good = 'var mozSms = \"window.navigator.mozSms;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n         /* deactivated, failing test.\n         context(null, function () {\n          var bad = 'var sms = window.navigator.mozSms;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        */\n        /* deactivated, failing test.\n        context(null, function () {\n          var bad = 'var msg = window.navigator.mozSms.getMessage(1);';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        */\n      });\n    });\n\n    context('mozSystem', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"mozSystem: true\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var xhr = new XMLHttpRequest({ mozSystem: true});';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('.mozTCPSocket', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"navigator.mozTCPSocket;\"';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var socket = navigator.mozTCPSocket;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozTelephony', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"window.navigator.mozTelephony;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var phone = window.navigator.mozTelephony;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozTime', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"mozTime;\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var time = window.navigator.mozTime;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozVoicemail', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"mozVoicemail\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var voicemail = window.navigator.mozVoicemail;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        context(null, function () {\n          var bad = 'var status = window.navigator.mozVoicemail.getStatus();';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozapp', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"mozapp\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        /* deactivated, failing test.\n        context(null, function () {\n          var bad = 'var a = document.createElement(\"iframe\"); a.mozapp = data.app; document.appendChild(a);';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        */\n        context(null, function () {\n          // issue 73 - https://github.com/mozilla/scanjs/issues/73\n          var bad = 'iframe.setAttribute(\"mozapp\", data.app);';\n          it.skip(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('mozaudiochannel', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"mozaudiochannel=content.toString()\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        /* deactivated, failing test.\n        context(null, function () {\n          var bad = 'var a = document.createElement(\"audio\"); a.mozaudiochannel = \"content\"; document.appendChild(a);';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        */\n        context(null, function () {\n          // issue 73 - https://github.com/mozilla/scanjs/issues/73\n          var bad = 'var a = document.createElement(\"audio\"); a.setAttribute(\"mozaudiochannel\", data.app);';\n          it.skip(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n    context('moznetworkdownload', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"moznetworkdownload\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        /* deactivated, failing test.\n        context(null, function () {\n          var bad = 'addEventListener(\"moznetworkdownload\", downloadHandler);';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        */\n      });\n    });\n\n    context('moznetworkupload', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"moznetworkupload\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        /* deactivated, failing test.\n        context(null, function () {\n          var bad = 'addEventListener(\"moznetworkupload\", downloadHandler);';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        */\n      });\n    });\n\n    context('mozWifiManager', function () {\n      context('safe', function () {\n        context(null, function () {\n          var good = 'var a = \"mozWifiManager\";';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n        context(null, function () {\n          var good = 'somethingNotNavigator.mozWifiManager;';\n          it(good, function () {\n            chai.expect(ScanJS.scan(acorn.parse(good, {locations : true}), \"/tests/\")).to.be.empty;\n          });\n        });\n      });\n      context('dangerous', function () {\n        context(null, function () {\n          var bad = 'var wifi = navigator.mozWifiManager;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        context(null, function () {\n          var bad = 'var networks = navigator.mozWifiManager.getNetworks();';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n        context(null, function () {\n          var bad = 'var wifi = navigator.mozWifiManager;';\n          it(bad, function () {\n            chai.expect(ScanJS.scan(acorn.parse(bad, {locations : true}), \"/tests/\")).not.to.be.empty;\n          });\n        });\n      });\n    });\n\n  })(); //describe('Mozilla specific tests'...\n"
  },
  {
    "path": "tests/cases/newFunction.js",
    "content": "(function() {\n  describe('new Function() tests', function() {\n    context('ignores safe patterns', function() {\n      context(null, function () {\n        var good = 'var Function = \"static string\";';\n        it(good, function(){\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations:true}),  \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function() {\n      context(null, function () {\n        var bad = 'new Function(\"alert(0)\")();';\n        it(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations:true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 76 - https://github.com/mozilla/scanjs/issues/76\n        var bad = 'var a = Function; new a(\"alert(0)\")();';\n        it.skip(bad, function(){\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations:true}),  \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/outerHTML.js",
    "content": "(function () {\n  describe('outerHTML tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'good.outerHTML = \"static string\";';\n        it.skip(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var a = document.createElement(\"div\"); a.setAttribute(\"outerHTML\", \"<h1>bad</h1>\"); document.body.appendChild(a);';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var getInnerHtml = document.getElementById(\"node\").outerHTML;';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = '//div.outerHTML = this is a comment';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'dangerous.outerHTML=document.location;';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'div.outerHTML = \"static string\" + someVariable;';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/parseFromString.js",
    "content": "(function () {\n  describe('parseFromString tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"parseFromString\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'doc = parser.parseFromString(\"<h1>somehtml</h1>\", \"text/html\");';\n        it.skip(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'doc = parser.parseFromString(someVar, \"text/html\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/placeholders.js",
    "content": "\n\n\ndescribe('Testing placeholders $_any, $_contains etc', function () {\n  context('$_any', function () {\n\n    it(\" $_any.foo should match something.foo\", function () {\n      ScanJS.loadRules([{name:\"$_any.foo\",source:\"$_any.foo\"}]);\n      var results = ScanJS.scan(acorn.parse(\"something.foo;\", {locations: true}));\n      chai.expect(results).to.have.length(1);\n    });\n\n    it(\" $_any.foo should not match something.bar\", function () {\n      ScanJS.loadRules([{name:\"$_any.foo\",source:\"$_any.foo\"}]);\n      var results = ScanJS.scan(acorn.parse(\"something.bar;\", {locations:true}));\n      chai.expect(results).to.have.length(0);\n    });\n\n    it(\" foo.$_any should match foo.something\", function () {\n      ScanJS.loadRules([{name:\"foo.$_any\",source:\"foo.something\"}]);\n      var results = ScanJS.scan(acorn.parse(\"foo.something;\", {locations:true}));\n      chai.expect(results).to.have.length(1);\n    });\n\n    it(\" foo.$_any should not match bar.something\", function () {\n      ScanJS.loadRules([{name:\"$_any.foo\",source:\"$_any.foo\"}]);\n      var results = ScanJS.scan(acorn.parse(\"something.bar;\", {locations:true}));\n      chai.expect(results).to.have.length(0);\n    });\n\n\n  });\n\n  context('$_contains', function () {\n\n    var rule= {name:\"foo=$_unsafe\",source:\"foo=$_unsafe\"};\n\n    it(rule.source + \" match template callargs\", function () {\n      var template=ScanJS.parseRule(rule);\n      chai.expect(\"assignment\").to.equal(template);\n    });\n\n    it(rule.source + \"  should match foo=identifier\", function () {\n      ScanJS.loadRules([rule]);\n      var results = ScanJS.scan(acorn.parse(\"foo=identifier;\", {locations:true}));\n      chai.expect(results).to.have.length(1);\n    });\n\n    it(rule.source + \"  should not match bar=identifier\", function () {\n      ScanJS.loadRules([rule]);\n      var results = ScanJS.scan(acorn.parse(\"bar=identifier;\", {locations:true}));\n      chai.expect(results).to.have.length(0);\n    });\n\n    it(rule.source + \"  should not match foo='literal'\", function () {\n      ScanJS.loadRules([rule]);\n      var results = ScanJS.scan(acorn.parse(\"foo='literal;'\", {locations:true}));\n      chai.expect(results).to.have.length(0);\n    });\n  });\n})\n"
  },
  {
    "path": "tests/cases/production_ruletests.js",
    "content": "describe('Testing production rules (common/rules.json)', function () {\n  function testSetup(ruleData) {\n\n    ruleData.forEach(function (rule) {\n      describe('Rule: ' + rule.name, function () {\n\n        rule.testhit.split(\";\").forEach(function (testsplit) {\n          if (testsplit.trim() != \"\") {\n            it(rule.source + \" should match \" + testsplit, function () {\n              ScanJS.loadRules([rule]);\n              var ast = acorn.parse(testsplit, {locations: true});\n              var results = ScanJS.scan(ast);\n              chai.expect(results.length).to.equal(1);\n            });\n          }\n        });\n\n        it(rule.name + \" should not match \" + rule.testmiss, function () {\n          ScanJS.loadRules([rule]);\n          var ast = acorn.parse(rule.testmiss, {locations: true});\n          var results = ScanJS.scan(ast);\n          chai.expect(results).to.have.length(0);\n        });\n      });\n    });\n  }\n  if (typeof $ !== \"undefined\") {\n    $.ajax({\n      url: '../common/rules.json',\n      async: false,\n      dataType: 'json'\n    }).done(testSetup);\n  }\n  else if (typeof require !== \"undefined\") {\n    var fs = require(\"fs\");\n    var signatures = JSON.parse(fs.readFileSync(\"../common/rules.json\", \"utf8\"));\n    testSetup(signatures);\n  }\n})\n"
  },
  {
    "path": "tests/cases/sessionStorage.js",
    "content": "(function () {\n  describe('sessionStorage tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"sessionStorage\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'window.sessionStorage.setItem(\"username\", \"John\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'sessionStorage.setItem(\"username\", \"John\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'var a = sessionStorage; a.setItem(\"username\", \"John\");';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/setInterval.js",
    "content": "(function () {\n  describe('setInterval tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"window.setInterval\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'setInterval(\"console.log(1)\", 500);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'var intervalID = window.setInterval(\"console.log(2)\", 500);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'something.setInterval(\"console.log(3)\", 500);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 76 - https://github.com/mozilla/scanjs/issues/76\n        var bad = 'var a = window.setInterval; a(\"console.log(4)\", 300);';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 82 - https://github.com/mozilla/scanjs/issues/82\n        var bad = 'var a = \"setInterval\"; window[a](\"console.log(5)\", 300);';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/setTimeout.js",
    "content": "(function () {\n  describe('setTimeout tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"window.setTimeout\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'setTimeout(\"console.log(1)\", 500);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'var intervalID = window.setTimeout(\"console.log(2)\", 500);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        var bad = 'something.setTimeout(\"console.log(3)\", 500);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 76 - https://github.com/mozilla/scanjs/issues/76\n        var bad = 'var a = window.setTimeout; a(\"console.log(4)\", 300);';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 82 - https://github.com/mozilla/scanjs/issues/82\n        var bad = 'var a = \"setTimeout\"; window[a](\"console.log(5)\", 300);';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/src.js",
    "content": "(function () {\n  describe('src attribute tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var a = \"something.src\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var src = \"something\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var src = img.src;';\n        it(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var a = document.createElement(\"script\"); a.src = \"static string\"; document.body.appendChild(a);';\n        it.skip(good, function () {\n          chai.expect(ScanJS.scan(acorn.parse(good, {locations: true}), \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      /* deactivated, failing test.\n      context(null, function () {\n        var bad = 'obj.src = \"mystring\";';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });*/\n      context(null, function () {\n        var bad = 'var a = document.createElement(\"script\"); a.src = variable; document.body.appendChild(a);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(acorn.parse(bad, {locations: true}), \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/cases/test_ruletests.js",
    "content": "describe('Testing rule templates (common/template_rules.json)', function () {\n  function testSetup(ruleData) {\n\n    ruleData.forEach(function (rule) {\n      describe('Rule: ' + rule.name, function () {\n        it(rule.name + \" should match template \" + rule.name, function () {\n          var template = ScanJS.parseRule(rule);\n          chai.expect(rule.name).to.equal(template);\n        });\n\n        rule.testhit.split(\";\").forEach(function (testsplit) {\n          if(testsplit.trim()!=\"\"){\n            it(rule.source + \" should match \" + testsplit, function () {\n              ScanJS.loadRules([rule]);\n              var ast = acorn.parse(testsplit, {locations: true});\n              var results = ScanJS.scan(ast);\n              chai.expect(results.length).to.equal(1);\n            });\n          }\n        });\n\n        it(rule.name + \" should not match \" + rule.testmiss, function () {\n          ScanJS.loadRules([rule]);\n          var ast = acorn.parse(rule.testmiss, {locations: true});\n          var results = ScanJS.scan(ast);\n          chai.expect(results).to.have.length(0);\n        });\n      });\n    });\n  }\n  if (typeof $ !== \"undefined\") {\n    $.ajax({\n      url: '../common/template_rules.json',\n      async: false,\n      dataType: 'json'\n    }).done(testSetup);\n  }\n  else if (typeof require !== \"undefined\") {\n    var fs = require(\"fs\");\n    var signatures = JSON.parse(fs.readFileSync(\"../common/template_rules.json\", \"utf8\"));\n    testSetup(signatures);\n  }\n})"
  },
  {
    "path": "tests/cases/window.open.js",
    "content": "(function () {\n  describe('window.open tests', function () {\n    context('ignores safe patterns', function () {\n      context(null, function () {\n        var good = 'var open = \"string window.open\";';\n        it(good, function () {\n          chai.expect(ScanJS.scan(good, \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var a = {}; a.open = \"string\"; ';\n        it(good, function () {\n          chai.expect(ScanJS.scan(good, \"/tests/\")).to.be.empty;\n        });\n      });\n      context(null, function () {\n        var good = 'var a = {}; a.open = function () { alert(1); }; a.open(\"1\", \"2\", a);';\n        it(good, function () {\n          chai.expect(ScanJS.scan(good, \"/tests/\")).to.be.empty;\n        });\n      });\n    });\n    context('detects dangerous patterns', function () {\n      context(null, function () {\n        var bad = 'win = window.open(\"http://www.mozilla.org\", \"name\", fets);';\n        it(bad, function () {\n          chai.expect(ScanJS.scan(bad, \"/tests/\")).not.to.be.empty;\n        });\n      });\n      context(null, function () {\n        // issue 76 - https://github.com/mozilla/scanjs/issues/76\n        var bad = 'var o = window.open; o(\"http://www.mozilla.org\", \"name\", {});';\n        it.skip(bad, function () {\n          chai.expect(ScanJS.scan(bad, \"/tests/\")).not.to.be.empty;\n        });\n      });\n    });\n  });\n})();\n"
  },
  {
    "path": "tests/css/mocha.css",
    "content": "@charset \"utf-8\";\n\nbody {\n  margin:0;\n}\n\n#mocha {\n  font: 20px/1.5 \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  margin: 60px 50px;\n}\n\n#mocha ul,\n#mocha li {\n  margin: 0;\n  padding: 0;\n}\n\n#mocha ul {\n  list-style: none;\n}\n\n#mocha h1,\n#mocha h2 {\n  margin: 0;\n}\n\n#mocha h1 {\n  margin-top: 15px;\n  font-size: 1em;\n  font-weight: 200;\n}\n\n#mocha h1 a {\n  text-decoration: none;\n  color: inherit;\n}\n\n#mocha h1 a:hover {\n  text-decoration: underline;\n}\n\n#mocha .suite .suite h1 {\n  margin-top: 0;\n  font-size: .8em;\n}\n\n#mocha .hidden {\n  display: none;\n}\n\n#mocha h2 {\n  font-size: 12px;\n  font-weight: normal;\n  cursor: pointer;\n}\n\n#mocha .suite {\n  margin-left: 15px;\n}\n\n#mocha .test {\n  margin-left: 15px;\n  overflow: hidden;\n}\n\n#mocha .test.pending:hover h2::after {\n  content: '(pending)';\n  font-family: arial, sans-serif;\n}\n\n#mocha .test.pass.medium .duration {\n  background: #c09853;\n}\n\n#mocha .test.pass.slow .duration {\n  background: #b94a48;\n}\n\n#mocha .test.pass::before {\n  content: '✓';\n  font-size: 12px;\n  display: block;\n  float: left;\n  margin-right: 5px;\n  color: #00d6b2;\n}\n\n#mocha .test.pass .duration {\n  font-size: 9px;\n  margin-left: 5px;\n  padding: 2px 5px;\n  color: #fff;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);\n  -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);\n  box-shadow: inset 0 1px 1px rgba(0,0,0,.2);\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  -ms-border-radius: 5px;\n  -o-border-radius: 5px;\n  border-radius: 5px;\n}\n\n#mocha .test.pass.fast .duration {\n  display: none;\n}\n\n#mocha .test.pending {\n  color: #0b97c4;\n}\n\n#mocha .test.pending::before {\n  content: '◦';\n  color: #0b97c4;\n}\n\n#mocha .test.fail {\n  color: #c00;\n}\n\n#mocha .test.fail pre {\n  color: black;\n}\n\n#mocha .test.fail::before {\n  content: '✖';\n  font-size: 12px;\n  display: block;\n  float: left;\n  margin-right: 5px;\n  color: #c00;\n}\n\n#mocha .test pre.error {\n  color: #c00;\n  max-height: 300px;\n  overflow: auto;\n}\n\n/**\n * (1): approximate for browsers not supporting calc\n * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)\n *      ^^ seriously\n */\n#mocha .test pre {\n  display: block;\n  float: left;\n  clear: left;\n  font: 12px/1.5 monaco, monospace;\n  margin: 5px;\n  padding: 15px;\n  border: 1px solid #eee;\n  max-width: 85%; /*(1)*/\n  max-width: calc(100% - 42px); /*(2)*/\n  word-wrap: break-word;\n  border-bottom-color: #ddd;\n  -webkit-border-radius: 3px;\n  -webkit-box-shadow: 0 1px 3px #eee;\n  -moz-border-radius: 3px;\n  -moz-box-shadow: 0 1px 3px #eee;\n  border-radius: 3px;\n}\n\n#mocha .test h2 {\n  position: relative;\n}\n\n#mocha .test a.replay {\n  position: absolute;\n  top: 3px;\n  right: 0;\n  text-decoration: none;\n  vertical-align: middle;\n  display: block;\n  width: 15px;\n  height: 15px;\n  line-height: 15px;\n  text-align: center;\n  background: #eee;\n  font-size: 15px;\n  -moz-border-radius: 15px;\n  border-radius: 15px;\n  -webkit-transition: opacity 200ms;\n  -moz-transition: opacity 200ms;\n  transition: opacity 200ms;\n  opacity: 0.3;\n  color: #888;\n}\n\n#mocha .test:hover a.replay {\n  opacity: 1;\n}\n\n#mocha-report.pass .test.fail {\n  display: none;\n}\n\n#mocha-report.fail .test.pass {\n  display: none;\n}\n\n#mocha-report.pending .test.pass,\n#mocha-report.pending .test.fail {\n  display: none;\n}\n#mocha-report.pending .test.pass.pending {\n  display: block;\n}\n\n#mocha-error {\n  color: #c00;\n  font-size: 1.5em;\n  font-weight: 100;\n  letter-spacing: 1px;\n}\n\n#mocha-stats {\n  position: fixed;\n  top: 15px;\n  right: 10px;\n  font-size: 12px;\n  margin: 0;\n  color: #888;\n  z-index: 1;\n}\n\n#mocha-stats .progress {\n  float: right;\n  padding-top: 0;\n}\n\n#mocha-stats em {\n  color: black;\n}\n\n#mocha-stats a {\n  text-decoration: none;\n  color: inherit;\n}\n\n#mocha-stats a:hover {\n  border-bottom: 1px solid #eee;\n}\n\n#mocha-stats li {\n  display: inline-block;\n  margin: 0 5px;\n  list-style: none;\n  padding-top: 11px;\n}\n\n#mocha-stats canvas {\n  width: 40px;\n  height: 40px;\n}\n\n#mocha code .comment { color: #ddd; }\n#mocha code .init { color: #2f6fad; }\n#mocha code .string { color: #5890ad; }\n#mocha code .keyword { color: #8a6343; }\n#mocha code .number { color: #2f6fad; }\n\n@media screen and (max-device-width: 480px) {\n  #mocha {\n    margin: 60px 0px;\n  }\n\n  #mocha #stats {\n    position: absolute;\n  }\n}\n"
  },
  {
    "path": "tests/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"content-security-policy\" content=\"default-src 'self'; object-src 'none'; img-src 'self' data:; script-src 'self' 'unsafe-eval'\">\n  <title>Scan.js Tests</title>\n  <!-- Third-party libs -->\n  <script src='../client/js/lib/jquery-2.1.0.min.js'></script>\n  <script src='../client/js/lib/acorn.js'></script>\n  <script src='../client/js/lib/walk.js'></script>\n  <script src='../client/js/lib/acorn_loose.js'></script>\n  <!-- CommonJS modules -->\n  <script src='../common/scan.js'></script>\n  <!-- Testing framework files -->\n  <link href='css/mocha.css' rel='stylesheet' media='screen'>\n  <script src='js/mocha.js'></script>\n  <script src='js/chai.js'></script>\n  <script src='js/main.js'></script>\n</head>\n<body>\n<h5><a href=\"advanced.html\">More detailed tests (work in progress)</a></h5>\n  <div id=\"mocha\"><p><h1><b>Scan.js Mocha Unit Tests</b></h1></p></div>\n  <div id=\"messages\"></div>\n  <div id=\"fixtures\"></div>\n\n\n\n  <!-- rule test cases -->\n  <script src='cases/placeholders.js'></script>\n  <script src='cases/test_ruletests.js'></script>\n  <script src='cases/production_ruletests.js'></script>\n\n\n</body>\n</html>\n"
  },
  {
    "path": "tests/js/chai.js",
    "content": ";(function(){\n\n/**\n * Require the given path.\n *\n * @param {String} path\n * @return {Object} exports\n * @api public\n */\n\nfunction require(path, parent, orig) {\n  var resolved = require.resolve(path);\n\n  // lookup failed\n  if (null == resolved) {\n    orig = orig || path;\n    parent = parent || 'root';\n    var err = new Error('Failed to require \"' + orig + '\" from \"' + parent + '\"');\n    err.path = orig;\n    err.parent = parent;\n    err.require = true;\n    throw err;\n  }\n\n  var module = require.modules[resolved];\n\n  // perform real require()\n  // by invoking the module's\n  // registered function\n  if (!module._resolving && !module.exports) {\n    var mod = {};\n    mod.exports = {};\n    mod.client = mod.component = true;\n    module._resolving = true;\n    module.call(this, mod.exports, require.relative(resolved), mod);\n    delete module._resolving;\n    module.exports = mod.exports;\n  }\n\n  return module.exports;\n}\n\n/**\n * Registered modules.\n */\n\nrequire.modules = {};\n\n/**\n * Registered aliases.\n */\n\nrequire.aliases = {};\n\n/**\n * Resolve `path`.\n *\n * Lookup:\n *\n *   - PATH/index.js\n *   - PATH.js\n *   - PATH\n *\n * @param {String} path\n * @return {String} path or null\n * @api private\n */\n\nrequire.resolve = function(path) {\n  if (path.charAt(0) === '/') path = path.slice(1);\n\n  var paths = [\n    path,\n    path + '.js',\n    path + '.json',\n    path + '/index.js',\n    path + '/index.json'\n  ];\n\n  for (var i = 0; i < paths.length; i++) {\n    var path = paths[i];\n    if (require.modules.hasOwnProperty(path)) return path;\n    if (require.aliases.hasOwnProperty(path)) return require.aliases[path];\n  }\n};\n\n/**\n * Normalize `path` relative to the current path.\n *\n * @param {String} curr\n * @param {String} path\n * @return {String}\n * @api private\n */\n\nrequire.normalize = function(curr, path) {\n  var segs = [];\n\n  if ('.' != path.charAt(0)) return path;\n\n  curr = curr.split('/');\n  path = path.split('/');\n\n  for (var i = 0; i < path.length; ++i) {\n    if ('..' == path[i]) {\n      curr.pop();\n    } else if ('.' != path[i] && '' != path[i]) {\n      segs.push(path[i]);\n    }\n  }\n\n  return curr.concat(segs).join('/');\n};\n\n/**\n * Register module at `path` with callback `definition`.\n *\n * @param {String} path\n * @param {Function} definition\n * @api private\n */\n\nrequire.register = function(path, definition) {\n  require.modules[path] = definition;\n};\n\n/**\n * Alias a module definition.\n *\n * @param {String} from\n * @param {String} to\n * @api private\n */\n\nrequire.alias = function(from, to) {\n  if (!require.modules.hasOwnProperty(from)) {\n    throw new Error('Failed to alias \"' + from + '\", it does not exist');\n  }\n  require.aliases[to] = from;\n};\n\n/**\n * Return a require function relative to the `parent` path.\n *\n * @param {String} parent\n * @return {Function}\n * @api private\n */\n\nrequire.relative = function(parent) {\n  var p = require.normalize(parent, '..');\n\n  /**\n   * lastIndexOf helper.\n   */\n\n  function lastIndexOf(arr, obj) {\n    var i = arr.length;\n    while (i--) {\n      if (arr[i] === obj) return i;\n    }\n    return -1;\n  }\n\n  /**\n   * The relative require() itself.\n   */\n\n  function localRequire(path) {\n    var resolved = localRequire.resolve(path);\n    return require(resolved, parent, path);\n  }\n\n  /**\n   * Resolve relative to the parent.\n   */\n\n  localRequire.resolve = function(path) {\n    var c = path.charAt(0);\n    if ('/' == c) return path.slice(1);\n    if ('.' == c) return require.normalize(p, path);\n\n    // resolve deps by returning\n    // the dep in the nearest \"deps\"\n    // directory\n    var segs = parent.split('/');\n    var i = lastIndexOf(segs, 'deps') + 1;\n    if (!i) i = 0;\n    path = segs.slice(0, i + 1).join('/') + '/deps/' + path;\n    return path;\n  };\n\n  /**\n   * Check if module is defined at `path`.\n   */\n\n  localRequire.exists = function(path) {\n    return require.modules.hasOwnProperty(localRequire.resolve(path));\n  };\n\n  return localRequire;\n};\nrequire.register(\"chaijs-assertion-error/index.js\", function(exports, require, module){\n/*!\n * assertion-error\n * Copyright(c) 2013 Jake Luer <jake@qualiancy.com>\n * MIT Licensed\n */\n\n/*!\n * Return a function that will copy properties from\n * one object to another excluding any originally\n * listed. Returned function will create a new `{}`.\n *\n * @param {String} excluded properties ...\n * @return {Function}\n */\n\nfunction exclude () {\n  var excludes = [].slice.call(arguments);\n\n  function excludeProps (res, obj) {\n    Object.keys(obj).forEach(function (key) {\n      if (!~excludes.indexOf(key)) res[key] = obj[key];\n    });\n  }\n\n  return function extendExclude () {\n    var args = [].slice.call(arguments)\n      , i = 0\n      , res = {};\n\n    for (; i < args.length; i++) {\n      excludeProps(res, args[i]);\n    }\n\n    return res;\n  };\n};\n\n/*!\n * Primary Exports\n */\n\nmodule.exports = AssertionError;\n\n/**\n * ### AssertionError\n *\n * An extension of the JavaScript `Error` constructor for\n * assertion and validation scenarios.\n *\n * @param {String} message\n * @param {Object} properties to include (optional)\n * @param {callee} start stack function (optional)\n */\n\nfunction AssertionError (message, _props, ssf) {\n  var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')\n    , props = extend(_props || {});\n\n  // default values\n  this.message = message || 'Unspecified AssertionError';\n  this.showDiff = false;\n\n  // copy from properties\n  for (var key in props) {\n    this[key] = props[key];\n  }\n\n  // capture stack trace\n  ssf = ssf || arguments.callee;\n  if (ssf && Error.captureStackTrace) {\n    Error.captureStackTrace(this, ssf);\n  }\n}\n\n/*!\n * Inherit from Error.prototype\n */\n\nAssertionError.prototype = Object.create(Error.prototype);\n\n/*!\n * Statically set name\n */\n\nAssertionError.prototype.name = 'AssertionError';\n\n/*!\n * Ensure correct constructor\n */\n\nAssertionError.prototype.constructor = AssertionError;\n\n/**\n * Allow errors to be converted to JSON for static transfer.\n *\n * @param {Boolean} include stack (default: `true`)\n * @return {Object} object that can be `JSON.stringify`\n */\n\nAssertionError.prototype.toJSON = function (stack) {\n  var extend = exclude('constructor', 'toJSON', 'stack')\n    , props = extend({ name: this.name }, this);\n\n  // include stack if exists and not turned off\n  if (false !== stack && this.stack) {\n    props.stack = this.stack;\n  }\n\n  return props;\n};\n\n});\nrequire.register(\"chaijs-type-detect/lib/type.js\", function(exports, require, module){\n/*!\n * type-detect\n * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Primary Exports\n */\n\nvar exports = module.exports = getType;\n\n/*!\n * Detectable javascript natives\n */\n\nvar natives = {\n    '[object Array]': 'array'\n  , '[object RegExp]': 'regexp'\n  , '[object Function]': 'function'\n  , '[object Arguments]': 'arguments'\n  , '[object Date]': 'date'\n};\n\n/**\n * ### typeOf (obj)\n *\n * Use several different techniques to determine\n * the type of object being tested.\n *\n *\n * @param {Mixed} object\n * @return {String} object type\n * @api public\n */\n\nfunction getType (obj) {\n  var str = Object.prototype.toString.call(obj);\n  if (natives[str]) return natives[str];\n  if (obj === null) return 'null';\n  if (obj === undefined) return 'undefined';\n  if (obj === Object(obj)) return 'object';\n  return typeof obj;\n}\n\nexports.Library = Library;\n\n/**\n * ### Library\n *\n * Create a repository for custom type detection.\n *\n * ```js\n * var lib = new type.Library;\n * ```\n *\n */\n\nfunction Library () {\n  this.tests = {};\n}\n\n/**\n * #### .of (obj)\n *\n * Expose replacement `typeof` detection to the library.\n *\n * ```js\n * if ('string' === lib.of('hello world')) {\n *   // ...\n * }\n * ```\n *\n * @param {Mixed} object to test\n * @return {String} type\n */\n\nLibrary.prototype.of = getType;\n\n/**\n * #### .define (type, test)\n *\n * Add a test to for the `.test()` assertion.\n *\n * Can be defined as a regular expression:\n *\n * ```js\n * lib.define('int', /^[0-9]+$/);\n * ```\n *\n * ... or as a function:\n *\n * ```js\n * lib.define('bln', function (obj) {\n *   if ('boolean' === lib.of(obj)) return true;\n *   var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];\n *   if ('string' === lib.of(obj)) obj = obj.toLowerCase();\n *   return !! ~blns.indexOf(obj);\n * });\n * ```\n *\n * @param {String} type\n * @param {RegExp|Function} test\n * @api public\n */\n\nLibrary.prototype.define = function (type, test) {\n  if (arguments.length === 1) return this.tests[type];\n  this.tests[type] = test;\n  return this;\n};\n\n/**\n * #### .test (obj, test)\n *\n * Assert that an object is of type. Will first\n * check natives, and if that does not pass it will\n * use the user defined custom tests.\n *\n * ```js\n * assert(lib.test('1', 'int'));\n * assert(lib.test('yes', 'bln'));\n * ```\n *\n * @param {Mixed} object\n * @param {String} type\n * @return {Boolean} result\n * @api public\n */\n\nLibrary.prototype.test = function (obj, type) {\n  if (type === getType(obj)) return true;\n  var test = this.tests[type];\n\n  if (test && 'regexp' === getType(test)) {\n    return test.test(obj);\n  } else if (test && 'function' === getType(test)) {\n    return test(obj);\n  } else {\n    throw new ReferenceError('Type test \"' + type + '\" not defined or invalid.');\n  }\n};\n\n});\nrequire.register(\"chaijs-deep-eql/lib/eql.js\", function(exports, require, module){\n/*!\n * deep-eql\n * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependencies\n */\n\nvar type = require('type-detect');\n\n/*!\n * Buffer.isBuffer browser shim\n */\n\nvar Buffer;\ntry { Buffer = require('buffer').Buffer; }\ncatch(ex) {\n  Buffer = {};\n  Buffer.isBuffer = function() { return false; }\n}\n\n/*!\n * Primary Export\n */\n\nmodule.exports = deepEqual;\n\n/**\n * Assert super-strict (egal) equality between\n * two objects of any type.\n *\n * @param {Mixed} a\n * @param {Mixed} b\n * @param {Array} memoised (optional)\n * @return {Boolean} equal match\n */\n\nfunction deepEqual(a, b, m) {\n  if (sameValue(a, b)) {\n    return true;\n  } else if ('date' === type(a)) {\n    return dateEqual(a, b);\n  } else if ('regexp' === type(a)) {\n    return regexpEqual(a, b);\n  } else if (Buffer.isBuffer(a)) {\n    return bufferEqual(a, b);\n  } else if ('arguments' === type(a)) {\n    return argumentsEqual(a, b, m);\n  } else if (!typeEqual(a, b)) {\n    return false;\n  } else if (('object' !== type(a) && 'object' !== type(b))\n  && ('array' !== type(a) && 'array' !== type(b))) {\n    return sameValue(a, b);\n  } else {\n    return objectEqual(a, b, m);\n  }\n}\n\n/*!\n * Strict (egal) equality test. Ensures that NaN always\n * equals NaN and `-0` does not equal `+0`.\n *\n * @param {Mixed} a\n * @param {Mixed} b\n * @return {Boolean} equal match\n */\n\nfunction sameValue(a, b) {\n  if (a === b) return a !== 0 || 1 / a === 1 / b;\n  return a !== a && b !== b;\n}\n\n/*!\n * Compare the types of two given objects and\n * return if they are equal. Note that an Array\n * has a type of `array` (not `object`) and arguments\n * have a type of `arguments` (not `array`/`object`).\n *\n * @param {Mixed} a\n * @param {Mixed} b\n * @return {Boolean} result\n */\n\nfunction typeEqual(a, b) {\n  return type(a) === type(b);\n}\n\n/*!\n * Compare two Date objects by asserting that\n * the time values are equal using `saveValue`.\n *\n * @param {Date} a\n * @param {Date} b\n * @return {Boolean} result\n */\n\nfunction dateEqual(a, b) {\n  if ('date' !== type(b)) return false;\n  return sameValue(a.getTime(), b.getTime());\n}\n\n/*!\n * Compare two regular expressions by converting them\n * to string and checking for `sameValue`.\n *\n * @param {RegExp} a\n * @param {RegExp} b\n * @return {Boolean} result\n */\n\nfunction regexpEqual(a, b) {\n  if ('regexp' !== type(b)) return false;\n  return sameValue(a.toString(), b.toString());\n}\n\n/*!\n * Assert deep equality of two `arguments` objects.\n * Unfortunately, these must be sliced to arrays\n * prior to test to ensure no bad behavior.\n *\n * @param {Arguments} a\n * @param {Arguments} b\n * @param {Array} memoize (optional)\n * @return {Boolean} result\n */\n\nfunction argumentsEqual(a, b, m) {\n  if ('arguments' !== type(b)) return false;\n  a = [].slice.call(a);\n  b = [].slice.call(b);\n  return deepEqual(a, b, m);\n}\n\n/*!\n * Get enumerable properties of a given object.\n *\n * @param {Object} a\n * @return {Array} property names\n */\n\nfunction enumerable(a) {\n  var res = [];\n  for (var key in a) res.push(key);\n  return res;\n}\n\n/*!\n * Simple equality for flat iterable objects\n * such as Arrays or Node.js buffers.\n *\n * @param {Iterable} a\n * @param {Iterable} b\n * @return {Boolean} result\n */\n\nfunction iterableEqual(a, b) {\n  if (a.length !==  b.length) return false;\n\n  var i = 0;\n  var match = true;\n\n  for (; i < a.length; i++) {\n    if (a[i] !== b[i]) {\n      match = false;\n      break;\n    }\n  }\n\n  return match;\n}\n\n/*!\n * Extension to `iterableEqual` specifically\n * for Node.js Buffers.\n *\n * @param {Buffer} a\n * @param {Mixed} b\n * @return {Boolean} result\n */\n\nfunction bufferEqual(a, b) {\n  if (!Buffer.isBuffer(b)) return false;\n  return iterableEqual(a, b);\n}\n\n/*!\n * Block for `objectEqual` ensuring non-existing\n * values don't get in.\n *\n * @param {Mixed} object\n * @return {Boolean} result\n */\n\nfunction isValue(a) {\n  return a !== null && a !== undefined;\n}\n\n/*!\n * Recursively check the equality of two objects.\n * Once basic sameness has been established it will\n * defer to `deepEqual` for each enumerable key\n * in the object.\n *\n * @param {Mixed} a\n * @param {Mixed} b\n * @return {Boolean} result\n */\n\nfunction objectEqual(a, b, m) {\n  if (!isValue(a) || !isValue(b)) {\n    return false;\n  }\n\n  if (a.prototype !== b.prototype) {\n    return false;\n  }\n\n  var i;\n  if (m) {\n    for (i = 0; i < m.length; i++) {\n      if ((m[i][0] === a && m[i][1] === b)\n      ||  (m[i][0] === b && m[i][1] === a)) {\n        return true;\n      }\n    }\n  } else {\n    m = [];\n  }\n\n  try {\n    var ka = enumerable(a);\n    var kb = enumerable(b);\n  } catch (ex) {\n    return false;\n  }\n\n  ka.sort();\n  kb.sort();\n\n  if (!iterableEqual(ka, kb)) {\n    return false;\n  }\n\n  m.push([ a, b ]);\n\n  var key;\n  for (i = ka.length - 1; i >= 0; i--) {\n    key = ka[i];\n    if (!deepEqual(a[key], b[key], m)) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n});\nrequire.register(\"chai/index.js\", function(exports, require, module){\nmodule.exports = require('./lib/chai');\n\n});\nrequire.register(\"chai/lib/chai.js\", function(exports, require, module){\n/*!\n * chai\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar used = []\n  , exports = module.exports = {};\n\n/*!\n * Chai version\n */\n\nexports.version = '1.8.1';\n\n/*!\n * Assertion Error\n */\n\nexports.AssertionError = require('assertion-error');\n\n/*!\n * Utils for plugins (not exported)\n */\n\nvar util = require('./chai/utils');\n\n/**\n * # .use(function)\n *\n * Provides a way to extend the internals of Chai\n *\n * @param {Function}\n * @returns {this} for chaining\n * @api public\n */\n\nexports.use = function (fn) {\n  if (!~used.indexOf(fn)) {\n    fn(this, util);\n    used.push(fn);\n  }\n\n  return this;\n};\n\n/*!\n * Primary `Assertion` prototype\n */\n\nvar assertion = require('./chai/assertion');\nexports.use(assertion);\n\n/*!\n * Core Assertions\n */\n\nvar core = require('./chai/core/assertions');\nexports.use(core);\n\n/*!\n * Expect interface\n */\n\nvar expect = require('./chai/interface/expect');\nexports.use(expect);\n\n/*!\n * Should interface\n */\n\nvar should = require('./chai/interface/should');\nexports.use(should);\n\n/*!\n * Assert interface\n */\n\nvar assert = require('./chai/interface/assert');\nexports.use(assert);\n\n});\nrequire.register(\"chai/lib/chai/assertion.js\", function(exports, require, module){\n/*!\n * chai\n * http://chaijs.com\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (_chai, util) {\n  /*!\n   * Module dependencies.\n   */\n\n  var AssertionError = _chai.AssertionError\n    , flag = util.flag;\n\n  /*!\n   * Module export.\n   */\n\n  _chai.Assertion = Assertion;\n\n  /*!\n   * Assertion Constructor\n   *\n   * Creates object for chaining.\n   *\n   * @api private\n   */\n\n  function Assertion (obj, msg, stack) {\n    flag(this, 'ssfi', stack || arguments.callee);\n    flag(this, 'object', obj);\n    flag(this, 'message', msg);\n  }\n\n  /*!\n    * ### Assertion.includeStack\n    *\n    * User configurable property, influences whether stack trace\n    * is included in Assertion error message. Default of false\n    * suppresses stack trace in the error message\n    *\n    *     Assertion.includeStack = true;  // enable stack on error\n    *\n    * @api public\n    */\n\n  Assertion.includeStack = false;\n\n  /*!\n   * ### Assertion.showDiff\n   *\n   * User configurable property, influences whether or not\n   * the `showDiff` flag should be included in the thrown\n   * AssertionErrors. `false` will always be `false`; `true`\n   * will be true when the assertion has requested a diff\n   * be shown.\n   *\n   * @api public\n   */\n\n  Assertion.showDiff = true;\n\n  Assertion.addProperty = function (name, fn) {\n    util.addProperty(this.prototype, name, fn);\n  };\n\n  Assertion.addMethod = function (name, fn) {\n    util.addMethod(this.prototype, name, fn);\n  };\n\n  Assertion.addChainableMethod = function (name, fn, chainingBehavior) {\n    util.addChainableMethod(this.prototype, name, fn, chainingBehavior);\n  };\n\n  Assertion.overwriteProperty = function (name, fn) {\n    util.overwriteProperty(this.prototype, name, fn);\n  };\n\n  Assertion.overwriteMethod = function (name, fn) {\n    util.overwriteMethod(this.prototype, name, fn);\n  };\n\n  Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {\n    util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);\n  };\n\n  /*!\n   * ### .assert(expression, message, negateMessage, expected, actual)\n   *\n   * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.\n   *\n   * @name assert\n   * @param {Philosophical} expression to be tested\n   * @param {String} message to display if fails\n   * @param {String} negatedMessage to display if negated expression fails\n   * @param {Mixed} expected value (remember to check for negation)\n   * @param {Mixed} actual (optional) will default to `this.obj`\n   * @api private\n   */\n\n  Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {\n    var ok = util.test(this, arguments);\n    if (true !== showDiff) showDiff = false;\n    if (true !== Assertion.showDiff) showDiff = false;\n\n    if (!ok) {\n      var msg = util.getMessage(this, arguments)\n        , actual = util.getActual(this, arguments);\n      throw new AssertionError(msg, {\n          actual: actual\n        , expected: expected\n        , showDiff: showDiff\n      }, (Assertion.includeStack) ? this.assert : flag(this, 'ssfi'));\n    }\n  };\n\n  /*!\n   * ### ._obj\n   *\n   * Quick reference to stored `actual` value for plugin developers.\n   *\n   * @api private\n   */\n\n  Object.defineProperty(Assertion.prototype, '_obj',\n    { get: function () {\n        return flag(this, 'object');\n      }\n    , set: function (val) {\n        flag(this, 'object', val);\n      }\n  });\n};\n\n});\nrequire.register(\"chai/lib/chai/core/assertions.js\", function(exports, require, module){\n/*!\n * chai\n * http://chaijs.com\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (chai, _) {\n  var Assertion = chai.Assertion\n    , toString = Object.prototype.toString\n    , flag = _.flag;\n\n  /**\n   * ### Language Chains\n   *\n   * The following are provided as chainable getters to\n   * improve the readability of your assertions. They\n   * do not provide an testing capability unless they\n   * have been overwritten by a plugin.\n   *\n   * **Chains**\n   *\n   * - to\n   * - be\n   * - been\n   * - is\n   * - that\n   * - and\n   * - has\n   * - have\n   * - with\n   * - at\n   * - of\n   * - same\n   *\n   * @name language chains\n   * @api public\n   */\n\n  [ 'to', 'be', 'been'\n  , 'is', 'and', 'has', 'have'\n  , 'with', 'that', 'at'\n  , 'of', 'same' ].forEach(function (chain) {\n    Assertion.addProperty(chain, function () {\n      return this;\n    });\n  });\n\n  /**\n   * ### .not\n   *\n   * Negates any of assertions following in the chain.\n   *\n   *     expect(foo).to.not.equal('bar');\n   *     expect(goodFn).to.not.throw(Error);\n   *     expect({ foo: 'baz' }).to.have.property('foo')\n   *       .and.not.equal('bar');\n   *\n   * @name not\n   * @api public\n   */\n\n  Assertion.addProperty('not', function () {\n    flag(this, 'negate', true);\n  });\n\n  /**\n   * ### .deep\n   *\n   * Sets the `deep` flag, later used by the `equal` and\n   * `property` assertions.\n   *\n   *     expect(foo).to.deep.equal({ bar: 'baz' });\n   *     expect({ foo: { bar: { baz: 'quux' } } })\n   *       .to.have.deep.property('foo.bar.baz', 'quux');\n   *\n   * @name deep\n   * @api public\n   */\n\n  Assertion.addProperty('deep', function () {\n    flag(this, 'deep', true);\n  });\n\n  /**\n   * ### .a(type)\n   *\n   * The `a` and `an` assertions are aliases that can be\n   * used either as language chains or to assert a value's\n   * type.\n   *\n   *     // typeof\n   *     expect('test').to.be.a('string');\n   *     expect({ foo: 'bar' }).to.be.an('object');\n   *     expect(null).to.be.a('null');\n   *     expect(undefined).to.be.an('undefined');\n   *\n   *     // language chain\n   *     expect(foo).to.be.an.instanceof(Foo);\n   *\n   * @name a\n   * @alias an\n   * @param {String} type\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function an (type, msg) {\n    if (msg) flag(this, 'message', msg);\n    type = type.toLowerCase();\n    var obj = flag(this, 'object')\n      , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';\n\n    this.assert(\n        type === _.type(obj)\n      , 'expected #{this} to be ' + article + type\n      , 'expected #{this} not to be ' + article + type\n    );\n  }\n\n  Assertion.addChainableMethod('an', an);\n  Assertion.addChainableMethod('a', an);\n\n  /**\n   * ### .include(value)\n   *\n   * The `include` and `contain` assertions can be used as either property\n   * based language chains or as methods to assert the inclusion of an object\n   * in an array or a substring in a string. When used as language chains,\n   * they toggle the `contain` flag for the `keys` assertion.\n   *\n   *     expect([1,2,3]).to.include(2);\n   *     expect('foobar').to.contain('foo');\n   *     expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');\n   *\n   * @name include\n   * @alias contain\n   * @param {Object|String|Number} obj\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function includeChainingBehavior () {\n    flag(this, 'contains', true);\n  }\n\n  function include (val, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n\n    if (_.type(val) === 'object') {\n      if (!flag(this, 'negate')) {\n        for (var k in val) new Assertion(obj).property(k, val[k]);\n        return;\n      }\n      var subset = {}\n      for (var k in val) subset[k] = obj[k]\n      var expected = _.eql(subset, val);\n    } else {\n      var expected = obj && ~obj.indexOf(val)\n    }\n    this.assert(\n        expected\n      , 'expected #{this} to include ' + _.inspect(val)\n      , 'expected #{this} to not include ' + _.inspect(val));\n  }\n\n  Assertion.addChainableMethod('include', include, includeChainingBehavior);\n  Assertion.addChainableMethod('contain', include, includeChainingBehavior);\n\n  /**\n   * ### .ok\n   *\n   * Asserts that the target is truthy.\n   *\n   *     expect('everthing').to.be.ok;\n   *     expect(1).to.be.ok;\n   *     expect(false).to.not.be.ok;\n   *     expect(undefined).to.not.be.ok;\n   *     expect(null).to.not.be.ok;\n   *\n   * @name ok\n   * @api public\n   */\n\n  Assertion.addProperty('ok', function () {\n    this.assert(\n        flag(this, 'object')\n      , 'expected #{this} to be truthy'\n      , 'expected #{this} to be falsy');\n  });\n\n  /**\n   * ### .true\n   *\n   * Asserts that the target is `true`.\n   *\n   *     expect(true).to.be.true;\n   *     expect(1).to.not.be.true;\n   *\n   * @name true\n   * @api public\n   */\n\n  Assertion.addProperty('true', function () {\n    this.assert(\n        true === flag(this, 'object')\n      , 'expected #{this} to be true'\n      , 'expected #{this} to be false'\n      , this.negate ? false : true\n    );\n  });\n\n  /**\n   * ### .false\n   *\n   * Asserts that the target is `false`.\n   *\n   *     expect(false).to.be.false;\n   *     expect(0).to.not.be.false;\n   *\n   * @name false\n   * @api public\n   */\n\n  Assertion.addProperty('false', function () {\n    this.assert(\n        false === flag(this, 'object')\n      , 'expected #{this} to be false'\n      , 'expected #{this} to be true'\n      , this.negate ? true : false\n    );\n  });\n\n  /**\n   * ### .null\n   *\n   * Asserts that the target is `null`.\n   *\n   *     expect(null).to.be.null;\n   *     expect(undefined).not.to.be.null;\n   *\n   * @name null\n   * @api public\n   */\n\n  Assertion.addProperty('null', function () {\n    this.assert(\n        null === flag(this, 'object')\n      , 'expected #{this} to be null'\n      , 'expected #{this} not to be null'\n    );\n  });\n\n  /**\n   * ### .undefined\n   *\n   * Asserts that the target is `undefined`.\n   *\n   *     expect(undefined).to.be.undefined;\n   *     expect(null).to.not.be.undefined;\n   *\n   * @name undefined\n   * @api public\n   */\n\n  Assertion.addProperty('undefined', function () {\n    this.assert(\n        undefined === flag(this, 'object')\n      , 'expected #{this} to be undefined'\n      , 'expected #{this} not to be undefined'\n    );\n  });\n\n  /**\n   * ### .exist\n   *\n   * Asserts that the target is neither `null` nor `undefined`.\n   *\n   *     var foo = 'hi'\n   *       , bar = null\n   *       , baz;\n   *\n   *     expect(foo).to.exist;\n   *     expect(bar).to.not.exist;\n   *     expect(baz).to.not.exist;\n   *\n   * @name exist\n   * @api public\n   */\n\n  Assertion.addProperty('exist', function () {\n    this.assert(\n        null != flag(this, 'object')\n      , 'expected #{this} to exist'\n      , 'expected #{this} to not exist'\n    );\n  });\n\n\n  /**\n   * ### .empty\n   *\n   * Asserts that the target's length is `0`. For arrays, it checks\n   * the `length` property. For objects, it gets the count of\n   * enumerable keys.\n   *\n   *     expect([]).to.be.empty;\n   *     expect('').to.be.empty;\n   *     expect({}).to.be.empty;\n   *\n   * @name empty\n   * @api public\n   */\n\n  Assertion.addProperty('empty', function () {\n    var obj = flag(this, 'object')\n      , expected = obj;\n\n    if (Array.isArray(obj) || 'string' === typeof object) {\n      expected = obj.length;\n    } else if (typeof obj === 'object') {\n      expected = Object.keys(obj).length;\n    }\n\n    this.assert(\n        !expected\n      , 'expected #{this} to be empty'\n      , 'expected #{this} not to be empty'\n    );\n  });\n\n  /**\n   * ### .arguments\n   *\n   * Asserts that the target is an arguments object.\n   *\n   *     function test () {\n   *       expect(arguments).to.be.arguments;\n   *     }\n   *\n   * @name arguments\n   * @alias Arguments\n   * @api public\n   */\n\n  function checkArguments () {\n    var obj = flag(this, 'object')\n      , type = Object.prototype.toString.call(obj);\n    this.assert(\n        '[object Arguments]' === type\n      , 'expected #{this} to be arguments but got ' + type\n      , 'expected #{this} to not be arguments'\n    );\n  }\n\n  Assertion.addProperty('arguments', checkArguments);\n  Assertion.addProperty('Arguments', checkArguments);\n\n  /**\n   * ### .equal(value)\n   *\n   * Asserts that the target is strictly equal (`===`) to `value`.\n   * Alternately, if the `deep` flag is set, asserts that\n   * the target is deeply equal to `value`.\n   *\n   *     expect('hello').to.equal('hello');\n   *     expect(42).to.equal(42);\n   *     expect(1).to.not.equal(true);\n   *     expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });\n   *     expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });\n   *\n   * @name equal\n   * @alias equals\n   * @alias eq\n   * @alias deep.equal\n   * @param {Mixed} value\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function assertEqual (val, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    if (flag(this, 'deep')) {\n      return this.eql(val);\n    } else {\n      this.assert(\n          val === obj\n        , 'expected #{this} to equal #{exp}'\n        , 'expected #{this} to not equal #{exp}'\n        , val\n        , this._obj\n        , true\n      );\n    }\n  }\n\n  Assertion.addMethod('equal', assertEqual);\n  Assertion.addMethod('equals', assertEqual);\n  Assertion.addMethod('eq', assertEqual);\n\n  /**\n   * ### .eql(value)\n   *\n   * Asserts that the target is deeply equal to `value`.\n   *\n   *     expect({ foo: 'bar' }).to.eql({ foo: 'bar' });\n   *     expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);\n   *\n   * @name eql\n   * @alias eqls\n   * @param {Mixed} value\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function assertEql(obj, msg) {\n    if (msg) flag(this, 'message', msg);\n    this.assert(\n        _.eql(obj, flag(this, 'object'))\n      , 'expected #{this} to deeply equal #{exp}'\n      , 'expected #{this} to not deeply equal #{exp}'\n      , obj\n      , this._obj\n      , true\n    );\n  }\n\n  Assertion.addMethod('eql', assertEql);\n  Assertion.addMethod('eqls', assertEql);\n\n  /**\n   * ### .above(value)\n   *\n   * Asserts that the target is greater than `value`.\n   *\n   *     expect(10).to.be.above(5);\n   *\n   * Can also be used in conjunction with `length` to\n   * assert a minimum length. The benefit being a\n   * more informative error message than if the length\n   * was supplied directly.\n   *\n   *     expect('foo').to.have.length.above(2);\n   *     expect([ 1, 2, 3 ]).to.have.length.above(2);\n   *\n   * @name above\n   * @alias gt\n   * @alias greaterThan\n   * @param {Number} value\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function assertAbove (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    if (flag(this, 'doLength')) {\n      new Assertion(obj, msg).to.have.property('length');\n      var len = obj.length;\n      this.assert(\n          len > n\n        , 'expected #{this} to have a length above #{exp} but got #{act}'\n        , 'expected #{this} to not have a length above #{exp}'\n        , n\n        , len\n      );\n    } else {\n      this.assert(\n          obj > n\n        , 'expected #{this} to be above ' + n\n        , 'expected #{this} to be at most ' + n\n      );\n    }\n  }\n\n  Assertion.addMethod('above', assertAbove);\n  Assertion.addMethod('gt', assertAbove);\n  Assertion.addMethod('greaterThan', assertAbove);\n\n  /**\n   * ### .least(value)\n   *\n   * Asserts that the target is greater than or equal to `value`.\n   *\n   *     expect(10).to.be.at.least(10);\n   *\n   * Can also be used in conjunction with `length` to\n   * assert a minimum length. The benefit being a\n   * more informative error message than if the length\n   * was supplied directly.\n   *\n   *     expect('foo').to.have.length.of.at.least(2);\n   *     expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);\n   *\n   * @name least\n   * @alias gte\n   * @param {Number} value\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function assertLeast (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    if (flag(this, 'doLength')) {\n      new Assertion(obj, msg).to.have.property('length');\n      var len = obj.length;\n      this.assert(\n          len >= n\n        , 'expected #{this} to have a length at least #{exp} but got #{act}'\n        , 'expected #{this} to have a length below #{exp}'\n        , n\n        , len\n      );\n    } else {\n      this.assert(\n          obj >= n\n        , 'expected #{this} to be at least ' + n\n        , 'expected #{this} to be below ' + n\n      );\n    }\n  }\n\n  Assertion.addMethod('least', assertLeast);\n  Assertion.addMethod('gte', assertLeast);\n\n  /**\n   * ### .below(value)\n   *\n   * Asserts that the target is less than `value`.\n   *\n   *     expect(5).to.be.below(10);\n   *\n   * Can also be used in conjunction with `length` to\n   * assert a maximum length. The benefit being a\n   * more informative error message than if the length\n   * was supplied directly.\n   *\n   *     expect('foo').to.have.length.below(4);\n   *     expect([ 1, 2, 3 ]).to.have.length.below(4);\n   *\n   * @name below\n   * @alias lt\n   * @alias lessThan\n   * @param {Number} value\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function assertBelow (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    if (flag(this, 'doLength')) {\n      new Assertion(obj, msg).to.have.property('length');\n      var len = obj.length;\n      this.assert(\n          len < n\n        , 'expected #{this} to have a length below #{exp} but got #{act}'\n        , 'expected #{this} to not have a length below #{exp}'\n        , n\n        , len\n      );\n    } else {\n      this.assert(\n          obj < n\n        , 'expected #{this} to be below ' + n\n        , 'expected #{this} to be at least ' + n\n      );\n    }\n  }\n\n  Assertion.addMethod('below', assertBelow);\n  Assertion.addMethod('lt', assertBelow);\n  Assertion.addMethod('lessThan', assertBelow);\n\n  /**\n   * ### .most(value)\n   *\n   * Asserts that the target is less than or equal to `value`.\n   *\n   *     expect(5).to.be.at.most(5);\n   *\n   * Can also be used in conjunction with `length` to\n   * assert a maximum length. The benefit being a\n   * more informative error message than if the length\n   * was supplied directly.\n   *\n   *     expect('foo').to.have.length.of.at.most(4);\n   *     expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);\n   *\n   * @name most\n   * @alias lte\n   * @param {Number} value\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function assertMost (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    if (flag(this, 'doLength')) {\n      new Assertion(obj, msg).to.have.property('length');\n      var len = obj.length;\n      this.assert(\n          len <= n\n        , 'expected #{this} to have a length at most #{exp} but got #{act}'\n        , 'expected #{this} to have a length above #{exp}'\n        , n\n        , len\n      );\n    } else {\n      this.assert(\n          obj <= n\n        , 'expected #{this} to be at most ' + n\n        , 'expected #{this} to be above ' + n\n      );\n    }\n  }\n\n  Assertion.addMethod('most', assertMost);\n  Assertion.addMethod('lte', assertMost);\n\n  /**\n   * ### .within(start, finish)\n   *\n   * Asserts that the target is within a range.\n   *\n   *     expect(7).to.be.within(5,10);\n   *\n   * Can also be used in conjunction with `length` to\n   * assert a length range. The benefit being a\n   * more informative error message than if the length\n   * was supplied directly.\n   *\n   *     expect('foo').to.have.length.within(2,4);\n   *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);\n   *\n   * @name within\n   * @param {Number} start lowerbound inclusive\n   * @param {Number} finish upperbound inclusive\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  Assertion.addMethod('within', function (start, finish, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , range = start + '..' + finish;\n    if (flag(this, 'doLength')) {\n      new Assertion(obj, msg).to.have.property('length');\n      var len = obj.length;\n      this.assert(\n          len >= start && len <= finish\n        , 'expected #{this} to have a length within ' + range\n        , 'expected #{this} to not have a length within ' + range\n      );\n    } else {\n      this.assert(\n          obj >= start && obj <= finish\n        , 'expected #{this} to be within ' + range\n        , 'expected #{this} to not be within ' + range\n      );\n    }\n  });\n\n  /**\n   * ### .instanceof(constructor)\n   *\n   * Asserts that the target is an instance of `constructor`.\n   *\n   *     var Tea = function (name) { this.name = name; }\n   *       , Chai = new Tea('chai');\n   *\n   *     expect(Chai).to.be.an.instanceof(Tea);\n   *     expect([ 1, 2, 3 ]).to.be.instanceof(Array);\n   *\n   * @name instanceof\n   * @param {Constructor} constructor\n   * @param {String} message _optional_\n   * @alias instanceOf\n   * @api public\n   */\n\n  function assertInstanceOf (constructor, msg) {\n    if (msg) flag(this, 'message', msg);\n    var name = _.getName(constructor);\n    this.assert(\n        flag(this, 'object') instanceof constructor\n      , 'expected #{this} to be an instance of ' + name\n      , 'expected #{this} to not be an instance of ' + name\n    );\n  };\n\n  Assertion.addMethod('instanceof', assertInstanceOf);\n  Assertion.addMethod('instanceOf', assertInstanceOf);\n\n  /**\n   * ### .property(name, [value])\n   *\n   * Asserts that the target has a property `name`, optionally asserting that\n   * the value of that property is strictly equal to  `value`.\n   * If the `deep` flag is set, you can use dot- and bracket-notation for deep\n   * references into objects and arrays.\n   *\n   *     // simple referencing\n   *     var obj = { foo: 'bar' };\n   *     expect(obj).to.have.property('foo');\n   *     expect(obj).to.have.property('foo', 'bar');\n   *\n   *     // deep referencing\n   *     var deepObj = {\n   *         green: { tea: 'matcha' }\n   *       , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]\n   *     };\n\n   *     expect(deepObj).to.have.deep.property('green.tea', 'matcha');\n   *     expect(deepObj).to.have.deep.property('teas[1]', 'matcha');\n   *     expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');\n   *\n   * You can also use an array as the starting point of a `deep.property`\n   * assertion, or traverse nested arrays.\n   *\n   *     var arr = [\n   *         [ 'chai', 'matcha', 'konacha' ]\n   *       , [ { tea: 'chai' }\n   *         , { tea: 'matcha' }\n   *         , { tea: 'konacha' } ]\n   *     ];\n   *\n   *     expect(arr).to.have.deep.property('[0][1]', 'matcha');\n   *     expect(arr).to.have.deep.property('[1][2].tea', 'konacha');\n   *\n   * Furthermore, `property` changes the subject of the assertion\n   * to be the value of that property from the original object. This\n   * permits for further chainable assertions on that property.\n   *\n   *     expect(obj).to.have.property('foo')\n   *       .that.is.a('string');\n   *     expect(deepObj).to.have.property('green')\n   *       .that.is.an('object')\n   *       .that.deep.equals({ tea: 'matcha' });\n   *     expect(deepObj).to.have.property('teas')\n   *       .that.is.an('array')\n   *       .with.deep.property('[2]')\n   *         .that.deep.equals({ tea: 'konacha' });\n   *\n   * @name property\n   * @alias deep.property\n   * @param {String} name\n   * @param {Mixed} value (optional)\n   * @param {String} message _optional_\n   * @returns value of property for chaining\n   * @api public\n   */\n\n  Assertion.addMethod('property', function (name, val, msg) {\n    if (msg) flag(this, 'message', msg);\n\n    var descriptor = flag(this, 'deep') ? 'deep property ' : 'property '\n      , negate = flag(this, 'negate')\n      , obj = flag(this, 'object')\n      , value = flag(this, 'deep')\n        ? _.getPathValue(name, obj)\n        : obj[name];\n\n    if (negate && undefined !== val) {\n      if (undefined === value) {\n        msg = (msg != null) ? msg + ': ' : '';\n        throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));\n      }\n    } else {\n      this.assert(\n          undefined !== value\n        , 'expected #{this} to have a ' + descriptor + _.inspect(name)\n        , 'expected #{this} to not have ' + descriptor + _.inspect(name));\n    }\n\n    if (undefined !== val) {\n      this.assert(\n          val === value\n        , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'\n        , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'\n        , val\n        , value\n      );\n    }\n\n    flag(this, 'object', value);\n  });\n\n\n  /**\n   * ### .ownProperty(name)\n   *\n   * Asserts that the target has an own property `name`.\n   *\n   *     expect('test').to.have.ownProperty('length');\n   *\n   * @name ownProperty\n   * @alias haveOwnProperty\n   * @param {String} name\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function assertOwnProperty (name, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    this.assert(\n        obj.hasOwnProperty(name)\n      , 'expected #{this} to have own property ' + _.inspect(name)\n      , 'expected #{this} to not have own property ' + _.inspect(name)\n    );\n  }\n\n  Assertion.addMethod('ownProperty', assertOwnProperty);\n  Assertion.addMethod('haveOwnProperty', assertOwnProperty);\n\n  /**\n   * ### .length(value)\n   *\n   * Asserts that the target's `length` property has\n   * the expected value.\n   *\n   *     expect([ 1, 2, 3]).to.have.length(3);\n   *     expect('foobar').to.have.length(6);\n   *\n   * Can also be used as a chain precursor to a value\n   * comparison for the length property.\n   *\n   *     expect('foo').to.have.length.above(2);\n   *     expect([ 1, 2, 3 ]).to.have.length.above(2);\n   *     expect('foo').to.have.length.below(4);\n   *     expect([ 1, 2, 3 ]).to.have.length.below(4);\n   *     expect('foo').to.have.length.within(2,4);\n   *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);\n   *\n   * @name length\n   * @alias lengthOf\n   * @param {Number} length\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  function assertLengthChain () {\n    flag(this, 'doLength', true);\n  }\n\n  function assertLength (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    new Assertion(obj, msg).to.have.property('length');\n    var len = obj.length;\n\n    this.assert(\n        len == n\n      , 'expected #{this} to have a length of #{exp} but got #{act}'\n      , 'expected #{this} to not have a length of #{act}'\n      , n\n      , len\n    );\n  }\n\n  Assertion.addChainableMethod('length', assertLength, assertLengthChain);\n  Assertion.addMethod('lengthOf', assertLength, assertLengthChain);\n\n  /**\n   * ### .match(regexp)\n   *\n   * Asserts that the target matches a regular expression.\n   *\n   *     expect('foobar').to.match(/^foo/);\n   *\n   * @name match\n   * @param {RegExp} RegularExpression\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  Assertion.addMethod('match', function (re, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    this.assert(\n        re.exec(obj)\n      , 'expected #{this} to match ' + re\n      , 'expected #{this} not to match ' + re\n    );\n  });\n\n  /**\n   * ### .string(string)\n   *\n   * Asserts that the string target contains another string.\n   *\n   *     expect('foobar').to.have.string('bar');\n   *\n   * @name string\n   * @param {String} string\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  Assertion.addMethod('string', function (str, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    new Assertion(obj, msg).is.a('string');\n\n    this.assert(\n        ~obj.indexOf(str)\n      , 'expected #{this} to contain ' + _.inspect(str)\n      , 'expected #{this} to not contain ' + _.inspect(str)\n    );\n  });\n\n\n  /**\n   * ### .keys(key1, [key2], [...])\n   *\n   * Asserts that the target has exactly the given keys, or\n   * asserts the inclusion of some keys when using the\n   * `include` or `contain` modifiers.\n   *\n   *     expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);\n   *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');\n   *\n   * @name keys\n   * @alias key\n   * @param {String...|Array} keys\n   * @api public\n   */\n\n  function assertKeys (keys) {\n    var obj = flag(this, 'object')\n      , str\n      , ok = true;\n\n    keys = keys instanceof Array\n      ? keys\n      : Array.prototype.slice.call(arguments);\n\n    if (!keys.length) throw new Error('keys required');\n\n    var actual = Object.keys(obj)\n      , len = keys.length;\n\n    // Inclusion\n    ok = keys.every(function(key){\n      return ~actual.indexOf(key);\n    });\n\n    // Strict\n    if (!flag(this, 'negate') && !flag(this, 'contains')) {\n      ok = ok && keys.length == actual.length;\n    }\n\n    // Key string\n    if (len > 1) {\n      keys = keys.map(function(key){\n        return _.inspect(key);\n      });\n      var last = keys.pop();\n      str = keys.join(', ') + ', and ' + last;\n    } else {\n      str = _.inspect(keys[0]);\n    }\n\n    // Form\n    str = (len > 1 ? 'keys ' : 'key ') + str;\n\n    // Have / include\n    str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;\n\n    // Assertion\n    this.assert(\n        ok\n      , 'expected #{this} to ' + str\n      , 'expected #{this} to not ' + str\n    );\n  }\n\n  Assertion.addMethod('keys', assertKeys);\n  Assertion.addMethod('key', assertKeys);\n\n  /**\n   * ### .throw(constructor)\n   *\n   * Asserts that the function target will throw a specific error, or specific type of error\n   * (as determined using `instanceof`), optionally with a RegExp or string inclusion test\n   * for the error's message.\n   *\n   *     var err = new ReferenceError('This is a bad function.');\n   *     var fn = function () { throw err; }\n   *     expect(fn).to.throw(ReferenceError);\n   *     expect(fn).to.throw(Error);\n   *     expect(fn).to.throw(/bad function/);\n   *     expect(fn).to.not.throw('good function');\n   *     expect(fn).to.throw(ReferenceError, /bad function/);\n   *     expect(fn).to.throw(err);\n   *     expect(fn).to.not.throw(new RangeError('Out of range.'));\n   *\n   * Please note that when a throw expectation is negated, it will check each\n   * parameter independently, starting with error constructor type. The appropriate way\n   * to check for the existence of a type of error but for a message that does not match\n   * is to use `and`.\n   *\n   *     expect(fn).to.throw(ReferenceError)\n   *        .and.not.throw(/good function/);\n   *\n   * @name throw\n   * @alias throws\n   * @alias Throw\n   * @param {ErrorConstructor} constructor\n   * @param {String|RegExp} expected error message\n   * @param {String} message _optional_\n   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n   * @returns error for chaining (null if no error)\n   * @api public\n   */\n\n  function assertThrows (constructor, errMsg, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    new Assertion(obj, msg).is.a('function');\n\n    var thrown = false\n      , desiredError = null\n      , name = null\n      , thrownError = null;\n\n    if (arguments.length === 0) {\n      errMsg = null;\n      constructor = null;\n    } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {\n      errMsg = constructor;\n      constructor = null;\n    } else if (constructor && constructor instanceof Error) {\n      desiredError = constructor;\n      constructor = null;\n      errMsg = null;\n    } else if (typeof constructor === 'function') {\n      name = constructor.prototype.name || constructor.name;\n      if (name === 'Error' && constructor !== Error) {\n        name = (new constructor()).name;\n      }\n    } else {\n      constructor = null;\n    }\n\n    try {\n      obj();\n    } catch (err) {\n      // first, check desired error\n      if (desiredError) {\n        this.assert(\n            err === desiredError\n          , 'expected #{this} to throw #{exp} but #{act} was thrown'\n          , 'expected #{this} to not throw #{exp}'\n          , (desiredError instanceof Error ? desiredError.toString() : desiredError)\n          , (err instanceof Error ? err.toString() : err)\n        );\n\n        flag(this, 'object', err);\n        return this;\n      }\n\n      // next, check constructor\n      if (constructor) {\n        this.assert(\n            err instanceof constructor\n          , 'expected #{this} to throw #{exp} but #{act} was thrown'\n          , 'expected #{this} to not throw #{exp} but #{act} was thrown'\n          , name\n          , (err instanceof Error ? err.toString() : err)\n        );\n\n        if (!errMsg) {\n          flag(this, 'object', err);\n          return this;\n        }\n      }\n\n      // next, check message\n      var message = 'object' === _.type(err) && \"message\" in err\n        ? err.message\n        : '' + err;\n\n      if ((message != null) && errMsg && errMsg instanceof RegExp) {\n        this.assert(\n            errMsg.exec(message)\n          , 'expected #{this} to throw error matching #{exp} but got #{act}'\n          , 'expected #{this} to throw error not matching #{exp}'\n          , errMsg\n          , message\n        );\n\n        flag(this, 'object', err);\n        return this;\n      } else if ((message != null) && errMsg && 'string' === typeof errMsg) {\n        this.assert(\n            ~message.indexOf(errMsg)\n          , 'expected #{this} to throw error including #{exp} but got #{act}'\n          , 'expected #{this} to throw error not including #{act}'\n          , errMsg\n          , message\n        );\n\n        flag(this, 'object', err);\n        return this;\n      } else {\n        thrown = true;\n        thrownError = err;\n      }\n    }\n\n    var actuallyGot = ''\n      , expectedThrown = name !== null\n        ? name\n        : desiredError\n          ? '#{exp}' //_.inspect(desiredError)\n          : 'an error';\n\n    if (thrown) {\n      actuallyGot = ' but #{act} was thrown'\n    }\n\n    this.assert(\n        thrown === true\n      , 'expected #{this} to throw ' + expectedThrown + actuallyGot\n      , 'expected #{this} to not throw ' + expectedThrown + actuallyGot\n      , (desiredError instanceof Error ? desiredError.toString() : desiredError)\n      , (thrownError instanceof Error ? thrownError.toString() : thrownError)\n    );\n\n    flag(this, 'object', thrownError);\n  };\n\n  Assertion.addMethod('throw', assertThrows);\n  Assertion.addMethod('throws', assertThrows);\n  Assertion.addMethod('Throw', assertThrows);\n\n  /**\n   * ### .respondTo(method)\n   *\n   * Asserts that the object or class target will respond to a method.\n   *\n   *     Klass.prototype.bar = function(){};\n   *     expect(Klass).to.respondTo('bar');\n   *     expect(obj).to.respondTo('bar');\n   *\n   * To check if a constructor will respond to a static function,\n   * set the `itself` flag.\n   *\n   *     Klass.baz = function(){};\n   *     expect(Klass).itself.to.respondTo('baz');\n   *\n   * @name respondTo\n   * @param {String} method\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  Assertion.addMethod('respondTo', function (method, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , itself = flag(this, 'itself')\n      , context = ('function' === _.type(obj) && !itself)\n        ? obj.prototype[method]\n        : obj[method];\n\n    this.assert(\n        'function' === typeof context\n      , 'expected #{this} to respond to ' + _.inspect(method)\n      , 'expected #{this} to not respond to ' + _.inspect(method)\n    );\n  });\n\n  /**\n   * ### .itself\n   *\n   * Sets the `itself` flag, later used by the `respondTo` assertion.\n   *\n   *     function Foo() {}\n   *     Foo.bar = function() {}\n   *     Foo.prototype.baz = function() {}\n   *\n   *     expect(Foo).itself.to.respondTo('bar');\n   *     expect(Foo).itself.not.to.respondTo('baz');\n   *\n   * @name itself\n   * @api public\n   */\n\n  Assertion.addProperty('itself', function () {\n    flag(this, 'itself', true);\n  });\n\n  /**\n   * ### .satisfy(method)\n   *\n   * Asserts that the target passes a given truth test.\n   *\n   *     expect(1).to.satisfy(function(num) { return num > 0; });\n   *\n   * @name satisfy\n   * @param {Function} matcher\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  Assertion.addMethod('satisfy', function (matcher, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    this.assert(\n        matcher(obj)\n      , 'expected #{this} to satisfy ' + _.objDisplay(matcher)\n      , 'expected #{this} to not satisfy' + _.objDisplay(matcher)\n      , this.negate ? false : true\n      , matcher(obj)\n    );\n  });\n\n  /**\n   * ### .closeTo(expected, delta)\n   *\n   * Asserts that the target is equal `expected`, to within a +/- `delta` range.\n   *\n   *     expect(1.5).to.be.closeTo(1, 0.5);\n   *\n   * @name closeTo\n   * @param {Number} expected\n   * @param {Number} delta\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  Assertion.addMethod('closeTo', function (expected, delta, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    this.assert(\n        Math.abs(obj - expected) <= delta\n      , 'expected #{this} to be close to ' + expected + ' +/- ' + delta\n      , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta\n    );\n  });\n\n  function isSubsetOf(subset, superset) {\n    return subset.every(function(elem) {\n      return superset.indexOf(elem) !== -1;\n    })\n  }\n\n  /**\n   * ### .members(set)\n   *\n   * Asserts that the target is a superset of `set`,\n   * or that the target and `set` have the same members.\n   *\n   *     expect([1, 2, 3]).to.include.members([3, 2]);\n   *     expect([1, 2, 3]).to.not.include.members([3, 2, 8]);\n   *\n   *     expect([4, 2]).to.have.members([2, 4]);\n   *     expect([5, 2]).to.not.have.members([5, 2, 1]);\n   *\n   * @name members\n   * @param {Array} set\n   * @param {String} message _optional_\n   * @api public\n   */\n\n  Assertion.addMethod('members', function (subset, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n\n    new Assertion(obj).to.be.an('array');\n    new Assertion(subset).to.be.an('array');\n\n    if (flag(this, 'contains')) {\n      return this.assert(\n          isSubsetOf(subset, obj)\n        , 'expected #{this} to be a superset of #{act}'\n        , 'expected #{this} to not be a superset of #{act}'\n        , obj\n        , subset\n      );\n    }\n\n    this.assert(\n        isSubsetOf(obj, subset) && isSubsetOf(subset, obj)\n        , 'expected #{this} to have the same members as #{act}'\n        , 'expected #{this} to not have the same members as #{act}'\n        , obj\n        , subset\n    );\n  });\n};\n\n});\nrequire.register(\"chai/lib/chai/interface/assert.js\", function(exports, require, module){\n/*!\n * chai\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n\nmodule.exports = function (chai, util) {\n\n  /*!\n   * Chai dependencies.\n   */\n\n  var Assertion = chai.Assertion\n    , flag = util.flag;\n\n  /*!\n   * Module export.\n   */\n\n  /**\n   * ### assert(expression, message)\n   *\n   * Write your own test expressions.\n   *\n   *     assert('foo' !== 'bar', 'foo is not bar');\n   *     assert(Array.isArray([]), 'empty arrays are arrays');\n   *\n   * @param {Mixed} expression to test for truthiness\n   * @param {String} message to display on error\n   * @name assert\n   * @api public\n   */\n\n  var assert = chai.assert = function (express, errmsg) {\n    var test = new Assertion(null);\n    test.assert(\n        express\n      , errmsg\n      , '[ negation message unavailable ]'\n    );\n  };\n\n  /**\n   * ### .fail(actual, expected, [message], [operator])\n   *\n   * Throw a failure. Node.js `assert` module-compatible.\n   *\n   * @name fail\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @param {String} operator\n   * @api public\n   */\n\n  assert.fail = function (actual, expected, message, operator) {\n    message = message || 'assert.fail()';\n    throw new chai.AssertionError(message, {\n        actual: actual\n      , expected: expected\n      , operator: operator\n    }, assert.fail);\n  };\n\n  /**\n   * ### .ok(object, [message])\n   *\n   * Asserts that `object` is truthy.\n   *\n   *     assert.ok('everything', 'everything is ok');\n   *     assert.ok(false, 'this will fail');\n   *\n   * @name ok\n   * @param {Mixed} object to test\n   * @param {String} message\n   * @api public\n   */\n\n  assert.ok = function (val, msg) {\n    new Assertion(val, msg).is.ok;\n  };\n\n  /**\n   * ### .notOk(object, [message])\n   *\n   * Asserts that `object` is falsy.\n   *\n   *     assert.notOk('everything', 'this will fail');\n   *     assert.notOk(false, 'this will pass');\n   *\n   * @name notOk\n   * @param {Mixed} object to test\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notOk = function (val, msg) {\n    new Assertion(val, msg).is.not.ok;\n  };\n\n  /**\n   * ### .equal(actual, expected, [message])\n   *\n   * Asserts non-strict equality (`==`) of `actual` and `expected`.\n   *\n   *     assert.equal(3, '3', '== coerces values to strings');\n   *\n   * @name equal\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @api public\n   */\n\n  assert.equal = function (act, exp, msg) {\n    var test = new Assertion(act, msg);\n\n    test.assert(\n        exp == flag(test, 'object')\n      , 'expected #{this} to equal #{exp}'\n      , 'expected #{this} to not equal #{act}'\n      , exp\n      , act\n    );\n  };\n\n  /**\n   * ### .notEqual(actual, expected, [message])\n   *\n   * Asserts non-strict inequality (`!=`) of `actual` and `expected`.\n   *\n   *     assert.notEqual(3, 4, 'these numbers are not equal');\n   *\n   * @name notEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notEqual = function (act, exp, msg) {\n    var test = new Assertion(act, msg);\n\n    test.assert(\n        exp != flag(test, 'object')\n      , 'expected #{this} to not equal #{exp}'\n      , 'expected #{this} to equal #{act}'\n      , exp\n      , act\n    );\n  };\n\n  /**\n   * ### .strictEqual(actual, expected, [message])\n   *\n   * Asserts strict equality (`===`) of `actual` and `expected`.\n   *\n   *     assert.strictEqual(true, true, 'these booleans are strictly equal');\n   *\n   * @name strictEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @api public\n   */\n\n  assert.strictEqual = function (act, exp, msg) {\n    new Assertion(act, msg).to.equal(exp);\n  };\n\n  /**\n   * ### .notStrictEqual(actual, expected, [message])\n   *\n   * Asserts strict inequality (`!==`) of `actual` and `expected`.\n   *\n   *     assert.notStrictEqual(3, '3', 'no coercion for strict equality');\n   *\n   * @name notStrictEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notStrictEqual = function (act, exp, msg) {\n    new Assertion(act, msg).to.not.equal(exp);\n  };\n\n  /**\n   * ### .deepEqual(actual, expected, [message])\n   *\n   * Asserts that `actual` is deeply equal to `expected`.\n   *\n   *     assert.deepEqual({ tea: 'green' }, { tea: 'green' });\n   *\n   * @name deepEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @api public\n   */\n\n  assert.deepEqual = function (act, exp, msg) {\n    new Assertion(act, msg).to.eql(exp);\n  };\n\n  /**\n   * ### .notDeepEqual(actual, expected, [message])\n   *\n   * Assert that `actual` is not deeply equal to `expected`.\n   *\n   *     assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });\n   *\n   * @name notDeepEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notDeepEqual = function (act, exp, msg) {\n    new Assertion(act, msg).to.not.eql(exp);\n  };\n\n  /**\n   * ### .isTrue(value, [message])\n   *\n   * Asserts that `value` is true.\n   *\n   *     var teaServed = true;\n   *     assert.isTrue(teaServed, 'the tea has been served');\n   *\n   * @name isTrue\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isTrue = function (val, msg) {\n    new Assertion(val, msg).is['true'];\n  };\n\n  /**\n   * ### .isFalse(value, [message])\n   *\n   * Asserts that `value` is false.\n   *\n   *     var teaServed = false;\n   *     assert.isFalse(teaServed, 'no tea yet? hmm...');\n   *\n   * @name isFalse\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isFalse = function (val, msg) {\n    new Assertion(val, msg).is['false'];\n  };\n\n  /**\n   * ### .isNull(value, [message])\n   *\n   * Asserts that `value` is null.\n   *\n   *     assert.isNull(err, 'there was no error');\n   *\n   * @name isNull\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNull = function (val, msg) {\n    new Assertion(val, msg).to.equal(null);\n  };\n\n  /**\n   * ### .isNotNull(value, [message])\n   *\n   * Asserts that `value` is not null.\n   *\n   *     var tea = 'tasty chai';\n   *     assert.isNotNull(tea, 'great, time for tea!');\n   *\n   * @name isNotNull\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNotNull = function (val, msg) {\n    new Assertion(val, msg).to.not.equal(null);\n  };\n\n  /**\n   * ### .isUndefined(value, [message])\n   *\n   * Asserts that `value` is `undefined`.\n   *\n   *     var tea;\n   *     assert.isUndefined(tea, 'no tea defined');\n   *\n   * @name isUndefined\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isUndefined = function (val, msg) {\n    new Assertion(val, msg).to.equal(undefined);\n  };\n\n  /**\n   * ### .isDefined(value, [message])\n   *\n   * Asserts that `value` is not `undefined`.\n   *\n   *     var tea = 'cup of chai';\n   *     assert.isDefined(tea, 'tea has been defined');\n   *\n   * @name isDefined\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isDefined = function (val, msg) {\n    new Assertion(val, msg).to.not.equal(undefined);\n  };\n\n  /**\n   * ### .isFunction(value, [message])\n   *\n   * Asserts that `value` is a function.\n   *\n   *     function serveTea() { return 'cup of tea'; };\n   *     assert.isFunction(serveTea, 'great, we can have tea now');\n   *\n   * @name isFunction\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isFunction = function (val, msg) {\n    new Assertion(val, msg).to.be.a('function');\n  };\n\n  /**\n   * ### .isNotFunction(value, [message])\n   *\n   * Asserts that `value` is _not_ a function.\n   *\n   *     var serveTea = [ 'heat', 'pour', 'sip' ];\n   *     assert.isNotFunction(serveTea, 'great, we have listed the steps');\n   *\n   * @name isNotFunction\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNotFunction = function (val, msg) {\n    new Assertion(val, msg).to.not.be.a('function');\n  };\n\n  /**\n   * ### .isObject(value, [message])\n   *\n   * Asserts that `value` is an object (as revealed by\n   * `Object.prototype.toString`).\n   *\n   *     var selection = { name: 'Chai', serve: 'with spices' };\n   *     assert.isObject(selection, 'tea selection is an object');\n   *\n   * @name isObject\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isObject = function (val, msg) {\n    new Assertion(val, msg).to.be.a('object');\n  };\n\n  /**\n   * ### .isNotObject(value, [message])\n   *\n   * Asserts that `value` is _not_ an object.\n   *\n   *     var selection = 'chai'\n   *     assert.isObject(selection, 'tea selection is not an object');\n   *     assert.isObject(null, 'null is not an object');\n   *\n   * @name isNotObject\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNotObject = function (val, msg) {\n    new Assertion(val, msg).to.not.be.a('object');\n  };\n\n  /**\n   * ### .isArray(value, [message])\n   *\n   * Asserts that `value` is an array.\n   *\n   *     var menu = [ 'green', 'chai', 'oolong' ];\n   *     assert.isArray(menu, 'what kind of tea do we want?');\n   *\n   * @name isArray\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isArray = function (val, msg) {\n    new Assertion(val, msg).to.be.an('array');\n  };\n\n  /**\n   * ### .isNotArray(value, [message])\n   *\n   * Asserts that `value` is _not_ an array.\n   *\n   *     var menu = 'green|chai|oolong';\n   *     assert.isNotArray(menu, 'what kind of tea do we want?');\n   *\n   * @name isNotArray\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNotArray = function (val, msg) {\n    new Assertion(val, msg).to.not.be.an('array');\n  };\n\n  /**\n   * ### .isString(value, [message])\n   *\n   * Asserts that `value` is a string.\n   *\n   *     var teaOrder = 'chai';\n   *     assert.isString(teaOrder, 'order placed');\n   *\n   * @name isString\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isString = function (val, msg) {\n    new Assertion(val, msg).to.be.a('string');\n  };\n\n  /**\n   * ### .isNotString(value, [message])\n   *\n   * Asserts that `value` is _not_ a string.\n   *\n   *     var teaOrder = 4;\n   *     assert.isNotString(teaOrder, 'order placed');\n   *\n   * @name isNotString\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNotString = function (val, msg) {\n    new Assertion(val, msg).to.not.be.a('string');\n  };\n\n  /**\n   * ### .isNumber(value, [message])\n   *\n   * Asserts that `value` is a number.\n   *\n   *     var cups = 2;\n   *     assert.isNumber(cups, 'how many cups');\n   *\n   * @name isNumber\n   * @param {Number} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNumber = function (val, msg) {\n    new Assertion(val, msg).to.be.a('number');\n  };\n\n  /**\n   * ### .isNotNumber(value, [message])\n   *\n   * Asserts that `value` is _not_ a number.\n   *\n   *     var cups = '2 cups please';\n   *     assert.isNotNumber(cups, 'how many cups');\n   *\n   * @name isNotNumber\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNotNumber = function (val, msg) {\n    new Assertion(val, msg).to.not.be.a('number');\n  };\n\n  /**\n   * ### .isBoolean(value, [message])\n   *\n   * Asserts that `value` is a boolean.\n   *\n   *     var teaReady = true\n   *       , teaServed = false;\n   *\n   *     assert.isBoolean(teaReady, 'is the tea ready');\n   *     assert.isBoolean(teaServed, 'has tea been served');\n   *\n   * @name isBoolean\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isBoolean = function (val, msg) {\n    new Assertion(val, msg).to.be.a('boolean');\n  };\n\n  /**\n   * ### .isNotBoolean(value, [message])\n   *\n   * Asserts that `value` is _not_ a boolean.\n   *\n   *     var teaReady = 'yep'\n   *       , teaServed = 'nope';\n   *\n   *     assert.isNotBoolean(teaReady, 'is the tea ready');\n   *     assert.isNotBoolean(teaServed, 'has tea been served');\n   *\n   * @name isNotBoolean\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.isNotBoolean = function (val, msg) {\n    new Assertion(val, msg).to.not.be.a('boolean');\n  };\n\n  /**\n   * ### .typeOf(value, name, [message])\n   *\n   * Asserts that `value`'s type is `name`, as determined by\n   * `Object.prototype.toString`.\n   *\n   *     assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');\n   *     assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');\n   *     assert.typeOf('tea', 'string', 'we have a string');\n   *     assert.typeOf(/tea/, 'regexp', 'we have a regular expression');\n   *     assert.typeOf(null, 'null', 'we have a null');\n   *     assert.typeOf(undefined, 'undefined', 'we have an undefined');\n   *\n   * @name typeOf\n   * @param {Mixed} value\n   * @param {String} name\n   * @param {String} message\n   * @api public\n   */\n\n  assert.typeOf = function (val, type, msg) {\n    new Assertion(val, msg).to.be.a(type);\n  };\n\n  /**\n   * ### .notTypeOf(value, name, [message])\n   *\n   * Asserts that `value`'s type is _not_ `name`, as determined by\n   * `Object.prototype.toString`.\n   *\n   *     assert.notTypeOf('tea', 'number', 'strings are not numbers');\n   *\n   * @name notTypeOf\n   * @param {Mixed} value\n   * @param {String} typeof name\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notTypeOf = function (val, type, msg) {\n    new Assertion(val, msg).to.not.be.a(type);\n  };\n\n  /**\n   * ### .instanceOf(object, constructor, [message])\n   *\n   * Asserts that `value` is an instance of `constructor`.\n   *\n   *     var Tea = function (name) { this.name = name; }\n   *       , chai = new Tea('chai');\n   *\n   *     assert.instanceOf(chai, Tea, 'chai is an instance of tea');\n   *\n   * @name instanceOf\n   * @param {Object} object\n   * @param {Constructor} constructor\n   * @param {String} message\n   * @api public\n   */\n\n  assert.instanceOf = function (val, type, msg) {\n    new Assertion(val, msg).to.be.instanceOf(type);\n  };\n\n  /**\n   * ### .notInstanceOf(object, constructor, [message])\n   *\n   * Asserts `value` is not an instance of `constructor`.\n   *\n   *     var Tea = function (name) { this.name = name; }\n   *       , chai = new String('chai');\n   *\n   *     assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');\n   *\n   * @name notInstanceOf\n   * @param {Object} object\n   * @param {Constructor} constructor\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notInstanceOf = function (val, type, msg) {\n    new Assertion(val, msg).to.not.be.instanceOf(type);\n  };\n\n  /**\n   * ### .include(haystack, needle, [message])\n   *\n   * Asserts that `haystack` includes `needle`. Works\n   * for strings and arrays.\n   *\n   *     assert.include('foobar', 'bar', 'foobar contains string \"bar\"');\n   *     assert.include([ 1, 2, 3 ], 3, 'array contains value');\n   *\n   * @name include\n   * @param {Array|String} haystack\n   * @param {Mixed} needle\n   * @param {String} message\n   * @api public\n   */\n\n  assert.include = function (exp, inc, msg) {\n    new Assertion(exp, msg).include(inc);\n  };\n\n  /**\n   * ### .notInclude(haystack, needle, [message])\n   *\n   * Asserts that `haystack` does not include `needle`. Works\n   * for strings and arrays.\n   *i\n   *     assert.notInclude('foobar', 'baz', 'string not include substring');\n   *     assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');\n   *\n   * @name notInclude\n   * @param {Array|String} haystack\n   * @param {Mixed} needle\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notInclude = function (exp, inc, msg) {\n    new Assertion(exp, msg).not.include(inc);\n  };\n\n  /**\n   * ### .match(value, regexp, [message])\n   *\n   * Asserts that `value` matches the regular expression `regexp`.\n   *\n   *     assert.match('foobar', /^foo/, 'regexp matches');\n   *\n   * @name match\n   * @param {Mixed} value\n   * @param {RegExp} regexp\n   * @param {String} message\n   * @api public\n   */\n\n  assert.match = function (exp, re, msg) {\n    new Assertion(exp, msg).to.match(re);\n  };\n\n  /**\n   * ### .notMatch(value, regexp, [message])\n   *\n   * Asserts that `value` does not match the regular expression `regexp`.\n   *\n   *     assert.notMatch('foobar', /^foo/, 'regexp does not match');\n   *\n   * @name notMatch\n   * @param {Mixed} value\n   * @param {RegExp} regexp\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notMatch = function (exp, re, msg) {\n    new Assertion(exp, msg).to.not.match(re);\n  };\n\n  /**\n   * ### .property(object, property, [message])\n   *\n   * Asserts that `object` has a property named by `property`.\n   *\n   *     assert.property({ tea: { green: 'matcha' }}, 'tea');\n   *\n   * @name property\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @api public\n   */\n\n  assert.property = function (obj, prop, msg) {\n    new Assertion(obj, msg).to.have.property(prop);\n  };\n\n  /**\n   * ### .notProperty(object, property, [message])\n   *\n   * Asserts that `object` does _not_ have a property named by `property`.\n   *\n   *     assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');\n   *\n   * @name notProperty\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notProperty = function (obj, prop, msg) {\n    new Assertion(obj, msg).to.not.have.property(prop);\n  };\n\n  /**\n   * ### .deepProperty(object, property, [message])\n   *\n   * Asserts that `object` has a property named by `property`, which can be a\n   * string using dot- and bracket-notation for deep reference.\n   *\n   *     assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');\n   *\n   * @name deepProperty\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @api public\n   */\n\n  assert.deepProperty = function (obj, prop, msg) {\n    new Assertion(obj, msg).to.have.deep.property(prop);\n  };\n\n  /**\n   * ### .notDeepProperty(object, property, [message])\n   *\n   * Asserts that `object` does _not_ have a property named by `property`, which\n   * can be a string using dot- and bracket-notation for deep reference.\n   *\n   *     assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');\n   *\n   * @name notDeepProperty\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notDeepProperty = function (obj, prop, msg) {\n    new Assertion(obj, msg).to.not.have.deep.property(prop);\n  };\n\n  /**\n   * ### .propertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a property named by `property` with value given\n   * by `value`.\n   *\n   *     assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');\n   *\n   * @name propertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.propertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg).to.have.property(prop, val);\n  };\n\n  /**\n   * ### .propertyNotVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a property named by `property`, but with a value\n   * different from that given by `value`.\n   *\n   *     assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');\n   *\n   * @name propertyNotVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.propertyNotVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg).to.not.have.property(prop, val);\n  };\n\n  /**\n   * ### .deepPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a property named by `property` with value given\n   * by `value`. `property` can use dot- and bracket-notation for deep\n   * reference.\n   *\n   *     assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');\n   *\n   * @name deepPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.deepPropertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg).to.have.deep.property(prop, val);\n  };\n\n  /**\n   * ### .deepPropertyNotVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a property named by `property`, but with a value\n   * different from that given by `value`. `property` can use dot- and\n   * bracket-notation for deep reference.\n   *\n   *     assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');\n   *\n   * @name deepPropertyNotVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.deepPropertyNotVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg).to.not.have.deep.property(prop, val);\n  };\n\n  /**\n   * ### .lengthOf(object, length, [message])\n   *\n   * Asserts that `object` has a `length` property with the expected value.\n   *\n   *     assert.lengthOf([1,2,3], 3, 'array has length of 3');\n   *     assert.lengthOf('foobar', 5, 'string has length of 6');\n   *\n   * @name lengthOf\n   * @param {Mixed} object\n   * @param {Number} length\n   * @param {String} message\n   * @api public\n   */\n\n  assert.lengthOf = function (exp, len, msg) {\n    new Assertion(exp, msg).to.have.length(len);\n  };\n\n  /**\n   * ### .throws(function, [constructor/string/regexp], [string/regexp], [message])\n   *\n   * Asserts that `function` will throw an error that is an instance of\n   * `constructor`, or alternately that it will throw an error with message\n   * matching `regexp`.\n   *\n   *     assert.throw(fn, 'function throws a reference error');\n   *     assert.throw(fn, /function throws a reference error/);\n   *     assert.throw(fn, ReferenceError);\n   *     assert.throw(fn, ReferenceError, 'function throws a reference error');\n   *     assert.throw(fn, ReferenceError, /function throws a reference error/);\n   *\n   * @name throws\n   * @alias throw\n   * @alias Throw\n   * @param {Function} function\n   * @param {ErrorConstructor} constructor\n   * @param {RegExp} regexp\n   * @param {String} message\n   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n   * @api public\n   */\n\n  assert.Throw = function (fn, errt, errs, msg) {\n    if ('string' === typeof errt || errt instanceof RegExp) {\n      errs = errt;\n      errt = null;\n    }\n\n    var assertErr = new Assertion(fn, msg).to.Throw(errt, errs);\n    return flag(assertErr, 'object');\n  };\n\n  /**\n   * ### .doesNotThrow(function, [constructor/regexp], [message])\n   *\n   * Asserts that `function` will _not_ throw an error that is an instance of\n   * `constructor`, or alternately that it will not throw an error with message\n   * matching `regexp`.\n   *\n   *     assert.doesNotThrow(fn, Error, 'function does not throw');\n   *\n   * @name doesNotThrow\n   * @param {Function} function\n   * @param {ErrorConstructor} constructor\n   * @param {RegExp} regexp\n   * @param {String} message\n   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n   * @api public\n   */\n\n  assert.doesNotThrow = function (fn, type, msg) {\n    if ('string' === typeof type) {\n      msg = type;\n      type = null;\n    }\n\n    new Assertion(fn, msg).to.not.Throw(type);\n  };\n\n  /**\n   * ### .operator(val1, operator, val2, [message])\n   *\n   * Compares two values using `operator`.\n   *\n   *     assert.operator(1, '<', 2, 'everything is ok');\n   *     assert.operator(1, '>', 2, 'this will fail');\n   *\n   * @name operator\n   * @param {Mixed} val1\n   * @param {String} operator\n   * @param {Mixed} val2\n   * @param {String} message\n   * @api public\n   */\n\n  assert.operator = function (val, operator, val2, msg) {\n    if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) {\n      throw new Error('Invalid operator \"' + operator + '\"');\n    }\n    var test = new Assertion(eval(val + operator + val2), msg);\n    test.assert(\n        true === flag(test, 'object')\n      , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)\n      , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );\n  };\n\n  /**\n   * ### .closeTo(actual, expected, delta, [message])\n   *\n   * Asserts that the target is equal `expected`, to within a +/- `delta` range.\n   *\n   *     assert.closeTo(1.5, 1, 0.5, 'numbers are close');\n   *\n   * @name closeTo\n   * @param {Number} actual\n   * @param {Number} expected\n   * @param {Number} delta\n   * @param {String} message\n   * @api public\n   */\n\n  assert.closeTo = function (act, exp, delta, msg) {\n    new Assertion(act, msg).to.be.closeTo(exp, delta);\n  };\n\n  /**\n   * ### .sameMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` have the same members.\n   * Order is not taken into account.\n   *\n   *     assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');\n   *\n   * @name sameMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @api public\n   */\n\n  assert.sameMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg).to.have.same.members(set2);\n  }\n\n  /**\n   * ### .includeMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` is included in `superset`.\n   * Order is not taken into account.\n   *\n   *     assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');\n   *\n   * @name includeMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @api public\n   */\n\n  assert.includeMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg).to.include.members(subset);\n  }\n\n  /*!\n   * Undocumented / untested\n   */\n\n  assert.ifError = function (val, msg) {\n    new Assertion(val, msg).to.not.be.ok;\n  };\n\n  /*!\n   * Aliases.\n   */\n\n  (function alias(name, as){\n    assert[as] = assert[name];\n    return alias;\n  })\n  ('Throw', 'throw')\n  ('Throw', 'throws');\n};\n\n});\nrequire.register(\"chai/lib/chai/interface/expect.js\", function(exports, require, module){\n/*!\n * chai\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (chai, util) {\n  chai.expect = function (val, message) {\n    return new chai.Assertion(val, message);\n  };\n};\n\n\n});\nrequire.register(\"chai/lib/chai/interface/should.js\", function(exports, require, module){\n/*!\n * chai\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (chai, util) {\n  var Assertion = chai.Assertion;\n\n  function loadShould () {\n    // modify Object.prototype to have `should`\n    Object.defineProperty(Object.prototype, 'should',\n      {\n        set: function (value) {\n          // See https://github.com/chaijs/chai/issues/86: this makes\n          // `whatever.should = someValue` actually set `someValue`, which is\n          // especially useful for `global.should = require('chai').should()`.\n          //\n          // Note that we have to use [[DefineProperty]] instead of [[Put]]\n          // since otherwise we would trigger this very setter!\n          Object.defineProperty(this, 'should', {\n            value: value,\n            enumerable: true,\n            configurable: true,\n            writable: true\n          });\n        }\n      , get: function(){\n          if (this instanceof String || this instanceof Number) {\n            return new Assertion(this.constructor(this));\n          } else if (this instanceof Boolean) {\n            return new Assertion(this == true);\n          }\n          return new Assertion(this);\n        }\n      , configurable: true\n    });\n\n    var should = {};\n\n    should.equal = function (val1, val2, msg) {\n      new Assertion(val1, msg).to.equal(val2);\n    };\n\n    should.Throw = function (fn, errt, errs, msg) {\n      new Assertion(fn, msg).to.Throw(errt, errs);\n    };\n\n    should.exist = function (val, msg) {\n      new Assertion(val, msg).to.exist;\n    }\n\n    // negation\n    should.not = {}\n\n    should.not.equal = function (val1, val2, msg) {\n      new Assertion(val1, msg).to.not.equal(val2);\n    };\n\n    should.not.Throw = function (fn, errt, errs, msg) {\n      new Assertion(fn, msg).to.not.Throw(errt, errs);\n    };\n\n    should.not.exist = function (val, msg) {\n      new Assertion(val, msg).to.not.exist;\n    }\n\n    should['throw'] = should['Throw'];\n    should.not['throw'] = should.not['Throw'];\n\n    return should;\n  };\n\n  chai.should = loadShould;\n  chai.Should = loadShould;\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/addChainableMethod.js\", function(exports, require, module){\n/*!\n * Chai - addChainingMethod utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependencies\n */\n\nvar transferFlags = require('./transferFlags');\n\n/*!\n * Module variables\n */\n\n// Check whether `__proto__` is supported\nvar hasProtoSupport = '__proto__' in Object;\n\n// Without `__proto__` support, this module will need to add properties to a function.\n// However, some Function.prototype methods cannot be overwritten,\n// and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).\nvar excludeNames = /^(?:length|name|arguments|caller)$/;\n\n// Cache `Function` properties\nvar call  = Function.prototype.call,\n    apply = Function.prototype.apply;\n\n/**\n * ### addChainableMethod (ctx, name, method, chainingBehavior)\n *\n * Adds a method to an object, such that the method can also be chained.\n *\n *     utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {\n *       var obj = utils.flag(this, 'object');\n *       new chai.Assertion(obj).to.be.equal(str);\n *     });\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);\n *\n * The result can then be used as both a method assertion, executing both `method` and\n * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.\n *\n *     expect(fooStr).to.be.foo('bar');\n *     expect(fooStr).to.be.foo.equal('foo');\n *\n * @param {Object} ctx object to which the method is added\n * @param {String} name of method to add\n * @param {Function} method function to be used for `name`, when called\n * @param {Function} chainingBehavior function to be called every time the property is accessed\n * @name addChainableMethod\n * @api public\n */\n\nmodule.exports = function (ctx, name, method, chainingBehavior) {\n  if (typeof chainingBehavior !== 'function') {\n    chainingBehavior = function () { };\n  }\n\n  var chainableBehavior = {\n      method: method\n    , chainingBehavior: chainingBehavior\n  };\n\n  // save the methods so we can overwrite them later, if we need to.\n  if (!ctx.__methods) {\n    ctx.__methods = {};\n  }\n  ctx.__methods[name] = chainableBehavior;\n\n  Object.defineProperty(ctx, name,\n    { get: function () {\n        chainableBehavior.chainingBehavior.call(this);\n\n        var assert = function () {\n          var result = chainableBehavior.method.apply(this, arguments);\n          return result === undefined ? this : result;\n        };\n\n        // Use `__proto__` if available\n        if (hasProtoSupport) {\n          // Inherit all properties from the object by replacing the `Function` prototype\n          var prototype = assert.__proto__ = Object.create(this);\n          // Restore the `call` and `apply` methods from `Function`\n          prototype.call = call;\n          prototype.apply = apply;\n        }\n        // Otherwise, redefine all properties (slow!)\n        else {\n          var asserterNames = Object.getOwnPropertyNames(ctx);\n          asserterNames.forEach(function (asserterName) {\n            if (!excludeNames.test(asserterName)) {\n              var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);\n              Object.defineProperty(assert, asserterName, pd);\n            }\n          });\n        }\n\n        transferFlags(this, assert);\n        return assert;\n      }\n    , configurable: true\n  });\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/addMethod.js\", function(exports, require, module){\n/*!\n * Chai - addMethod utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .addMethod (ctx, name, method)\n *\n * Adds a method to the prototype of an object.\n *\n *     utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {\n *       var obj = utils.flag(this, 'object');\n *       new chai.Assertion(obj).to.be.equal(str);\n *     });\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.addMethod('foo', fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(fooStr).to.be.foo('bar');\n *\n * @param {Object} ctx object to which the method is added\n * @param {String} name of method to add\n * @param {Function} method function to be used for name\n * @name addMethod\n * @api public\n */\n\nmodule.exports = function (ctx, name, method) {\n  ctx[name] = function () {\n    var result = method.apply(this, arguments);\n    return result === undefined ? this : result;\n  };\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/addProperty.js\", function(exports, require, module){\n/*!\n * Chai - addProperty utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### addProperty (ctx, name, getter)\n *\n * Adds a property to the prototype of an object.\n *\n *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {\n *       var obj = utils.flag(this, 'object');\n *       new chai.Assertion(obj).to.be.instanceof(Foo);\n *     });\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.addProperty('foo', fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(myFoo).to.be.foo;\n *\n * @param {Object} ctx object to which the property is added\n * @param {String} name of property to add\n * @param {Function} getter function to be used for name\n * @name addProperty\n * @api public\n */\n\nmodule.exports = function (ctx, name, getter) {\n  Object.defineProperty(ctx, name,\n    { get: function () {\n        var result = getter.call(this);\n        return result === undefined ? this : result;\n      }\n    , configurable: true\n  });\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/flag.js\", function(exports, require, module){\n/*!\n * Chai - flag utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### flag(object ,key, [value])\n *\n * Get or set a flag value on an object. If a\n * value is provided it will be set, else it will\n * return the currently set value or `undefined` if\n * the value is not set.\n *\n *     utils.flag(this, 'foo', 'bar'); // setter\n *     utils.flag(this, 'foo'); // getter, returns `bar`\n *\n * @param {Object} object (constructed Assertion\n * @param {String} key\n * @param {Mixed} value (optional)\n * @name flag\n * @api private\n */\n\nmodule.exports = function (obj, key, value) {\n  var flags = obj.__flags || (obj.__flags = Object.create(null));\n  if (arguments.length === 3) {\n    flags[key] = value;\n  } else {\n    return flags[key];\n  }\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/getActual.js\", function(exports, require, module){\n/*!\n * Chai - getActual utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * # getActual(object, [actual])\n *\n * Returns the `actual` value for an Assertion\n *\n * @param {Object} object (constructed Assertion)\n * @param {Arguments} chai.Assertion.prototype.assert arguments\n */\n\nmodule.exports = function (obj, args) {\n  var actual = args[4];\n  return 'undefined' !== typeof actual ? actual : obj._obj;\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/getEnumerableProperties.js\", function(exports, require, module){\n/*!\n * Chai - getEnumerableProperties utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .getEnumerableProperties(object)\n *\n * This allows the retrieval of enumerable property names of an object,\n * inherited or not.\n *\n * @param {Object} object\n * @returns {Array}\n * @name getEnumerableProperties\n * @api public\n */\n\nmodule.exports = function getEnumerableProperties(object) {\n  var result = [];\n  for (var name in object) {\n    result.push(name);\n  }\n  return result;\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/getMessage.js\", function(exports, require, module){\n/*!\n * Chai - message composition utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependancies\n */\n\nvar flag = require('./flag')\n  , getActual = require('./getActual')\n  , inspect = require('./inspect')\n  , objDisplay = require('./objDisplay');\n\n/**\n * ### .getMessage(object, message, negateMessage)\n *\n * Construct the error message based on flags\n * and template tags. Template tags will return\n * a stringified inspection of the object referenced.\n *\n * Message template tags:\n * - `#{this}` current asserted object\n * - `#{act}` actual value\n * - `#{exp}` expected value\n *\n * @param {Object} object (constructed Assertion)\n * @param {Arguments} chai.Assertion.prototype.assert arguments\n * @name getMessage\n * @api public\n */\n\nmodule.exports = function (obj, args) {\n  var negate = flag(obj, 'negate')\n    , val = flag(obj, 'object')\n    , expected = args[3]\n    , actual = getActual(obj, args)\n    , msg = negate ? args[2] : args[1]\n    , flagMsg = flag(obj, 'message');\n\n  msg = msg || '';\n  msg = msg\n    .replace(/#{this}/g, objDisplay(val))\n    .replace(/#{act}/g, objDisplay(actual))\n    .replace(/#{exp}/g, objDisplay(expected));\n\n  return flagMsg ? flagMsg + ': ' + msg : msg;\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/getName.js\", function(exports, require, module){\n/*!\n * Chai - getName utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * # getName(func)\n *\n * Gets the name of a function, in a cross-browser way.\n *\n * @param {Function} a function (usually a constructor)\n */\n\nmodule.exports = function (func) {\n  if (func.name) return func.name;\n\n  var match = /^\\s?function ([^(]*)\\(/.exec(func);\n  return match && match[1] ? match[1] : \"\";\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/getPathValue.js\", function(exports, require, module){\n/*!\n * Chai - getPathValue utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * @see https://github.com/logicalparadox/filtr\n * MIT Licensed\n */\n\n/**\n * ### .getPathValue(path, object)\n *\n * This allows the retrieval of values in an\n * object given a string path.\n *\n *     var obj = {\n *         prop1: {\n *             arr: ['a', 'b', 'c']\n *           , str: 'Hello'\n *         }\n *       , prop2: {\n *             arr: [ { nested: 'Universe' } ]\n *           , str: 'Hello again!'\n *         }\n *     }\n *\n * The following would be the results.\n *\n *     getPathValue('prop1.str', obj); // Hello\n *     getPathValue('prop1.att[2]', obj); // b\n *     getPathValue('prop2.arr[0].nested', obj); // Universe\n *\n * @param {String} path\n * @param {Object} object\n * @returns {Object} value or `undefined`\n * @name getPathValue\n * @api public\n */\n\nvar getPathValue = module.exports = function (path, obj) {\n  var parsed = parsePath(path);\n  return _getPathValue(parsed, obj);\n};\n\n/*!\n * ## parsePath(path)\n *\n * Helper function used to parse string object\n * paths. Use in conjunction with `_getPathValue`.\n *\n *      var parsed = parsePath('myobject.property.subprop');\n *\n * ### Paths:\n *\n * * Can be as near infinitely deep and nested\n * * Arrays are also valid using the formal `myobject.document[3].property`.\n *\n * @param {String} path\n * @returns {Object} parsed\n * @api private\n */\n\nfunction parsePath (path) {\n  var str = path.replace(/\\[/g, '.[')\n    , parts = str.match(/(\\\\\\.|[^.]+?)+/g);\n  return parts.map(function (value) {\n    var re = /\\[(\\d+)\\]$/\n      , mArr = re.exec(value)\n    if (mArr) return { i: parseFloat(mArr[1]) };\n    else return { p: value };\n  });\n};\n\n/*!\n * ## _getPathValue(parsed, obj)\n *\n * Helper companion function for `.parsePath` that returns\n * the value located at the parsed address.\n *\n *      var value = getPathValue(parsed, obj);\n *\n * @param {Object} parsed definition from `parsePath`.\n * @param {Object} object to search against\n * @returns {Object|Undefined} value\n * @api private\n */\n\nfunction _getPathValue (parsed, obj) {\n  var tmp = obj\n    , res;\n  for (var i = 0, l = parsed.length; i < l; i++) {\n    var part = parsed[i];\n    if (tmp) {\n      if ('undefined' !== typeof part.p)\n        tmp = tmp[part.p];\n      else if ('undefined' !== typeof part.i)\n        tmp = tmp[part.i];\n      if (i == (l - 1)) res = tmp;\n    } else {\n      res = undefined;\n    }\n  }\n  return res;\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/getProperties.js\", function(exports, require, module){\n/*!\n * Chai - getProperties utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .getProperties(object)\n *\n * This allows the retrieval of property names of an object, enumerable or not,\n * inherited or not.\n *\n * @param {Object} object\n * @returns {Array}\n * @name getProperties\n * @api public\n */\n\nmodule.exports = function getProperties(object) {\n  var result = Object.getOwnPropertyNames(subject);\n\n  function addProperty(property) {\n    if (result.indexOf(property) === -1) {\n      result.push(property);\n    }\n  }\n\n  var proto = Object.getPrototypeOf(subject);\n  while (proto !== null) {\n    Object.getOwnPropertyNames(proto).forEach(addProperty);\n    proto = Object.getPrototypeOf(proto);\n  }\n\n  return result;\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/index.js\", function(exports, require, module){\n/*!\n * chai\n * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Main exports\n */\n\nvar exports = module.exports = {};\n\n/*!\n * test utility\n */\n\nexports.test = require('./test');\n\n/*!\n * type utility\n */\n\nexports.type = require('./type');\n\n/*!\n * message utility\n */\n\nexports.getMessage = require('./getMessage');\n\n/*!\n * actual utility\n */\n\nexports.getActual = require('./getActual');\n\n/*!\n * Inspect util\n */\n\nexports.inspect = require('./inspect');\n\n/*!\n * Object Display util\n */\n\nexports.objDisplay = require('./objDisplay');\n\n/*!\n * Flag utility\n */\n\nexports.flag = require('./flag');\n\n/*!\n * Flag transferring utility\n */\n\nexports.transferFlags = require('./transferFlags');\n\n/*!\n * Deep equal utility\n */\n\nexports.eql = require('deep-eql');\n\n/*!\n * Deep path value\n */\n\nexports.getPathValue = require('./getPathValue');\n\n/*!\n * Function name\n */\n\nexports.getName = require('./getName');\n\n/*!\n * add Property\n */\n\nexports.addProperty = require('./addProperty');\n\n/*!\n * add Method\n */\n\nexports.addMethod = require('./addMethod');\n\n/*!\n * overwrite Property\n */\n\nexports.overwriteProperty = require('./overwriteProperty');\n\n/*!\n * overwrite Method\n */\n\nexports.overwriteMethod = require('./overwriteMethod');\n\n/*!\n * Add a chainable method\n */\n\nexports.addChainableMethod = require('./addChainableMethod');\n\n/*!\n * Overwrite chainable method\n */\n\nexports.overwriteChainableMethod = require('./overwriteChainableMethod');\n\n\n});\nrequire.register(\"chai/lib/chai/utils/inspect.js\", function(exports, require, module){\n// This is (almost) directly from Node.js utils\n// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js\n\nvar getName = require('./getName');\nvar getProperties = require('./getProperties');\nvar getEnumerableProperties = require('./getEnumerableProperties');\n\nmodule.exports = inspect;\n\n/**\n * Echos the value of a value. Trys to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Boolean} showHidden Flag that shows hidden (not enumerable)\n *    properties of objects.\n * @param {Number} depth Depth in which to descend in object. Default is 2.\n * @param {Boolean} colors Flag to turn on ANSI escape codes to color the\n *    output. Default is false (no coloring).\n */\nfunction inspect(obj, showHidden, depth, colors) {\n  var ctx = {\n    showHidden: showHidden,\n    seen: [],\n    stylize: function (str) { return str; }\n  };\n  return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));\n}\n\n// https://gist.github.com/1044128/\nvar getOuterHTML = function(element) {\n  if ('outerHTML' in element) return element.outerHTML;\n  var ns = \"http://www.w3.org/1999/xhtml\";\n  var container = document.createElementNS(ns, '_');\n  var elemProto = (window.HTMLElement || window.Element).prototype;\n  var xmlSerializer = new XMLSerializer();\n  var html;\n  if (document.xmlVersion) {\n    return xmlSerializer.serializeToString(element);\n  } else {\n    container.appendChild(element.cloneNode(false));\n    html = container.innerHTML.replace('><', '>' + element.innerHTML + '<');\n    container.innerHTML = '';\n    return html;\n  }\n};\n\n// Returns true if object is a DOM element.\nvar isDOMElement = function (object) {\n  if (typeof HTMLElement === 'object') {\n    return object instanceof HTMLElement;\n  } else {\n    return object &&\n      typeof object === 'object' &&\n      object.nodeType === 1 &&\n      typeof object.nodeName === 'string';\n  }\n};\n\nfunction formatValue(ctx, value, recurseTimes) {\n  // Provide a hook for user-specified inspect functions.\n  // Check that value is an object with an inspect function on it\n  if (value && typeof value.inspect === 'function' &&\n      // Filter out the util module, it's inspect function is special\n      value.inspect !== exports.inspect &&\n      // Also filter out any prototype objects using the circular check.\n      !(value.constructor && value.constructor.prototype === value)) {\n    var ret = value.inspect(recurseTimes);\n    if (typeof ret !== 'string') {\n      ret = formatValue(ctx, ret, recurseTimes);\n    }\n    return ret;\n  }\n\n  // Primitive types cannot have properties\n  var primitive = formatPrimitive(ctx, value);\n  if (primitive) {\n    return primitive;\n  }\n\n  // If it's DOM elem, get outer HTML.\n  if (isDOMElement(value)) {\n    return getOuterHTML(value);\n  }\n\n  // Look up the keys of the object.\n  var visibleKeys = getEnumerableProperties(value);\n  var keys = ctx.showHidden ? getProperties(value) : visibleKeys;\n\n  // Some type of object without properties can be shortcutted.\n  // In IE, errors have a single `stack` property, or if they are vanilla `Error`,\n  // a `stack` plus `description` property; ignore those for consistency.\n  if (keys.length === 0 || (isError(value) && (\n      (keys.length === 1 && keys[0] === 'stack') ||\n      (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')\n     ))) {\n    if (typeof value === 'function') {\n      var name = getName(value);\n      var nameSuffix = name ? ': ' + name : '';\n      return ctx.stylize('[Function' + nameSuffix + ']', 'special');\n    }\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    }\n    if (isDate(value)) {\n      return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');\n    }\n    if (isError(value)) {\n      return formatError(value);\n    }\n  }\n\n  var base = '', array = false, braces = ['{', '}'];\n\n  // Make Array say that they are Array\n  if (isArray(value)) {\n    array = true;\n    braces = ['[', ']'];\n  }\n\n  // Make functions say that they are functions\n  if (typeof value === 'function') {\n    var name = getName(value);\n    var nameSuffix = name ? ': ' + name : '';\n    base = ' [Function' + nameSuffix + ']';\n  }\n\n  // Make RegExps say that they are RegExps\n  if (isRegExp(value)) {\n    base = ' ' + RegExp.prototype.toString.call(value);\n  }\n\n  // Make dates with properties first say the date\n  if (isDate(value)) {\n    base = ' ' + Date.prototype.toUTCString.call(value);\n  }\n\n  // Make error with message first say the error\n  if (isError(value)) {\n    return formatError(value);\n  }\n\n  if (keys.length === 0 && (!array || value.length == 0)) {\n    return braces[0] + base + braces[1];\n  }\n\n  if (recurseTimes < 0) {\n    if (isRegExp(value)) {\n      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');\n    } else {\n      return ctx.stylize('[Object]', 'special');\n    }\n  }\n\n  ctx.seen.push(value);\n\n  var output;\n  if (array) {\n    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);\n  } else {\n    output = keys.map(function(key) {\n      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);\n    });\n  }\n\n  ctx.seen.pop();\n\n  return reduceToSingleString(output, base, braces);\n}\n\n\nfunction formatPrimitive(ctx, value) {\n  switch (typeof value) {\n    case 'undefined':\n      return ctx.stylize('undefined', 'undefined');\n\n    case 'string':\n      var simple = '\\'' + JSON.stringify(value).replace(/^\"|\"$/g, '')\n                                               .replace(/'/g, \"\\\\'\")\n                                               .replace(/\\\\\"/g, '\"') + '\\'';\n      return ctx.stylize(simple, 'string');\n\n    case 'number':\n      return ctx.stylize('' + value, 'number');\n\n    case 'boolean':\n      return ctx.stylize('' + value, 'boolean');\n  }\n  // For some reason typeof null is \"object\", so special case here.\n  if (value === null) {\n    return ctx.stylize('null', 'null');\n  }\n}\n\n\nfunction formatError(value) {\n  return '[' + Error.prototype.toString.call(value) + ']';\n}\n\n\nfunction formatArray(ctx, value, recurseTimes, visibleKeys, keys) {\n  var output = [];\n  for (var i = 0, l = value.length; i < l; ++i) {\n    if (Object.prototype.hasOwnProperty.call(value, String(i))) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          String(i), true));\n    } else {\n      output.push('');\n    }\n  }\n  keys.forEach(function(key) {\n    if (!key.match(/^\\d+$/)) {\n      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,\n          key, true));\n    }\n  });\n  return output;\n}\n\n\nfunction formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {\n  var name, str;\n  if (value.__lookupGetter__) {\n    if (value.__lookupGetter__(key)) {\n      if (value.__lookupSetter__(key)) {\n        str = ctx.stylize('[Getter/Setter]', 'special');\n      } else {\n        str = ctx.stylize('[Getter]', 'special');\n      }\n    } else {\n      if (value.__lookupSetter__(key)) {\n        str = ctx.stylize('[Setter]', 'special');\n      }\n    }\n  }\n  if (visibleKeys.indexOf(key) < 0) {\n    name = '[' + key + ']';\n  }\n  if (!str) {\n    if (ctx.seen.indexOf(value[key]) < 0) {\n      if (recurseTimes === null) {\n        str = formatValue(ctx, value[key], null);\n      } else {\n        str = formatValue(ctx, value[key], recurseTimes - 1);\n      }\n      if (str.indexOf('\\n') > -1) {\n        if (array) {\n          str = str.split('\\n').map(function(line) {\n            return '  ' + line;\n          }).join('\\n').substr(2);\n        } else {\n          str = '\\n' + str.split('\\n').map(function(line) {\n            return '   ' + line;\n          }).join('\\n');\n        }\n      }\n    } else {\n      str = ctx.stylize('[Circular]', 'special');\n    }\n  }\n  if (typeof name === 'undefined') {\n    if (array && key.match(/^\\d+$/)) {\n      return str;\n    }\n    name = JSON.stringify('' + key);\n    if (name.match(/^\"([a-zA-Z_][a-zA-Z_0-9]*)\"$/)) {\n      name = name.substr(1, name.length - 2);\n      name = ctx.stylize(name, 'name');\n    } else {\n      name = name.replace(/'/g, \"\\\\'\")\n                 .replace(/\\\\\"/g, '\"')\n                 .replace(/(^\"|\"$)/g, \"'\");\n      name = ctx.stylize(name, 'string');\n    }\n  }\n\n  return name + ': ' + str;\n}\n\n\nfunction reduceToSingleString(output, base, braces) {\n  var numLinesEst = 0;\n  var length = output.reduce(function(prev, cur) {\n    numLinesEst++;\n    if (cur.indexOf('\\n') >= 0) numLinesEst++;\n    return prev + cur.length + 1;\n  }, 0);\n\n  if (length > 60) {\n    return braces[0] +\n           (base === '' ? '' : base + '\\n ') +\n           ' ' +\n           output.join(',\\n  ') +\n           ' ' +\n           braces[1];\n  }\n\n  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];\n}\n\nfunction isArray(ar) {\n  return Array.isArray(ar) ||\n         (typeof ar === 'object' && objectToString(ar) === '[object Array]');\n}\n\nfunction isRegExp(re) {\n  return typeof re === 'object' && objectToString(re) === '[object RegExp]';\n}\n\nfunction isDate(d) {\n  return typeof d === 'object' && objectToString(d) === '[object Date]';\n}\n\nfunction isError(e) {\n  return typeof e === 'object' && objectToString(e) === '[object Error]';\n}\n\nfunction objectToString(o) {\n  return Object.prototype.toString.call(o);\n}\n\n});\nrequire.register(\"chai/lib/chai/utils/objDisplay.js\", function(exports, require, module){\n/*!\n * Chai - flag utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependancies\n */\n\nvar inspect = require('./inspect');\n\n/**\n * ### .objDisplay (object)\n *\n * Determines if an object or an array matches\n * criteria to be inspected in-line for error\n * messages or should be truncated.\n *\n * @param {Mixed} javascript object to inspect\n * @name objDisplay\n * @api public\n */\n\nmodule.exports = function (obj) {\n  var str = inspect(obj)\n    , type = Object.prototype.toString.call(obj);\n\n  if (str.length >= 40) {\n    if (type === '[object Function]') {\n      return !obj.name || obj.name === ''\n        ? '[Function]'\n        : '[Function: ' + obj.name + ']';\n    } else if (type === '[object Array]') {\n      return '[ Array(' + obj.length + ') ]';\n    } else if (type === '[object Object]') {\n      var keys = Object.keys(obj)\n        , kstr = keys.length > 2\n          ? keys.splice(0, 2).join(', ') + ', ...'\n          : keys.join(', ');\n      return '{ Object (' + kstr + ') }';\n    } else {\n      return str;\n    }\n  } else {\n    return str;\n  }\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/overwriteMethod.js\", function(exports, require, module){\n/*!\n * Chai - overwriteMethod utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### overwriteMethod (ctx, name, fn)\n *\n * Overwites an already existing method and provides\n * access to previous function. Must return function\n * to be used for name.\n *\n *     utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {\n *       return function (str) {\n *         var obj = utils.flag(this, 'object');\n *         if (obj instanceof Foo) {\n *           new chai.Assertion(obj.value).to.equal(str);\n *         } else {\n *           _super.apply(this, arguments);\n *         }\n *       }\n *     });\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.overwriteMethod('foo', fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(myFoo).to.equal('bar');\n *\n * @param {Object} ctx object whose method is to be overwritten\n * @param {String} name of method to overwrite\n * @param {Function} method function that returns a function to be used for name\n * @name overwriteMethod\n * @api public\n */\n\nmodule.exports = function (ctx, name, method) {\n  var _method = ctx[name]\n    , _super = function () { return this; };\n\n  if (_method && 'function' === typeof _method)\n    _super = _method;\n\n  ctx[name] = function () {\n    var result = method(_super).apply(this, arguments);\n    return result === undefined ? this : result;\n  }\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/overwriteProperty.js\", function(exports, require, module){\n/*!\n * Chai - overwriteProperty utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### overwriteProperty (ctx, name, fn)\n *\n * Overwites an already existing property getter and provides\n * access to previous value. Must return function to use as getter.\n *\n *     utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {\n *       return function () {\n *         var obj = utils.flag(this, 'object');\n *         if (obj instanceof Foo) {\n *           new chai.Assertion(obj.name).to.equal('bar');\n *         } else {\n *           _super.call(this);\n *         }\n *       }\n *     });\n *\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.overwriteProperty('foo', fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(myFoo).to.be.ok;\n *\n * @param {Object} ctx object whose property is to be overwritten\n * @param {String} name of property to overwrite\n * @param {Function} getter function that returns a getter function to be used for name\n * @name overwriteProperty\n * @api public\n */\n\nmodule.exports = function (ctx, name, getter) {\n  var _get = Object.getOwnPropertyDescriptor(ctx, name)\n    , _super = function () {};\n\n  if (_get && 'function' === typeof _get.get)\n    _super = _get.get\n\n  Object.defineProperty(ctx, name,\n    { get: function () {\n        var result = getter(_super).call(this);\n        return result === undefined ? this : result;\n      }\n    , configurable: true\n  });\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/overwriteChainableMethod.js\", function(exports, require, module){\n/*!\n * Chai - overwriteChainableMethod utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### overwriteChainableMethod (ctx, name, fn)\n *\n * Overwites an already existing chainable method\n * and provides access to the previous function or\n * property.  Must return functions to be used for\n * name.\n *\n *     utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',\n *       function (_super) {\n *       }\n *     , function (_super) {\n *       }\n *     );\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.overwriteChainableMethod('foo', fn, fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(myFoo).to.have.length(3);\n *     expect(myFoo).to.have.length.above(3);\n *\n * @param {Object} ctx object whose method / property is to be overwritten\n * @param {String} name of method / property to overwrite\n * @param {Function} method function that returns a function to be used for name\n * @param {Function} chainingBehavior function that returns a function to be used for property\n * @name overwriteChainableMethod\n * @api public\n */\n\nmodule.exports = function (ctx, name, method, chainingBehavior) {\n  var chainableBehavior = ctx.__methods[name];\n\n  var _chainingBehavior = chainableBehavior.chainingBehavior;\n  chainableBehavior.chainingBehavior = function () {\n    var result = chainingBehavior(_chainingBehavior).call(this);\n    return result === undefined ? this : result;\n  };\n\n  var _method = chainableBehavior.method;\n  chainableBehavior.method = function () {\n    var result = method(_method).apply(this, arguments);\n    return result === undefined ? this : result;\n  };\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/test.js\", function(exports, require, module){\n/*!\n * Chai - test utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependancies\n */\n\nvar flag = require('./flag');\n\n/**\n * # test(object, expression)\n *\n * Test and object for expression.\n *\n * @param {Object} object (constructed Assertion)\n * @param {Arguments} chai.Assertion.prototype.assert arguments\n */\n\nmodule.exports = function (obj, args) {\n  var negate = flag(obj, 'negate')\n    , expr = args[0];\n  return negate ? !expr : expr;\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/transferFlags.js\", function(exports, require, module){\n/*!\n * Chai - transferFlags utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### transferFlags(assertion, object, includeAll = true)\n *\n * Transfer all the flags for `assertion` to `object`. If\n * `includeAll` is set to `false`, then the base Chai\n * assertion flags (namely `object`, `ssfi`, and `message`)\n * will not be transferred.\n *\n *\n *     var newAssertion = new Assertion();\n *     utils.transferFlags(assertion, newAssertion);\n *\n *     var anotherAsseriton = new Assertion(myObj);\n *     utils.transferFlags(assertion, anotherAssertion, false);\n *\n * @param {Assertion} assertion the assertion to transfer the flags from\n * @param {Object} object the object to transfer the flags too; usually a new assertion\n * @param {Boolean} includeAll\n * @name getAllFlags\n * @api private\n */\n\nmodule.exports = function (assertion, object, includeAll) {\n  var flags = assertion.__flags || (assertion.__flags = Object.create(null));\n\n  if (!object.__flags) {\n    object.__flags = Object.create(null);\n  }\n\n  includeAll = arguments.length === 3 ? includeAll : true;\n\n  for (var flag in flags) {\n    if (includeAll ||\n        (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {\n      object.__flags[flag] = flags[flag];\n    }\n  }\n};\n\n});\nrequire.register(\"chai/lib/chai/utils/type.js\", function(exports, require, module){\n/*!\n * Chai - type utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Detectable javascript natives\n */\n\nvar natives = {\n    '[object Arguments]': 'arguments'\n  , '[object Array]': 'array'\n  , '[object Date]': 'date'\n  , '[object Function]': 'function'\n  , '[object Number]': 'number'\n  , '[object RegExp]': 'regexp'\n  , '[object String]': 'string'\n};\n\n/**\n * ### type(object)\n *\n * Better implementation of `typeof` detection that can\n * be used cross-browser. Handles the inconsistencies of\n * Array, `null`, and `undefined` detection.\n *\n *     utils.type({}) // 'object'\n *     utils.type(null) // `null'\n *     utils.type(undefined) // `undefined`\n *     utils.type([]) // `array`\n *\n * @param {Mixed} object to detect type of\n * @name type\n * @api private\n */\n\nmodule.exports = function (obj) {\n  var str = Object.prototype.toString.call(obj);\n  if (natives[str]) return natives[str];\n  if (obj === null) return 'null';\n  if (obj === undefined) return 'undefined';\n  if (obj === Object(obj)) return 'object';\n  return typeof obj;\n};\n\n});\n\n\n\n\nrequire.alias(\"chaijs-assertion-error/index.js\", \"chai/deps/assertion-error/index.js\");\nrequire.alias(\"chaijs-assertion-error/index.js\", \"chai/deps/assertion-error/index.js\");\nrequire.alias(\"chaijs-assertion-error/index.js\", \"assertion-error/index.js\");\nrequire.alias(\"chaijs-assertion-error/index.js\", \"chaijs-assertion-error/index.js\");\nrequire.alias(\"chaijs-deep-eql/lib/eql.js\", \"chai/deps/deep-eql/lib/eql.js\");\nrequire.alias(\"chaijs-deep-eql/lib/eql.js\", \"chai/deps/deep-eql/index.js\");\nrequire.alias(\"chaijs-deep-eql/lib/eql.js\", \"deep-eql/index.js\");\nrequire.alias(\"chaijs-type-detect/lib/type.js\", \"chaijs-deep-eql/deps/type-detect/lib/type.js\");\nrequire.alias(\"chaijs-type-detect/lib/type.js\", \"chaijs-deep-eql/deps/type-detect/index.js\");\nrequire.alias(\"chaijs-type-detect/lib/type.js\", \"chaijs-type-detect/index.js\");\nrequire.alias(\"chaijs-deep-eql/lib/eql.js\", \"chaijs-deep-eql/index.js\");\nrequire.alias(\"chai/index.js\", \"chai/index.js\");if (typeof exports == \"object\") {\n  module.exports = require(\"chai\");\n} else if (typeof define == \"function\" && define.amd) {\n  define([], function(){ return require(\"chai\"); });\n} else {\n  this[\"chai\"] = require(\"chai\");\n}})();"
  },
  {
    "path": "tests/js/loadrules.js",
    "content": "ScanJS.loadRulesFile(\"../common/rules.json\");\n"
  },
  {
    "path": "tests/js/main.js",
    "content": "mocha.setup('bdd');\n$(document).ready(function() { mocha.run(); });"
  },
  {
    "path": "tests/js/mocha.js",
    "content": ";(function(){\n\n// CommonJS require()\n\nfunction require(p){\n    var path = require.resolve(p)\n      , mod = require.modules[path];\n    if (!mod) throw new Error('failed to require \"' + p + '\"');\n    if (!mod.exports) {\n      mod.exports = {};\n      mod.call(mod.exports, mod, mod.exports, require.relative(path));\n    }\n    return mod.exports;\n  }\n\nrequire.modules = {};\n\nrequire.resolve = function (path){\n    var orig = path\n      , reg = path + '.js'\n      , index = path + '/index.js';\n    return require.modules[reg] && reg\n      || require.modules[index] && index\n      || orig;\n  };\n\nrequire.register = function (path, fn){\n    require.modules[path] = fn;\n  };\n\nrequire.relative = function (parent) {\n    return function(p){\n      if ('.' != p.charAt(0)) return require(p);\n\n      var path = parent.split('/')\n        , segs = p.split('/');\n      path.pop();\n\n      for (var i = 0; i < segs.length; i++) {\n        var seg = segs[i];\n        if ('..' == seg) path.pop();\n        else if ('.' != seg) path.push(seg);\n      }\n\n      return require(path.join('/'));\n    };\n  };\n\n\nrequire.register(\"browser/debug.js\", function(module, exports, require){\n\nmodule.exports = function(type){\n  return function(){\n  }\n};\n\n}); // module: browser/debug.js\n\nrequire.register(\"browser/diff.js\", function(module, exports, require){\n/* See LICENSE file for terms of use */\n\n/*\n * Text diff implementation.\n *\n * This library supports the following APIS:\n * JsDiff.diffChars: Character by character diff\n * JsDiff.diffWords: Word (as defined by \\b regex) diff which ignores whitespace\n * JsDiff.diffLines: Line based diff\n *\n * JsDiff.diffCss: Diff targeted at CSS content\n *\n * These methods are based on the implementation proposed in\n * \"An O(ND) Difference Algorithm and its Variations\" (Myers, 1986).\n * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927\n */\nvar JsDiff = (function() {\n  /*jshint maxparams: 5*/\n  function clonePath(path) {\n    return { newPos: path.newPos, components: path.components.slice(0) };\n  }\n  function removeEmpty(array) {\n    var ret = [];\n    for (var i = 0; i < array.length; i++) {\n      if (array[i]) {\n        ret.push(array[i]);\n      }\n    }\n    return ret;\n  }\n  function escapeHTML(s) {\n    var n = s;\n    n = n.replace(/&/g, '&amp;');\n    n = n.replace(/</g, '&lt;');\n    n = n.replace(/>/g, '&gt;');\n    n = n.replace(/\"/g, '&quot;');\n\n    return n;\n  }\n\n  var Diff = function(ignoreWhitespace) {\n    this.ignoreWhitespace = ignoreWhitespace;\n  };\n  Diff.prototype = {\n      diff: function(oldString, newString) {\n        // Handle the identity case (this is due to unrolling editLength == 0\n        if (newString === oldString) {\n          return [{ value: newString }];\n        }\n        if (!newString) {\n          return [{ value: oldString, removed: true }];\n        }\n        if (!oldString) {\n          return [{ value: newString, added: true }];\n        }\n\n        newString = this.tokenize(newString);\n        oldString = this.tokenize(oldString);\n\n        var newLen = newString.length, oldLen = oldString.length;\n        var maxEditLength = newLen + oldLen;\n        var bestPath = [{ newPos: -1, components: [] }];\n\n        // Seed editLength = 0\n        var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);\n        if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {\n          return bestPath[0].components;\n        }\n\n        for (var editLength = 1; editLength <= maxEditLength; editLength++) {\n          for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {\n            var basePath;\n            var addPath = bestPath[diagonalPath-1],\n                removePath = bestPath[diagonalPath+1];\n            oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;\n            if (addPath) {\n              // No one else is going to attempt to use this value, clear it\n              bestPath[diagonalPath-1] = undefined;\n            }\n\n            var canAdd = addPath && addPath.newPos+1 < newLen;\n            var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;\n            if (!canAdd && !canRemove) {\n              bestPath[diagonalPath] = undefined;\n              continue;\n            }\n\n            // Select the diagonal that we want to branch from. We select the prior\n            // path whose position in the new string is the farthest from the origin\n            // and does not pass the bounds of the diff graph\n            if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {\n              basePath = clonePath(removePath);\n              this.pushComponent(basePath.components, oldString[oldPos], undefined, true);\n            } else {\n              basePath = clonePath(addPath);\n              basePath.newPos++;\n              this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);\n            }\n\n            var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);\n\n            if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {\n              return basePath.components;\n            } else {\n              bestPath[diagonalPath] = basePath;\n            }\n          }\n        }\n      },\n\n      pushComponent: function(components, value, added, removed) {\n        var last = components[components.length-1];\n        if (last && last.added === added && last.removed === removed) {\n          // We need to clone here as the component clone operation is just\n          // as shallow array clone\n          components[components.length-1] =\n            {value: this.join(last.value, value), added: added, removed: removed };\n        } else {\n          components.push({value: value, added: added, removed: removed });\n        }\n      },\n      extractCommon: function(basePath, newString, oldString, diagonalPath) {\n        var newLen = newString.length,\n            oldLen = oldString.length,\n            newPos = basePath.newPos,\n            oldPos = newPos - diagonalPath;\n        while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {\n          newPos++;\n          oldPos++;\n\n          this.pushComponent(basePath.components, newString[newPos], undefined, undefined);\n        }\n        basePath.newPos = newPos;\n        return oldPos;\n      },\n\n      equals: function(left, right) {\n        var reWhitespace = /\\S/;\n        if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {\n          return true;\n        } else {\n          return left === right;\n        }\n      },\n      join: function(left, right) {\n        return left + right;\n      },\n      tokenize: function(value) {\n        return value;\n      }\n  };\n\n  var CharDiff = new Diff();\n\n  var WordDiff = new Diff(true);\n  var WordWithSpaceDiff = new Diff();\n  WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {\n    return removeEmpty(value.split(/(\\s+|\\b)/));\n  };\n\n  var CssDiff = new Diff(true);\n  CssDiff.tokenize = function(value) {\n    return removeEmpty(value.split(/([{}:;,]|\\s+)/));\n  };\n\n  var LineDiff = new Diff();\n  LineDiff.tokenize = function(value) {\n    return value.split(/^/m);\n  };\n\n  return {\n    Diff: Diff,\n\n    diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },\n    diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },\n    diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },\n    diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },\n\n    diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },\n\n    createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {\n      var ret = [];\n\n      ret.push('Index: ' + fileName);\n      ret.push('===================================================================');\n      ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\\t' + oldHeader));\n      ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\\t' + newHeader));\n\n      var diff = LineDiff.diff(oldStr, newStr);\n      if (!diff[diff.length-1].value) {\n        diff.pop();   // Remove trailing newline add\n      }\n      diff.push({value: '', lines: []});   // Append an empty value to make cleanup easier\n\n      function contextLines(lines) {\n        return lines.map(function(entry) { return ' ' + entry; });\n      }\n      function eofNL(curRange, i, current) {\n        var last = diff[diff.length-2],\n            isLast = i === diff.length-2,\n            isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);\n\n        // Figure out if this is the last line for the given file and missing NL\n        if (!/\\n$/.test(current.value) && (isLast || isLastOfType)) {\n          curRange.push('\\\\ No newline at end of file');\n        }\n      }\n\n      var oldRangeStart = 0, newRangeStart = 0, curRange = [],\n          oldLine = 1, newLine = 1;\n      for (var i = 0; i < diff.length; i++) {\n        var current = diff[i],\n            lines = current.lines || current.value.replace(/\\n$/, '').split('\\n');\n        current.lines = lines;\n\n        if (current.added || current.removed) {\n          if (!oldRangeStart) {\n            var prev = diff[i-1];\n            oldRangeStart = oldLine;\n            newRangeStart = newLine;\n\n            if (prev) {\n              curRange = contextLines(prev.lines.slice(-4));\n              oldRangeStart -= curRange.length;\n              newRangeStart -= curRange.length;\n            }\n          }\n          curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));\n          eofNL(curRange, i, current);\n\n          if (current.added) {\n            newLine += lines.length;\n          } else {\n            oldLine += lines.length;\n          }\n        } else {\n          if (oldRangeStart) {\n            // Close out any changes that have been output (or join overlapping)\n            if (lines.length <= 8 && i < diff.length-2) {\n              // Overlapping\n              curRange.push.apply(curRange, contextLines(lines));\n            } else {\n              // end the range and output\n              var contextSize = Math.min(lines.length, 4);\n              ret.push(\n                  '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)\n                  + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)\n                  + ' @@');\n              ret.push.apply(ret, curRange);\n              ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));\n              if (lines.length <= 4) {\n                eofNL(ret, i, current);\n              }\n\n              oldRangeStart = 0;  newRangeStart = 0; curRange = [];\n            }\n          }\n          oldLine += lines.length;\n          newLine += lines.length;\n        }\n      }\n\n      return ret.join('\\n') + '\\n';\n    },\n\n    applyPatch: function(oldStr, uniDiff) {\n      var diffstr = uniDiff.split('\\n');\n      var diff = [];\n      var remEOFNL = false,\n          addEOFNL = false;\n\n      for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {\n        if(diffstr[i][0] === '@') {\n          var meh = diffstr[i].split(/@@ -(\\d+),(\\d+) \\+(\\d+),(\\d+) @@/);\n          diff.unshift({\n            start:meh[3],\n            oldlength:meh[2],\n            oldlines:[],\n            newlength:meh[4],\n            newlines:[]\n          });\n        } else if(diffstr[i][0] === '+') {\n          diff[0].newlines.push(diffstr[i].substr(1));\n        } else if(diffstr[i][0] === '-') {\n          diff[0].oldlines.push(diffstr[i].substr(1));\n        } else if(diffstr[i][0] === ' ') {\n          diff[0].newlines.push(diffstr[i].substr(1));\n          diff[0].oldlines.push(diffstr[i].substr(1));\n        } else if(diffstr[i][0] === '\\\\') {\n          if (diffstr[i-1][0] === '+') {\n            remEOFNL = true;\n          } else if(diffstr[i-1][0] === '-') {\n            addEOFNL = true;\n          }\n        }\n      }\n\n      var str = oldStr.split('\\n');\n      for (var i = diff.length - 1; i >= 0; i--) {\n        var d = diff[i];\n        for (var j = 0; j < d.oldlength; j++) {\n          if(str[d.start-1+j] !== d.oldlines[j]) {\n            return false;\n          }\n        }\n        Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));\n      }\n\n      if (remEOFNL) {\n        while (!str[str.length-1]) {\n          str.pop();\n        }\n      } else if (addEOFNL) {\n        str.push('');\n      }\n      return str.join('\\n');\n    },\n\n    convertChangesToXML: function(changes){\n      var ret = [];\n      for ( var i = 0; i < changes.length; i++) {\n        var change = changes[i];\n        if (change.added) {\n          ret.push('<ins>');\n        } else if (change.removed) {\n          ret.push('<del>');\n        }\n\n        ret.push(escapeHTML(change.value));\n\n        if (change.added) {\n          ret.push('</ins>');\n        } else if (change.removed) {\n          ret.push('</del>');\n        }\n      }\n      return ret.join('');\n    },\n\n    // See: http://code.google.com/p/google-diff-match-patch/wiki/API\n    convertChangesToDMP: function(changes){\n      var ret = [], change;\n      for ( var i = 0; i < changes.length; i++) {\n        change = changes[i];\n        ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);\n      }\n      return ret;\n    }\n  };\n})();\n\nif (typeof module !== 'undefined') {\n    module.exports = JsDiff;\n}\n\n}); // module: browser/diff.js\n\nrequire.register(\"browser/events.js\", function(module, exports, require){\n\n/**\n * Module exports.\n */\n\nexports.EventEmitter = EventEmitter;\n\n/**\n * Check if `obj` is an array.\n */\n\nfunction isArray(obj) {\n  return '[object Array]' == {}.toString.call(obj);\n}\n\n/**\n * Event emitter constructor.\n *\n * @api public\n */\n\nfunction EventEmitter(){};\n\n/**\n * Adds a listener.\n *\n * @api public\n */\n\nEventEmitter.prototype.on = function (name, fn) {\n  if (!this.$events) {\n    this.$events = {};\n  }\n\n  if (!this.$events[name]) {\n    this.$events[name] = fn;\n  } else if (isArray(this.$events[name])) {\n    this.$events[name].push(fn);\n  } else {\n    this.$events[name] = [this.$events[name], fn];\n  }\n\n  return this;\n};\n\nEventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n/**\n * Adds a volatile listener.\n *\n * @api public\n */\n\nEventEmitter.prototype.once = function (name, fn) {\n  var self = this;\n\n  function on () {\n    self.removeListener(name, on);\n    fn.apply(this, arguments);\n  };\n\n  on.listener = fn;\n  this.on(name, on);\n\n  return this;\n};\n\n/**\n * Removes a listener.\n *\n * @api public\n */\n\nEventEmitter.prototype.removeListener = function (name, fn) {\n  if (this.$events && this.$events[name]) {\n    var list = this.$events[name];\n\n    if (isArray(list)) {\n      var pos = -1;\n\n      for (var i = 0, l = list.length; i < l; i++) {\n        if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {\n          pos = i;\n          break;\n        }\n      }\n\n      if (pos < 0) {\n        return this;\n      }\n\n      list.splice(pos, 1);\n\n      if (!list.length) {\n        delete this.$events[name];\n      }\n    } else if (list === fn || (list.listener && list.listener === fn)) {\n      delete this.$events[name];\n    }\n  }\n\n  return this;\n};\n\n/**\n * Removes all listeners for an event.\n *\n * @api public\n */\n\nEventEmitter.prototype.removeAllListeners = function (name) {\n  if (name === undefined) {\n    this.$events = {};\n    return this;\n  }\n\n  if (this.$events && this.$events[name]) {\n    this.$events[name] = null;\n  }\n\n  return this;\n};\n\n/**\n * Gets all listeners for a certain event.\n *\n * @api public\n */\n\nEventEmitter.prototype.listeners = function (name) {\n  if (!this.$events) {\n    this.$events = {};\n  }\n\n  if (!this.$events[name]) {\n    this.$events[name] = [];\n  }\n\n  if (!isArray(this.$events[name])) {\n    this.$events[name] = [this.$events[name]];\n  }\n\n  return this.$events[name];\n};\n\n/**\n * Emits an event.\n *\n * @api public\n */\n\nEventEmitter.prototype.emit = function (name) {\n  if (!this.$events) {\n    return false;\n  }\n\n  var handler = this.$events[name];\n\n  if (!handler) {\n    return false;\n  }\n\n  var args = [].slice.call(arguments, 1);\n\n  if ('function' == typeof handler) {\n    handler.apply(this, args);\n  } else if (isArray(handler)) {\n    var listeners = handler.slice();\n\n    for (var i = 0, l = listeners.length; i < l; i++) {\n      listeners[i].apply(this, args);\n    }\n  } else {\n    return false;\n  }\n\n  return true;\n};\n}); // module: browser/events.js\n\nrequire.register(\"browser/fs.js\", function(module, exports, require){\n\n}); // module: browser/fs.js\n\nrequire.register(\"browser/path.js\", function(module, exports, require){\n\n}); // module: browser/path.js\n\nrequire.register(\"browser/progress.js\", function(module, exports, require){\n/**\n * Expose `Progress`.\n */\n\nmodule.exports = Progress;\n\n/**\n * Initialize a new `Progress` indicator.\n */\n\nfunction Progress() {\n  this.percent = 0;\n  this.size(0);\n  this.fontSize(11);\n  this.font('helvetica, arial, sans-serif');\n}\n\n/**\n * Set progress size to `n`.\n *\n * @param {Number} n\n * @return {Progress} for chaining\n * @api public\n */\n\nProgress.prototype.size = function(n){\n  this._size = n;\n  return this;\n};\n\n/**\n * Set text to `str`.\n *\n * @param {String} str\n * @return {Progress} for chaining\n * @api public\n */\n\nProgress.prototype.text = function(str){\n  this._text = str;\n  return this;\n};\n\n/**\n * Set font size to `n`.\n *\n * @param {Number} n\n * @return {Progress} for chaining\n * @api public\n */\n\nProgress.prototype.fontSize = function(n){\n  this._fontSize = n;\n  return this;\n};\n\n/**\n * Set font `family`.\n *\n * @param {String} family\n * @return {Progress} for chaining\n */\n\nProgress.prototype.font = function(family){\n  this._font = family;\n  return this;\n};\n\n/**\n * Update percentage to `n`.\n *\n * @param {Number} n\n * @return {Progress} for chaining\n */\n\nProgress.prototype.update = function(n){\n  this.percent = n;\n  return this;\n};\n\n/**\n * Draw on `ctx`.\n *\n * @param {CanvasRenderingContext2d} ctx\n * @return {Progress} for chaining\n */\n\nProgress.prototype.draw = function(ctx){\n  try {\n    var percent = Math.min(this.percent, 100)\n      , size = this._size\n      , half = size / 2\n      , x = half\n      , y = half\n      , rad = half - 1\n      , fontSize = this._fontSize;\n  \n    ctx.font = fontSize + 'px ' + this._font;\n  \n    var angle = Math.PI * 2 * (percent / 100);\n    ctx.clearRect(0, 0, size, size);\n  \n    // outer circle\n    ctx.strokeStyle = '#9f9f9f';\n    ctx.beginPath();\n    ctx.arc(x, y, rad, 0, angle, false);\n    ctx.stroke();\n  \n    // inner circle\n    ctx.strokeStyle = '#eee';\n    ctx.beginPath();\n    ctx.arc(x, y, rad - 1, 0, angle, true);\n    ctx.stroke();\n  \n    // text\n    var text = this._text || (percent | 0) + '%'\n      , w = ctx.measureText(text).width;\n  \n    ctx.fillText(\n        text\n      , x - w / 2 + 1\n      , y + fontSize / 2 - 1);\n  } catch (ex) {} //don't fail if we can't render progress\n  return this;\n};\n\n}); // module: browser/progress.js\n\nrequire.register(\"browser/tty.js\", function(module, exports, require){\n\nexports.isatty = function(){\n  return true;\n};\n\nexports.getWindowSize = function(){\n  if ('innerHeight' in global) {\n    return [global.innerHeight, global.innerWidth];\n  } else {\n    // In a Web Worker, the DOM Window is not available.\n    return [640, 480];\n  }\n};\n\n}); // module: browser/tty.js\n\nrequire.register(\"context.js\", function(module, exports, require){\n\n/**\n * Expose `Context`.\n */\n\nmodule.exports = Context;\n\n/**\n * Initialize a new `Context`.\n *\n * @api private\n */\n\nfunction Context(){}\n\n/**\n * Set or get the context `Runnable` to `runnable`.\n *\n * @param {Runnable} runnable\n * @return {Context}\n * @api private\n */\n\nContext.prototype.runnable = function(runnable){\n  if (0 == arguments.length) return this._runnable;\n  this.test = this._runnable = runnable;\n  return this;\n};\n\n/**\n * Set test timeout `ms`.\n *\n * @param {Number} ms\n * @return {Context} self\n * @api private\n */\n\nContext.prototype.timeout = function(ms){\n  this.runnable().timeout(ms);\n  return this;\n};\n\n/**\n * Set test slowness threshold `ms`.\n *\n * @param {Number} ms\n * @return {Context} self\n * @api private\n */\n\nContext.prototype.slow = function(ms){\n  this.runnable().slow(ms);\n  return this;\n};\n\n/**\n * Inspect the context void of `._runnable`.\n *\n * @return {String}\n * @api private\n */\n\nContext.prototype.inspect = function(){\n  return JSON.stringify(this, function(key, val){\n    if ('_runnable' == key) return;\n    if ('test' == key) return;\n    return val;\n  }, 2);\n};\n\n}); // module: context.js\n\nrequire.register(\"hook.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Runnable = require('./runnable');\n\n/**\n * Expose `Hook`.\n */\n\nmodule.exports = Hook;\n\n/**\n * Initialize a new `Hook` with the given `title` and callback `fn`.\n *\n * @param {String} title\n * @param {Function} fn\n * @api private\n */\n\nfunction Hook(title, fn) {\n  Runnable.call(this, title, fn);\n  this.type = 'hook';\n}\n\n/**\n * Inherit from `Runnable.prototype`.\n */\n\nfunction F(){};\nF.prototype = Runnable.prototype;\nHook.prototype = new F;\nHook.prototype.constructor = Hook;\n\n\n/**\n * Get or set the test `err`.\n *\n * @param {Error} err\n * @return {Error}\n * @api public\n */\n\nHook.prototype.error = function(err){\n  if (0 == arguments.length) {\n    var err = this._error;\n    this._error = null;\n    return err;\n  }\n\n  this._error = err;\n};\n\n}); // module: hook.js\n\nrequire.register(\"interfaces/bdd.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Suite = require('../suite')\n  , Test = require('../test')\n  , utils = require('../utils');\n\n/**\n * BDD-style interface:\n *\n *      describe('Array', function(){\n *        describe('#indexOf()', function(){\n *          it('should return -1 when not present', function(){\n *\n *          });\n *\n *          it('should return the index when present', function(){\n *\n *          });\n *        });\n *      });\n *\n */\n\nmodule.exports = function(suite){\n  var suites = [suite];\n\n  suite.on('pre-require', function(context, file, mocha){\n\n    /**\n     * Execute before running tests.\n     */\n\n    context.before = function(fn){\n      suites[0].beforeAll(fn);\n    };\n\n    /**\n     * Execute after running tests.\n     */\n\n    context.after = function(fn){\n      suites[0].afterAll(fn);\n    };\n\n    /**\n     * Execute before each test case.\n     */\n\n    context.beforeEach = function(fn){\n      suites[0].beforeEach(fn);\n    };\n\n    /**\n     * Execute after each test case.\n     */\n\n    context.afterEach = function(fn){\n      suites[0].afterEach(fn);\n    };\n\n    /**\n     * Describe a \"suite\" with the given `title`\n     * and callback `fn` containing nested suites\n     * and/or tests.\n     */\n\n    context.describe = context.context = function(title, fn){\n      var suite = Suite.create(suites[0], title);\n      suites.unshift(suite);\n      fn.call(suite);\n      suites.shift();\n      return suite;\n    };\n\n    /**\n     * Pending describe.\n     */\n\n    context.xdescribe =\n    context.xcontext =\n    context.describe.skip = function(title, fn){\n      var suite = Suite.create(suites[0], title);\n      suite.pending = true;\n      suites.unshift(suite);\n      fn.call(suite);\n      suites.shift();\n    };\n\n    /**\n     * Exclusive suite.\n     */\n\n    context.describe.only = function(title, fn){\n      var suite = context.describe(title, fn);\n      mocha.grep(suite.fullTitle());\n      return suite;\n    };\n\n    /**\n     * Describe a specification or test-case\n     * with the given `title` and callback `fn`\n     * acting as a thunk.\n     */\n\n    context.it = context.specify = function(title, fn){\n      var suite = suites[0];\n      if (suite.pending) var fn = null;\n      var test = new Test(title, fn);\n      suite.addTest(test);\n      return test;\n    };\n\n    /**\n     * Exclusive test-case.\n     */\n\n    context.it.only = function(title, fn){\n      var test = context.it(title, fn);\n      var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';\n      mocha.grep(new RegExp(reString));\n      return test;\n    };\n\n    /**\n     * Pending test case.\n     */\n\n    context.xit =\n    context.xspecify =\n    context.it.skip = function(title){\n      context.it(title);\n    };\n  });\n};\n\n}); // module: interfaces/bdd.js\n\nrequire.register(\"interfaces/exports.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Suite = require('../suite')\n  , Test = require('../test');\n\n/**\n * TDD-style interface:\n *\n *     exports.Array = {\n *       '#indexOf()': {\n *         'should return -1 when the value is not present': function(){\n *\n *         },\n *\n *         'should return the correct index when the value is present': function(){\n *\n *         }\n *       }\n *     };\n *\n */\n\nmodule.exports = function(suite){\n  var suites = [suite];\n\n  suite.on('require', visit);\n\n  function visit(obj) {\n    var suite;\n    for (var key in obj) {\n      if ('function' == typeof obj[key]) {\n        var fn = obj[key];\n        switch (key) {\n          case 'before':\n            suites[0].beforeAll(fn);\n            break;\n          case 'after':\n            suites[0].afterAll(fn);\n            break;\n          case 'beforeEach':\n            suites[0].beforeEach(fn);\n            break;\n          case 'afterEach':\n            suites[0].afterEach(fn);\n            break;\n          default:\n            suites[0].addTest(new Test(key, fn));\n        }\n      } else {\n        var suite = Suite.create(suites[0], key);\n        suites.unshift(suite);\n        visit(obj[key]);\n        suites.shift();\n      }\n    }\n  }\n};\n\n}); // module: interfaces/exports.js\n\nrequire.register(\"interfaces/index.js\", function(module, exports, require){\n\nexports.bdd = require('./bdd');\nexports.tdd = require('./tdd');\nexports.qunit = require('./qunit');\nexports.exports = require('./exports');\n\n}); // module: interfaces/index.js\n\nrequire.register(\"interfaces/qunit.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Suite = require('../suite')\n  , Test = require('../test')\n  , utils = require('../utils');\n\n/**\n * QUnit-style interface:\n *\n *     suite('Array');\n *\n *     test('#length', function(){\n *       var arr = [1,2,3];\n *       ok(arr.length == 3);\n *     });\n *\n *     test('#indexOf()', function(){\n *       var arr = [1,2,3];\n *       ok(arr.indexOf(1) == 0);\n *       ok(arr.indexOf(2) == 1);\n *       ok(arr.indexOf(3) == 2);\n *     });\n *\n *     suite('String');\n *\n *     test('#length', function(){\n *       ok('foo'.length == 3);\n *     });\n *\n */\n\nmodule.exports = function(suite){\n  var suites = [suite];\n\n  suite.on('pre-require', function(context, file, mocha){\n\n    /**\n     * Execute before running tests.\n     */\n\n    context.before = function(fn){\n      suites[0].beforeAll(fn);\n    };\n\n    /**\n     * Execute after running tests.\n     */\n\n    context.after = function(fn){\n      suites[0].afterAll(fn);\n    };\n\n    /**\n     * Execute before each test case.\n     */\n\n    context.beforeEach = function(fn){\n      suites[0].beforeEach(fn);\n    };\n\n    /**\n     * Execute after each test case.\n     */\n\n    context.afterEach = function(fn){\n      suites[0].afterEach(fn);\n    };\n\n    /**\n     * Describe a \"suite\" with the given `title`.\n     */\n\n    context.suite = function(title){\n      if (suites.length > 1) suites.shift();\n      var suite = Suite.create(suites[0], title);\n      suites.unshift(suite);\n      return suite;\n    };\n\n    /**\n     * Exclusive test-case.\n     */\n\n    context.suite.only = function(title, fn){\n      var suite = context.suite(title, fn);\n      mocha.grep(suite.fullTitle());\n    };\n\n    /**\n     * Describe a specification or test-case\n     * with the given `title` and callback `fn`\n     * acting as a thunk.\n     */\n\n    context.test = function(title, fn){\n      var test = new Test(title, fn);\n      suites[0].addTest(test);\n      return test;\n    };\n\n    /**\n     * Exclusive test-case.\n     */\n\n    context.test.only = function(title, fn){\n      var test = context.test(title, fn);\n      var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';\n      mocha.grep(new RegExp(reString));\n    };\n\n    /**\n     * Pending test case.\n     */\n\n    context.test.skip = function(title){\n      context.test(title);\n    };\n  });\n};\n\n}); // module: interfaces/qunit.js\n\nrequire.register(\"interfaces/tdd.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Suite = require('../suite')\n  , Test = require('../test')\n  , utils = require('../utils');;\n\n/**\n * TDD-style interface:\n *\n *      suite('Array', function(){\n *        suite('#indexOf()', function(){\n *          suiteSetup(function(){\n *\n *          });\n *\n *          test('should return -1 when not present', function(){\n *\n *          });\n *\n *          test('should return the index when present', function(){\n *\n *          });\n *\n *          suiteTeardown(function(){\n *\n *          });\n *        });\n *      });\n *\n */\n\nmodule.exports = function(suite){\n  var suites = [suite];\n\n  suite.on('pre-require', function(context, file, mocha){\n\n    /**\n     * Execute before each test case.\n     */\n\n    context.setup = function(fn){\n      suites[0].beforeEach(fn);\n    };\n\n    /**\n     * Execute after each test case.\n     */\n\n    context.teardown = function(fn){\n      suites[0].afterEach(fn);\n    };\n\n    /**\n     * Execute before the suite.\n     */\n\n    context.suiteSetup = function(fn){\n      suites[0].beforeAll(fn);\n    };\n\n    /**\n     * Execute after the suite.\n     */\n\n    context.suiteTeardown = function(fn){\n      suites[0].afterAll(fn);\n    };\n\n    /**\n     * Describe a \"suite\" with the given `title`\n     * and callback `fn` containing nested suites\n     * and/or tests.\n     */\n\n    context.suite = function(title, fn){\n      var suite = Suite.create(suites[0], title);\n      suites.unshift(suite);\n      fn.call(suite);\n      suites.shift();\n      return suite;\n    };\n\n    /**\n     * Pending suite.\n     */\n    context.suite.skip = function(title, fn) {\n      var suite = Suite.create(suites[0], title);\n      suite.pending = true;\n      suites.unshift(suite);\n      fn.call(suite);\n      suites.shift();\n    };\n\n    /**\n     * Exclusive test-case.\n     */\n\n    context.suite.only = function(title, fn){\n      var suite = context.suite(title, fn);\n      mocha.grep(suite.fullTitle());\n    };\n\n    /**\n     * Describe a specification or test-case\n     * with the given `title` and callback `fn`\n     * acting as a thunk.\n     */\n\n    context.test = function(title, fn){\n      var suite = suites[0];\n      if (suite.pending) var fn = null;\n      var test = new Test(title, fn);\n      suite.addTest(test);\n      return test;\n    };\n\n    /**\n     * Exclusive test-case.\n     */\n\n    context.test.only = function(title, fn){\n      var test = context.test(title, fn);\n      var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';\n      mocha.grep(new RegExp(reString));\n    };\n\n    /**\n     * Pending test case.\n     */\n\n    context.test.skip = function(title){\n      context.test(title);\n    };\n  });\n};\n\n}); // module: interfaces/tdd.js\n\nrequire.register(\"mocha.js\", function(module, exports, require){\n/*!\n * mocha\n * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n * MIT Licensed\n */\n\n/**\n * Module dependencies.\n */\n\nvar path = require('browser/path')\n  , utils = require('./utils');\n\n/**\n * Expose `Mocha`.\n */\n\nexports = module.exports = Mocha;\n\n/**\n * Expose internals.\n */\n\nexports.utils = utils;\nexports.interfaces = require('./interfaces');\nexports.reporters = require('./reporters');\nexports.Runnable = require('./runnable');\nexports.Context = require('./context');\nexports.Runner = require('./runner');\nexports.Suite = require('./suite');\nexports.Hook = require('./hook');\nexports.Test = require('./test');\n\n/**\n * Return image `name` path.\n *\n * @param {String} name\n * @return {String}\n * @api private\n */\n\nfunction image(name) {\n  return __dirname + '/../images/' + name + '.png';\n}\n\n/**\n * Setup mocha with `options`.\n *\n * Options:\n *\n *   - `ui` name \"bdd\", \"tdd\", \"exports\" etc\n *   - `reporter` reporter instance, defaults to `mocha.reporters.Dot`\n *   - `globals` array of accepted globals\n *   - `timeout` timeout in milliseconds\n *   - `bail` bail on the first test failure\n *   - `slow` milliseconds to wait before considering a test slow\n *   - `ignoreLeaks` ignore global leaks\n *   - `grep` string or regexp to filter tests with\n *\n * @param {Object} options\n * @api public\n */\n\nfunction Mocha(options) {\n  options = options || {};\n  this.files = [];\n  this.options = options;\n  this.grep(options.grep);\n  this.suite = new exports.Suite('', new exports.Context);\n  this.ui(options.ui);\n  this.bail(options.bail);\n  this.reporter(options.reporter);\n  if (null != options.timeout) this.timeout(options.timeout);\n  this.useColors(options.useColors)\n  if (options.slow) this.slow(options.slow);\n\n  this.suite.on('pre-require', function (context) {\n    exports.afterEach = context.afterEach || context.teardown;\n    exports.after = context.after || context.suiteTeardown;\n    exports.beforeEach = context.beforeEach || context.setup;\n    exports.before = context.before || context.suiteSetup;\n    exports.describe = context.describe || context.suite;\n    exports.it = context.it || context.test;\n    exports.setup = context.setup || context.beforeEach;\n    exports.suiteSetup = context.suiteSetup || context.before;\n    exports.suiteTeardown = context.suiteTeardown || context.after;\n    exports.suite = context.suite || context.describe;\n    exports.teardown = context.teardown || context.afterEach;\n    exports.test = context.test || context.it;\n  });\n}\n\n/**\n * Enable or disable bailing on the first failure.\n *\n * @param {Boolean} [bail]\n * @api public\n */\n\nMocha.prototype.bail = function(bail){\n  if (0 == arguments.length) bail = true;\n  this.suite.bail(bail);\n  return this;\n};\n\n/**\n * Add test `file`.\n *\n * @param {String} file\n * @api public\n */\n\nMocha.prototype.addFile = function(file){\n  this.files.push(file);\n  return this;\n};\n\n/**\n * Set reporter to `reporter`, defaults to \"dot\".\n *\n * @param {String|Function} reporter name or constructor\n * @api public\n */\n\nMocha.prototype.reporter = function(reporter){\n  if ('function' == typeof reporter) {\n    this._reporter = reporter;\n  } else {\n    reporter = reporter || 'dot';\n    var _reporter;\n    try { _reporter = require('./reporters/' + reporter); } catch (err) {};\n    if (!_reporter) try { _reporter = require(reporter); } catch (err) {};\n    if (!_reporter && reporter === 'teamcity')\n      console.warn('The Teamcity reporter was moved to a package named ' +\n        'mocha-teamcity-reporter ' +\n        '(https://npmjs.org/package/mocha-teamcity-reporter).');\n    if (!_reporter) throw new Error('invalid reporter \"' + reporter + '\"');\n    this._reporter = _reporter;\n  }\n  return this;\n};\n\n/**\n * Set test UI `name`, defaults to \"bdd\".\n *\n * @param {String} bdd\n * @api public\n */\n\nMocha.prototype.ui = function(name){\n  name = name || 'bdd';\n  this._ui = exports.interfaces[name];\n  if (!this._ui) try { this._ui = require(name); } catch (err) {};\n  if (!this._ui) throw new Error('invalid interface \"' + name + '\"');\n  this._ui = this._ui(this.suite);\n  return this;\n};\n\n/**\n * Load registered files.\n *\n * @api private\n */\n\nMocha.prototype.loadFiles = function(fn){\n  var self = this;\n  var suite = this.suite;\n  var pending = this.files.length;\n  this.files.forEach(function(file){\n    file = path.resolve(file);\n    suite.emit('pre-require', global, file, self);\n    suite.emit('require', require(file), file, self);\n    suite.emit('post-require', global, file, self);\n    --pending || (fn && fn());\n  });\n};\n\n/**\n * Enable growl support.\n *\n * @api private\n */\n\nMocha.prototype._growl = function(runner, reporter) {\n  var notify = require('growl');\n\n  runner.on('end', function(){\n    var stats = reporter.stats;\n    if (stats.failures) {\n      var msg = stats.failures + ' of ' + runner.total + ' tests failed';\n      notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });\n    } else {\n      notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {\n          name: 'mocha'\n        , title: 'Passed'\n        , image: image('ok')\n      });\n    }\n  });\n};\n\n/**\n * Add regexp to grep, if `re` is a string it is escaped.\n *\n * @param {RegExp|String} re\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.grep = function(re){\n  this.options.grep = 'string' == typeof re\n    ? new RegExp(utils.escapeRegexp(re))\n    : re;\n  return this;\n};\n\n/**\n * Invert `.grep()` matches.\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.invert = function(){\n  this.options.invert = true;\n  return this;\n};\n\n/**\n * Ignore global leaks.\n *\n * @param {Boolean} ignore\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.ignoreLeaks = function(ignore){\n  this.options.ignoreLeaks = !!ignore;\n  return this;\n};\n\n/**\n * Enable global leak checking.\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.checkLeaks = function(){\n  this.options.ignoreLeaks = false;\n  return this;\n};\n\n/**\n * Enable growl support.\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.growl = function(){\n  this.options.growl = true;\n  return this;\n};\n\n/**\n * Ignore `globals` array or string.\n *\n * @param {Array|String} globals\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.globals = function(globals){\n  this.options.globals = (this.options.globals || []).concat(globals);\n  return this;\n};\n\n/**\n * Emit color output.\n *\n * @param {Boolean} colors\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.useColors = function(colors){\n  this.options.useColors = arguments.length && colors != undefined\n    ? colors\n    : true;\n  return this;\n};\n\n/**\n * Use inline diffs rather than +/-.\n *\n * @param {Boolean} inlineDiffs\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.useInlineDiffs = function(inlineDiffs) {\n  this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined\n  ? inlineDiffs\n  : false;\n  return this;\n};\n\n/**\n * Set the timeout in milliseconds.\n *\n * @param {Number} timeout\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.timeout = function(timeout){\n  this.suite.timeout(timeout);\n  return this;\n};\n\n/**\n * Set slowness threshold in milliseconds.\n *\n * @param {Number} slow\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.slow = function(slow){\n  this.suite.slow(slow);\n  return this;\n};\n\n/**\n * Makes all tests async (accepting a callback)\n *\n * @return {Mocha}\n * @api public\n */\n\nMocha.prototype.asyncOnly = function(){\n  this.options.asyncOnly = true;\n  return this;\n};\n\n/**\n * Run tests and invoke `fn()` when complete.\n *\n * @param {Function} fn\n * @return {Runner}\n * @api public\n */\n\nMocha.prototype.run = function(fn){\n  if (this.files.length) this.loadFiles();\n  var suite = this.suite;\n  var options = this.options;\n  var runner = new exports.Runner(suite);\n  var reporter = new this._reporter(runner);\n  runner.ignoreLeaks = false !== options.ignoreLeaks;\n  runner.asyncOnly = options.asyncOnly;\n  if (options.grep) runner.grep(options.grep, options.invert);\n  if (options.globals) runner.globals(options.globals);\n  if (options.growl) this._growl(runner, reporter);\n  exports.reporters.Base.useColors = options.useColors;\n  exports.reporters.Base.inlineDiffs = options.useInlineDiffs;\n  return runner.run(fn);\n};\n\n}); // module: mocha.js\n\nrequire.register(\"ms.js\", function(module, exports, require){\n/**\n * Helpers.\n */\n\nvar s = 1000;\nvar m = s * 60;\nvar h = m * 60;\nvar d = h * 24;\nvar y = d * 365.25;\n\n/**\n * Parse or format the given `val`.\n *\n * Options:\n *\n *  - `long` verbose formatting [false]\n *\n * @param {String|Number} val\n * @param {Object} options\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function(val, options){\n  options = options || {};\n  if ('string' == typeof val) return parse(val);\n  return options.long ? longFormat(val) : shortFormat(val);\n};\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n  var match = /^((?:\\d+)?\\.?\\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);\n  if (!match) return;\n  var n = parseFloat(match[1]);\n  var type = (match[2] || 'ms').toLowerCase();\n  switch (type) {\n    case 'years':\n    case 'year':\n    case 'y':\n      return n * y;\n    case 'days':\n    case 'day':\n    case 'd':\n      return n * d;\n    case 'hours':\n    case 'hour':\n    case 'h':\n      return n * h;\n    case 'minutes':\n    case 'minute':\n    case 'm':\n      return n * m;\n    case 'seconds':\n    case 'second':\n    case 's':\n      return n * s;\n    case 'ms':\n      return n;\n  }\n}\n\n/**\n * Short format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction shortFormat(ms) {\n  if (ms >= d) return Math.round(ms / d) + 'd';\n  if (ms >= h) return Math.round(ms / h) + 'h';\n  if (ms >= m) return Math.round(ms / m) + 'm';\n  if (ms >= s) return Math.round(ms / s) + 's';\n  return ms + 'ms';\n}\n\n/**\n * Long format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction longFormat(ms) {\n  return plural(ms, d, 'day')\n    || plural(ms, h, 'hour')\n    || plural(ms, m, 'minute')\n    || plural(ms, s, 'second')\n    || ms + ' ms';\n}\n\n/**\n * Pluralization helper.\n */\n\nfunction plural(ms, n, name) {\n  if (ms < n) return;\n  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;\n  return Math.ceil(ms / n) + ' ' + name + 's';\n}\n\n}); // module: ms.js\n\nrequire.register(\"reporters/base.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar tty = require('browser/tty')\n  , diff = require('browser/diff')\n  , ms = require('../ms')\n  , utils = require('../utils');\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date\n  , setTimeout = global.setTimeout\n  , setInterval = global.setInterval\n  , clearTimeout = global.clearTimeout\n  , clearInterval = global.clearInterval;\n\n/**\n * Check if both stdio streams are associated with a tty.\n */\n\nvar isatty = tty.isatty(1) && tty.isatty(2);\n\n/**\n * Expose `Base`.\n */\n\nexports = module.exports = Base;\n\n/**\n * Enable coloring by default.\n */\n\nexports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined);\n\n/**\n * Inline diffs instead of +/-\n */\n\nexports.inlineDiffs = false;\n\n/**\n * Default color map.\n */\n\nexports.colors = {\n    'pass': 90\n  , 'fail': 31\n  , 'bright pass': 92\n  , 'bright fail': 91\n  , 'bright yellow': 93\n  , 'pending': 36\n  , 'suite': 0\n  , 'error title': 0\n  , 'error message': 31\n  , 'error stack': 90\n  , 'checkmark': 32\n  , 'fast': 90\n  , 'medium': 33\n  , 'slow': 31\n  , 'green': 32\n  , 'light': 90\n  , 'diff gutter': 90\n  , 'diff added': 42\n  , 'diff removed': 41\n};\n\n/**\n * Default symbol map.\n */\n\nexports.symbols = {\n  ok: '✓',\n  err: '✖',\n  dot: '․'\n};\n\n// With node.js on Windows: use symbols available in terminal default fonts\nif ('win32' == process.platform) {\n  exports.symbols.ok = '\\u221A';\n  exports.symbols.err = '\\u00D7';\n  exports.symbols.dot = '.';\n}\n\n/**\n * Color `str` with the given `type`,\n * allowing colors to be disabled,\n * as well as user-defined color\n * schemes.\n *\n * @param {String} type\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nvar color = exports.color = function(type, str) {\n  if (!exports.useColors) return str;\n  return '\\u001b[' + exports.colors[type] + 'm' + str + '\\u001b[0m';\n};\n\n/**\n * Expose term window size, with some\n * defaults for when stderr is not a tty.\n */\n\nexports.window = {\n  width: isatty\n    ? process.stdout.getWindowSize\n      ? process.stdout.getWindowSize(1)[0]\n      : tty.getWindowSize()[1]\n    : 75\n};\n\n/**\n * Expose some basic cursor interactions\n * that are common among reporters.\n */\n\nexports.cursor = {\n  hide: function(){\n    isatty && process.stdout.write('\\u001b[?25l');\n  },\n\n  show: function(){\n    isatty && process.stdout.write('\\u001b[?25h');\n  },\n\n  deleteLine: function(){\n    isatty && process.stdout.write('\\u001b[2K');\n  },\n\n  beginningOfLine: function(){\n    isatty && process.stdout.write('\\u001b[0G');\n  },\n\n  CR: function(){\n    if (isatty) {\n      exports.cursor.deleteLine();\n      exports.cursor.beginningOfLine();\n    } else {\n      process.stdout.write('\\r');\n    }\n  }\n};\n\n/**\n * Outut the given `failures` as a list.\n *\n * @param {Array} failures\n * @api public\n */\n\nexports.list = function(failures){\n  console.error();\n  failures.forEach(function(test, i){\n    // format\n    var fmt = color('error title', '  %s) %s:\\n')\n      + color('error message', '     %s')\n      + color('error stack', '\\n%s\\n');\n\n    // msg\n    var err = test.err\n      , message = err.message || ''\n      , stack = err.stack || message\n      , index = stack.indexOf(message) + message.length\n      , msg = stack.slice(0, index)\n      , actual = err.actual\n      , expected = err.expected\n      , escape = true;\n\n    // uncaught\n    if (err.uncaught) {\n      msg = 'Uncaught ' + msg;\n    }\n\n    // explicitly show diff\n    if (err.showDiff && sameType(actual, expected)) {\n      escape = false;\n      err.actual = actual = stringify(canonicalize(actual));\n      err.expected = expected = stringify(canonicalize(expected));\n    }\n\n    // actual / expected diff\n    if ('string' == typeof actual && 'string' == typeof expected) {\n      fmt = color('error title', '  %s) %s:\\n%s') + color('error stack', '\\n%s\\n');\n      var match = message.match(/^([^:]+): expected/);\n      msg = '\\n      ' + color('error message', match ? match[1] : msg);\n\n      if (exports.inlineDiffs) {\n        msg += inlineDiff(err, escape);\n      } else {\n        msg += unifiedDiff(err, escape);\n      }\n    }\n\n    // indent stack trace without msg\n    stack = stack.slice(index ? index + 1 : index)\n      .replace(/^/gm, '  ');\n\n    console.error(fmt, (i + 1), test.fullTitle(), msg, stack);\n  });\n};\n\n/**\n * Initialize a new `Base` reporter.\n *\n * All other reporters generally\n * inherit from this reporter, providing\n * stats such as test duration, number\n * of tests passed / failed etc.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Base(runner) {\n  var self = this\n    , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }\n    , failures = this.failures = [];\n\n  if (!runner) return;\n  this.runner = runner;\n\n  runner.stats = stats;\n\n  runner.on('start', function(){\n    stats.start = new Date;\n  });\n\n  runner.on('suite', function(suite){\n    stats.suites = stats.suites || 0;\n    suite.root || stats.suites++;\n  });\n\n  runner.on('test end', function(test){\n    stats.tests = stats.tests || 0;\n    stats.tests++;\n  });\n\n  runner.on('pass', function(test){\n    stats.passes = stats.passes || 0;\n\n    var medium = test.slow() / 2;\n    test.speed = test.duration > test.slow()\n      ? 'slow'\n      : test.duration > medium\n        ? 'medium'\n        : 'fast';\n\n    stats.passes++;\n  });\n\n  runner.on('fail', function(test, err){\n    stats.failures = stats.failures || 0;\n    stats.failures++;\n    test.err = err;\n    failures.push(test);\n  });\n\n  runner.on('end', function(){\n    stats.end = new Date;\n    stats.duration = new Date - stats.start;\n  });\n\n  runner.on('pending', function(){\n    stats.pending++;\n  });\n}\n\n/**\n * Output common epilogue used by many of\n * the bundled reporters.\n *\n * @api public\n */\n\nBase.prototype.epilogue = function(){\n  var stats = this.stats;\n  var tests;\n  var fmt;\n\n  console.log();\n\n  // passes\n  fmt = color('bright pass', ' ')\n    + color('green', ' %d passing')\n    + color('light', ' (%s)');\n\n  console.log(fmt,\n    stats.passes || 0,\n    ms(stats.duration));\n\n  // pending\n  if (stats.pending) {\n    fmt = color('pending', ' ')\n      + color('pending', ' %d pending');\n\n    console.log(fmt, stats.pending);\n  }\n\n  // failures\n  if (stats.failures) {\n    fmt = color('fail', '  %d failing');\n\n    console.error(fmt,\n      stats.failures);\n\n    Base.list(this.failures);\n    console.error();\n  }\n\n  console.log();\n};\n\n/**\n * Pad the given `str` to `len`.\n *\n * @param {String} str\n * @param {String} len\n * @return {String}\n * @api private\n */\n\nfunction pad(str, len) {\n  str = String(str);\n  return Array(len - str.length + 1).join(' ') + str;\n}\n\n\n/**\n * Returns an inline diff between 2 strings with coloured ANSI output\n *\n * @param {Error} Error with actual/expected\n * @return {String} Diff\n * @api private\n */\n\nfunction inlineDiff(err, escape) {\n  var msg = errorDiff(err, 'WordsWithSpace', escape);\n\n  // linenos\n  var lines = msg.split('\\n');\n  if (lines.length > 4) {\n    var width = String(lines.length).length;\n    msg = lines.map(function(str, i){\n      return pad(++i, width) + ' |' + ' ' + str;\n    }).join('\\n');\n  }\n\n  // legend\n  msg = '\\n'\n    + color('diff removed', 'actual')\n    + ' '\n    + color('diff added', 'expected')\n    + '\\n\\n'\n    + msg\n    + '\\n';\n\n  // indent\n  msg = msg.replace(/^/gm, '      ');\n  return msg;\n}\n\n/**\n * Returns a unified diff between 2 strings\n *\n * @param {Error} Error with actual/expected\n * @return {String} Diff\n * @api private\n */\n\nfunction unifiedDiff(err, escape) {\n  var indent = '      ';\n  function cleanUp(line) {\n    if (escape) {\n      line = escapeInvisibles(line);\n    }\n    if (line[0] === '+') return indent + colorLines('diff added', line);\n    if (line[0] === '-') return indent + colorLines('diff removed', line);\n    if (line.match(/\\@\\@/)) return null;\n    if (line.match(/\\\\ No newline/)) return null;\n    else return indent + line;\n  }\n  function notBlank(line) {\n    return line != null;\n  }\n  msg = diff.createPatch('string', err.actual, err.expected);\n  var lines = msg.split('\\n').splice(4);\n  return '\\n      '\n         + colorLines('diff added',   '+ expected') + ' '\n         + colorLines('diff removed', '- actual')\n         + '\\n\\n'\n         + lines.map(cleanUp).filter(notBlank).join('\\n');\n}\n\n/**\n * Return a character diff for `err`.\n *\n * @param {Error} err\n * @return {String}\n * @api private\n */\n\nfunction errorDiff(err, type, escape) {\n  var actual   = escape ? escapeInvisibles(err.actual)   : err.actual;\n  var expected = escape ? escapeInvisibles(err.expected) : err.expected;\n  return diff['diff' + type](actual, expected).map(function(str){\n    if (str.added) return colorLines('diff added', str.value);\n    if (str.removed) return colorLines('diff removed', str.value);\n    return str.value;\n  }).join('');\n}\n\n/**\n * Returns a string with all invisible characters in plain text\n *\n * @param {String} line\n * @return {String}\n * @api private\n */\nfunction escapeInvisibles(line) {\n    return line.replace(/\\t/g, '<tab>')\n               .replace(/\\r/g, '<CR>')\n               .replace(/\\n/g, '<LF>\\n');\n}\n\n/**\n * Color lines for `str`, using the color `name`.\n *\n * @param {String} name\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nfunction colorLines(name, str) {\n  return str.split('\\n').map(function(str){\n    return color(name, str);\n  }).join('\\n');\n}\n\n/**\n * Stringify `obj`.\n *\n * @param {Object} obj\n * @return {String}\n * @api private\n */\n\nfunction stringify(obj) {\n  if (obj instanceof RegExp) return obj.toString();\n  return JSON.stringify(obj, null, 2);\n}\n\n/**\n * Return a new object that has the keys in sorted order.\n * @param {Object} obj\n * @return {Object}\n * @api private\n */\n\n function canonicalize(obj, stack) {\n   stack = stack || [];\n\n   if (utils.indexOf(stack, obj) !== -1) return obj;\n\n   var canonicalizedObj;\n\n   if ('[object Array]' == {}.toString.call(obj)) {\n     stack.push(obj);\n     canonicalizedObj = utils.map(obj, function(item) {\n       return canonicalize(item, stack);\n     });\n     stack.pop();\n   } else if (typeof obj === 'object' && obj !== null) {\n     stack.push(obj);\n     canonicalizedObj = {};\n     utils.forEach(utils.keys(obj).sort(), function(key) {\n       canonicalizedObj[key] = canonicalize(obj[key], stack);\n     });\n     stack.pop();\n   } else {\n     canonicalizedObj = obj;\n   }\n\n   return canonicalizedObj;\n }\n\n/**\n * Check that a / b have the same type.\n *\n * @param {Object} a\n * @param {Object} b\n * @return {Boolean}\n * @api private\n */\n\nfunction sameType(a, b) {\n  a = Object.prototype.toString.call(a);\n  b = Object.prototype.toString.call(b);\n  return a == b;\n}\n\n\n}); // module: reporters/base.js\n\nrequire.register(\"reporters/doc.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , utils = require('../utils');\n\n/**\n * Expose `Doc`.\n */\n\nexports = module.exports = Doc;\n\n/**\n * Initialize a new `Doc` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Doc(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , total = runner.total\n    , indents = 2;\n\n  function indent() {\n    return Array(indents).join('  ');\n  }\n\n  runner.on('suite', function(suite){\n    if (suite.root) return;\n    ++indents;\n    console.log('%s<section class=\"suite\">', indent());\n    ++indents;\n    console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));\n    console.log('%s<dl>', indent());\n  });\n\n  runner.on('suite end', function(suite){\n    if (suite.root) return;\n    console.log('%s</dl>', indent());\n    --indents;\n    console.log('%s</section>', indent());\n    --indents;\n  });\n\n  runner.on('pass', function(test){\n    console.log('%s  <dt>%s</dt>', indent(), utils.escape(test.title));\n    var code = utils.escape(utils.clean(test.fn.toString()));\n    console.log('%s  <dd><pre><code>%s</code></pre></dd>', indent(), code);\n  });\n}\n\n}); // module: reporters/doc.js\n\nrequire.register(\"reporters/dot.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , color = Base.color;\n\n/**\n * Expose `Dot`.\n */\n\nexports = module.exports = Dot;\n\n/**\n * Initialize a new `Dot` matrix test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Dot(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , width = Base.window.width * .75 | 0\n    , n = 0;\n\n  runner.on('start', function(){\n    process.stdout.write('\\n  ');\n  });\n\n  runner.on('pending', function(test){\n    process.stdout.write(color('pending', Base.symbols.dot));\n  });\n\n  runner.on('pass', function(test){\n    if (++n % width == 0) process.stdout.write('\\n  ');\n    if ('slow' == test.speed) {\n      process.stdout.write(color('bright yellow', Base.symbols.dot));\n    } else {\n      process.stdout.write(color(test.speed, Base.symbols.dot));\n    }\n  });\n\n  runner.on('fail', function(test, err){\n    if (++n % width == 0) process.stdout.write('\\n  ');\n    process.stdout.write(color('fail', Base.symbols.dot));\n  });\n\n  runner.on('end', function(){\n    console.log();\n    self.epilogue();\n  });\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nDot.prototype = new F;\nDot.prototype.constructor = Dot;\n\n}); // module: reporters/dot.js\n\nrequire.register(\"reporters/html-cov.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar JSONCov = require('./json-cov')\n  , fs = require('browser/fs');\n\n/**\n * Expose `HTMLCov`.\n */\n\nexports = module.exports = HTMLCov;\n\n/**\n * Initialize a new `JsCoverage` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction HTMLCov(runner) {\n  var jade = require('jade')\n    , file = __dirname + '/templates/coverage.jade'\n    , str = fs.readFileSync(file, 'utf8')\n    , fn = jade.compile(str, { filename: file })\n    , self = this;\n\n  JSONCov.call(this, runner, false);\n\n  runner.on('end', function(){\n    process.stdout.write(fn({\n        cov: self.cov\n      , coverageClass: coverageClass\n    }));\n  });\n}\n\n/**\n * Return coverage class for `n`.\n *\n * @return {String}\n * @api private\n */\n\nfunction coverageClass(n) {\n  if (n >= 75) return 'high';\n  if (n >= 50) return 'medium';\n  if (n >= 25) return 'low';\n  return 'terrible';\n}\n}); // module: reporters/html-cov.js\n\nrequire.register(\"reporters/html.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , utils = require('../utils')\n  , Progress = require('../browser/progress')\n  , escape = utils.escape;\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date\n  , setTimeout = global.setTimeout\n  , setInterval = global.setInterval\n  , clearTimeout = global.clearTimeout\n  , clearInterval = global.clearInterval;\n\n/**\n * Expose `HTML`.\n */\n\nexports = module.exports = HTML;\n\n/**\n * Stats template.\n */\n\nvar statsTemplate = '<ul id=\"mocha-stats\">'\n  + '<li class=\"progress\"><canvas width=\"40\" height=\"40\"></canvas></li>'\n  + '<li class=\"passes\"><a href=\"#\">passes:</a> <em>0</em></li>'\n  + '<li class=\"failures\"><a href=\"#\">failures:</a> <em>0</em></li>'\n  + '<li class=\"duration\">duration: <em>0</em>s</li>'\n  + '</ul>';\n\n/**\n * Initialize a new `HTML` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction HTML(runner, root) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , total = runner.total\n    , stat = fragment(statsTemplate)\n    , items = stat.getElementsByTagName('li')\n    , passes = items[1].getElementsByTagName('em')[0]\n    , passesLink = items[1].getElementsByTagName('a')[0]\n    , failures = items[2].getElementsByTagName('em')[0]\n    , failuresLink = items[2].getElementsByTagName('a')[0]\n    , duration = items[3].getElementsByTagName('em')[0]\n    , canvas = stat.getElementsByTagName('canvas')[0]\n    , report = fragment('<ul id=\"mocha-report\"></ul>')\n    , stack = [report]\n    , progress\n    , ctx\n\n  root = root || document.getElementById('mocha');\n\n  if (canvas.getContext) {\n    var ratio = window.devicePixelRatio || 1;\n    canvas.style.width = canvas.width;\n    canvas.style.height = canvas.height;\n    canvas.width *= ratio;\n    canvas.height *= ratio;\n    ctx = canvas.getContext('2d');\n    ctx.scale(ratio, ratio);\n    progress = new Progress;\n  }\n\n  if (!root) return error('#mocha div missing, add it to your document');\n\n  // pass toggle\n  on(passesLink, 'click', function(){\n    unhide();\n    var name = /pass/.test(report.className) ? '' : ' pass';\n    report.className = report.className.replace(/fail|pass/g, '') + name;\n    if (report.className.trim()) hideSuitesWithout('test pass');\n  });\n\n  // failure toggle\n  on(failuresLink, 'click', function(){\n    unhide();\n    var name = /fail/.test(report.className) ? '' : ' fail';\n    report.className = report.className.replace(/fail|pass/g, '') + name;\n    if (report.className.trim()) hideSuitesWithout('test fail');\n  });\n\n  root.appendChild(stat);\n  root.appendChild(report);\n\n  if (progress) progress.size(40);\n\n  runner.on('suite', function(suite){\n    if (suite.root) return;\n\n    // suite\n    var url = self.suiteURL(suite);\n    var el = fragment('<li class=\"suite\"><h1><a href=\"%s\">%s</a></h1></li>', url, escape(suite.title));\n\n    // container\n    stack[0].appendChild(el);\n    stack.unshift(document.createElement('ul'));\n    el.appendChild(stack[0]);\n  });\n\n  runner.on('suite end', function(suite){\n    if (suite.root) return;\n    stack.shift();\n  });\n\n  runner.on('fail', function(test, err){\n    if ('hook' == test.type) runner.emit('test end', test);\n  });\n\n  runner.on('test end', function(test){\n    // TODO: add to stats\n    var percent = stats.tests / this.total * 100 | 0;\n    if (progress) progress.update(percent).draw(ctx);\n\n    // update stats\n    var ms = new Date - stats.start;\n    text(passes, stats.passes);\n    text(failures, stats.failures);\n    text(duration, (ms / 1000).toFixed(2));\n\n    // test\n    if ('passed' == test.state) {\n      var url = self.testURL(test);\n      var el = fragment('<li class=\"test pass %e\"><h2>%e<span class=\"duration\">%ems</span> <a href=\"%s\" class=\"replay\">‣</a></h2></li>', test.speed, test.title, test.duration, url);\n    } else if (test.pending) {\n      var el = fragment('<li class=\"test pass pending\"><h2>%e</h2></li>', test.title);\n    } else {\n      var el = fragment('<li class=\"test fail\"><h2>%e <a href=\"?grep=%e\" class=\"replay\">‣</a></h2></li>', test.title, encodeURIComponent(test.fullTitle()));\n      var str = test.err.stack || test.err.toString();\n\n      // FF / Opera do not add the message\n      if (!~str.indexOf(test.err.message)) {\n        str = test.err.message + '\\n' + str;\n      }\n\n      // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we\n      // check for the result of the stringifying.\n      if ('[object Error]' == str) str = test.err.message;\n\n      // Safari doesn't give you a stack. Let's at least provide a source line.\n      if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {\n        str += \"\\n(\" + test.err.sourceURL + \":\" + test.err.line + \")\";\n      }\n\n      el.appendChild(fragment('<pre class=\"error\">%e</pre>', str));\n    }\n\n    // toggle code\n    // TODO: defer\n    if (!test.pending) {\n      var h2 = el.getElementsByTagName('h2')[0];\n\n      on(h2, 'click', function(){\n        pre.style.display = 'none' == pre.style.display\n          ? 'block'\n          : 'none';\n      });\n\n      var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));\n      el.appendChild(pre);\n      pre.style.display = 'none';\n    }\n\n    // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.\n    if (stack[0]) stack[0].appendChild(el);\n  });\n}\n\n/**\n * Provide suite URL\n *\n * @param {Object} [suite]\n */\n\nHTML.prototype.suiteURL = function(suite){\n  return '?grep=' + encodeURIComponent(suite.fullTitle());\n};\n\n/**\n * Provide test URL\n *\n * @param {Object} [test]\n */\n\nHTML.prototype.testURL = function(test){\n  return '?grep=' + encodeURIComponent(test.fullTitle());\n};\n\n/**\n * Display error `msg`.\n */\n\nfunction error(msg) {\n  document.body.appendChild(fragment('<div id=\"mocha-error\">%s</div>', msg));\n}\n\n/**\n * Return a DOM fragment from `html`.\n */\n\nfunction fragment(html) {\n  var args = arguments\n    , div = document.createElement('div')\n    , i = 1;\n\n  div.innerHTML = html.replace(/%([se])/g, function(_, type){\n    switch (type) {\n      case 's': return String(args[i++]);\n      case 'e': return escape(args[i++]);\n    }\n  });\n\n  return div.firstChild;\n}\n\n/**\n * Check for suites that do not have elements\n * with `classname`, and hide them.\n */\n\nfunction hideSuitesWithout(classname) {\n  var suites = document.getElementsByClassName('suite');\n  for (var i = 0; i < suites.length; i++) {\n    var els = suites[i].getElementsByClassName(classname);\n    if (0 == els.length) suites[i].className += ' hidden';\n  }\n}\n\n/**\n * Unhide .hidden suites.\n */\n\nfunction unhide() {\n  var els = document.getElementsByClassName('suite hidden');\n  for (var i = 0; i < els.length; ++i) {\n    els[i].className = els[i].className.replace('suite hidden', 'suite');\n  }\n}\n\n/**\n * Set `el` text to `str`.\n */\n\nfunction text(el, str) {\n  if (el.textContent) {\n    el.textContent = str;\n  } else {\n    el.innerText = str;\n  }\n}\n\n/**\n * Listen on `event` with callback `fn`.\n */\n\nfunction on(el, event, fn) {\n  if (el.addEventListener) {\n    el.addEventListener(event, fn, false);\n  } else {\n    el.attachEvent('on' + event, fn);\n  }\n}\n\n}); // module: reporters/html.js\n\nrequire.register(\"reporters/index.js\", function(module, exports, require){\n\nexports.Base = require('./base');\nexports.Dot = require('./dot');\nexports.Doc = require('./doc');\nexports.TAP = require('./tap');\nexports.JSON = require('./json');\nexports.HTML = require('./html');\nexports.List = require('./list');\nexports.Min = require('./min');\nexports.Spec = require('./spec');\nexports.Nyan = require('./nyan');\nexports.XUnit = require('./xunit');\nexports.Markdown = require('./markdown');\nexports.Progress = require('./progress');\nexports.Landing = require('./landing');\nexports.JSONCov = require('./json-cov');\nexports.HTMLCov = require('./html-cov');\nexports.JSONStream = require('./json-stream');\n\n}); // module: reporters/index.js\n\nrequire.register(\"reporters/json-cov.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base');\n\n/**\n * Expose `JSONCov`.\n */\n\nexports = module.exports = JSONCov;\n\n/**\n * Initialize a new `JsCoverage` reporter.\n *\n * @param {Runner} runner\n * @param {Boolean} output\n * @api public\n */\n\nfunction JSONCov(runner, output) {\n  var self = this\n    , output = 1 == arguments.length ? true : output;\n\n  Base.call(this, runner);\n\n  var tests = []\n    , failures = []\n    , passes = [];\n\n  runner.on('test end', function(test){\n    tests.push(test);\n  });\n\n  runner.on('pass', function(test){\n    passes.push(test);\n  });\n\n  runner.on('fail', function(test){\n    failures.push(test);\n  });\n\n  runner.on('end', function(){\n    var cov = global._$jscoverage || {};\n    var result = self.cov = map(cov);\n    result.stats = self.stats;\n    result.tests = tests.map(clean);\n    result.failures = failures.map(clean);\n    result.passes = passes.map(clean);\n    if (!output) return;\n    process.stdout.write(JSON.stringify(result, null, 2 ));\n  });\n}\n\n/**\n * Map jscoverage data to a JSON structure\n * suitable for reporting.\n *\n * @param {Object} cov\n * @return {Object}\n * @api private\n */\n\nfunction map(cov) {\n  var ret = {\n      instrumentation: 'node-jscoverage'\n    , sloc: 0\n    , hits: 0\n    , misses: 0\n    , coverage: 0\n    , files: []\n  };\n\n  for (var filename in cov) {\n    var data = coverage(filename, cov[filename]);\n    ret.files.push(data);\n    ret.hits += data.hits;\n    ret.misses += data.misses;\n    ret.sloc += data.sloc;\n  }\n\n  ret.files.sort(function(a, b) {\n    return a.filename.localeCompare(b.filename);\n  });\n\n  if (ret.sloc > 0) {\n    ret.coverage = (ret.hits / ret.sloc) * 100;\n  }\n\n  return ret;\n};\n\n/**\n * Map jscoverage data for a single source file\n * to a JSON structure suitable for reporting.\n *\n * @param {String} filename name of the source file\n * @param {Object} data jscoverage coverage data\n * @return {Object}\n * @api private\n */\n\nfunction coverage(filename, data) {\n  var ret = {\n    filename: filename,\n    coverage: 0,\n    hits: 0,\n    misses: 0,\n    sloc: 0,\n    source: {}\n  };\n\n  data.source.forEach(function(line, num){\n    num++;\n\n    if (data[num] === 0) {\n      ret.misses++;\n      ret.sloc++;\n    } else if (data[num] !== undefined) {\n      ret.hits++;\n      ret.sloc++;\n    }\n\n    ret.source[num] = {\n        source: line\n      , coverage: data[num] === undefined\n        ? ''\n        : data[num]\n    };\n  });\n\n  ret.coverage = ret.hits / ret.sloc * 100;\n\n  return ret;\n}\n\n/**\n * Return a plain-object representation of `test`\n * free of cyclic properties etc.\n *\n * @param {Object} test\n * @return {Object}\n * @api private\n */\n\nfunction clean(test) {\n  return {\n      title: test.title\n    , fullTitle: test.fullTitle()\n    , duration: test.duration\n  }\n}\n\n}); // module: reporters/json-cov.js\n\nrequire.register(\"reporters/json-stream.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , color = Base.color;\n\n/**\n * Expose `List`.\n */\n\nexports = module.exports = List;\n\n/**\n * Initialize a new `List` test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction List(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , total = runner.total;\n\n  runner.on('start', function(){\n    console.log(JSON.stringify(['start', { total: total }]));\n  });\n\n  runner.on('pass', function(test){\n    console.log(JSON.stringify(['pass', clean(test)]));\n  });\n\n  runner.on('fail', function(test, err){\n    console.log(JSON.stringify(['fail', clean(test)]));\n  });\n\n  runner.on('end', function(){\n    process.stdout.write(JSON.stringify(['end', self.stats]));\n  });\n}\n\n/**\n * Return a plain-object representation of `test`\n * free of cyclic properties etc.\n *\n * @param {Object} test\n * @return {Object}\n * @api private\n */\n\nfunction clean(test) {\n  return {\n      title: test.title\n    , fullTitle: test.fullTitle()\n    , duration: test.duration\n  }\n}\n}); // module: reporters/json-stream.js\n\nrequire.register(\"reporters/json.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `JSON`.\n */\n\nexports = module.exports = JSONReporter;\n\n/**\n * Initialize a new `JSON` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction JSONReporter(runner) {\n  var self = this;\n  Base.call(this, runner);\n\n  var tests = []\n    , failures = []\n    , passes = [];\n\n  runner.on('test end', function(test){\n    tests.push(test);\n  });\n\n  runner.on('pass', function(test){\n    passes.push(test);\n  });\n\n  runner.on('fail', function(test){\n    failures.push(test);\n  });\n\n  runner.on('end', function(){\n    var obj = {\n        stats: self.stats\n      , tests: tests.map(clean)\n      , failures: failures.map(clean)\n      , passes: passes.map(clean)\n    };\n\n    process.stdout.write(JSON.stringify(obj, null, 2));\n  });\n}\n\n/**\n * Return a plain-object representation of `test`\n * free of cyclic properties etc.\n *\n * @param {Object} test\n * @return {Object}\n * @api private\n */\n\nfunction clean(test) {\n  return {\n      title: test.title\n    , fullTitle: test.fullTitle()\n    , duration: test.duration\n  }\n}\n}); // module: reporters/json.js\n\nrequire.register(\"reporters/landing.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `Landing`.\n */\n\nexports = module.exports = Landing;\n\n/**\n * Airplane color.\n */\n\nBase.colors.plane = 0;\n\n/**\n * Airplane crash color.\n */\n\nBase.colors['plane crash'] = 31;\n\n/**\n * Runway color.\n */\n\nBase.colors.runway = 90;\n\n/**\n * Initialize a new `Landing` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Landing(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , width = Base.window.width * .75 | 0\n    , total = runner.total\n    , stream = process.stdout\n    , plane = color('plane', '✈')\n    , crashed = -1\n    , n = 0;\n\n  function runway() {\n    var buf = Array(width).join('-');\n    return '  ' + color('runway', buf);\n  }\n\n  runner.on('start', function(){\n    stream.write('\\n  ');\n    cursor.hide();\n  });\n\n  runner.on('test end', function(test){\n    // check if the plane crashed\n    var col = -1 == crashed\n      ? width * ++n / total | 0\n      : crashed;\n\n    // show the crash\n    if ('failed' == test.state) {\n      plane = color('plane crash', '✈');\n      crashed = col;\n    }\n\n    // render landing strip\n    stream.write('\\u001b[4F\\n\\n');\n    stream.write(runway());\n    stream.write('\\n  ');\n    stream.write(color('runway', Array(col).join('⋅')));\n    stream.write(plane)\n    stream.write(color('runway', Array(width - col).join('⋅') + '\\n'));\n    stream.write(runway());\n    stream.write('\\u001b[0m');\n  });\n\n  runner.on('end', function(){\n    cursor.show();\n    console.log();\n    self.epilogue();\n  });\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nLanding.prototype = new F;\nLanding.prototype.constructor = Landing;\n\n}); // module: reporters/landing.js\n\nrequire.register(\"reporters/list.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `List`.\n */\n\nexports = module.exports = List;\n\n/**\n * Initialize a new `List` test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction List(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , n = 0;\n\n  runner.on('start', function(){\n    console.log();\n  });\n\n  runner.on('test', function(test){\n    process.stdout.write(color('pass', '    ' + test.fullTitle() + ': '));\n  });\n\n  runner.on('pending', function(test){\n    var fmt = color('checkmark', '  -')\n      + color('pending', ' %s');\n    console.log(fmt, test.fullTitle());\n  });\n\n  runner.on('pass', function(test){\n    var fmt = color('checkmark', '  '+Base.symbols.dot)\n      + color('pass', ' %s: ')\n      + color(test.speed, '%dms');\n    cursor.CR();\n    console.log(fmt, test.fullTitle(), test.duration);\n  });\n\n  runner.on('fail', function(test, err){\n    cursor.CR();\n    console.log(color('fail', '  %d) %s'), ++n, test.fullTitle());\n  });\n\n  runner.on('end', self.epilogue.bind(self));\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nList.prototype = new F;\nList.prototype.constructor = List;\n\n\n}); // module: reporters/list.js\n\nrequire.register(\"reporters/markdown.js\", function(module, exports, require){\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , utils = require('../utils');\n\n/**\n * Expose `Markdown`.\n */\n\nexports = module.exports = Markdown;\n\n/**\n * Initialize a new `Markdown` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Markdown(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , level = 0\n    , buf = '';\n\n  function title(str) {\n    return Array(level).join('#') + ' ' + str;\n  }\n\n  function indent() {\n    return Array(level).join('  ');\n  }\n\n  function mapTOC(suite, obj) {\n    var ret = obj;\n    obj = obj[suite.title] = obj[suite.title] || { suite: suite };\n    suite.suites.forEach(function(suite){\n      mapTOC(suite, obj);\n    });\n    return ret;\n  }\n\n  function stringifyTOC(obj, level) {\n    ++level;\n    var buf = '';\n    var link;\n    for (var key in obj) {\n      if ('suite' == key) continue;\n      if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\\n';\n      if (key) buf += Array(level).join('  ') + link;\n      buf += stringifyTOC(obj[key], level);\n    }\n    --level;\n    return buf;\n  }\n\n  function generateTOC(suite) {\n    var obj = mapTOC(suite, {});\n    return stringifyTOC(obj, 0);\n  }\n\n  generateTOC(runner.suite);\n\n  runner.on('suite', function(suite){\n    ++level;\n    var slug = utils.slug(suite.fullTitle());\n    buf += '<a name=\"' + slug + '\"></a>' + '\\n';\n    buf += title(suite.title) + '\\n';\n  });\n\n  runner.on('suite end', function(suite){\n    --level;\n  });\n\n  runner.on('pass', function(test){\n    var code = utils.clean(test.fn.toString());\n    buf += test.title + '.\\n';\n    buf += '\\n```js\\n';\n    buf += code + '\\n';\n    buf += '```\\n\\n';\n  });\n\n  runner.on('end', function(){\n    process.stdout.write('# TOC\\n');\n    process.stdout.write(generateTOC(runner.suite));\n    process.stdout.write(buf);\n  });\n}\n}); // module: reporters/markdown.js\n\nrequire.register(\"reporters/min.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base');\n\n/**\n * Expose `Min`.\n */\n\nexports = module.exports = Min;\n\n/**\n * Initialize a new `Min` minimal test reporter (best used with --watch).\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Min(runner) {\n  Base.call(this, runner);\n\n  runner.on('start', function(){\n    // clear screen\n    process.stdout.write('\\u001b[2J');\n    // set cursor position\n    process.stdout.write('\\u001b[1;3H');\n  });\n\n  runner.on('end', this.epilogue.bind(this));\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nMin.prototype = new F;\nMin.prototype.constructor = Min;\n\n\n}); // module: reporters/min.js\n\nrequire.register(\"reporters/nyan.js\", function(module, exports, require){\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , color = Base.color;\n\n/**\n * Expose `Dot`.\n */\n\nexports = module.exports = NyanCat;\n\n/**\n * Initialize a new `Dot` matrix test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction NyanCat(runner) {\n  Base.call(this, runner);\n  var self = this\n    , stats = this.stats\n    , width = Base.window.width * .75 | 0\n    , rainbowColors = this.rainbowColors = self.generateColors()\n    , colorIndex = this.colorIndex = 0\n    , numerOfLines = this.numberOfLines = 4\n    , trajectories = this.trajectories = [[], [], [], []]\n    , nyanCatWidth = this.nyanCatWidth = 11\n    , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)\n    , scoreboardWidth = this.scoreboardWidth = 5\n    , tick = this.tick = 0\n    , n = 0;\n\n  runner.on('start', function(){\n    Base.cursor.hide();\n    self.draw();\n  });\n\n  runner.on('pending', function(test){\n    self.draw();\n  });\n\n  runner.on('pass', function(test){\n    self.draw();\n  });\n\n  runner.on('fail', function(test, err){\n    self.draw();\n  });\n\n  runner.on('end', function(){\n    Base.cursor.show();\n    for (var i = 0; i < self.numberOfLines; i++) write('\\n');\n    self.epilogue();\n  });\n}\n\n/**\n * Draw the nyan cat\n *\n * @api private\n */\n\nNyanCat.prototype.draw = function(){\n  this.appendRainbow();\n  this.drawScoreboard();\n  this.drawRainbow();\n  this.drawNyanCat();\n  this.tick = !this.tick;\n};\n\n/**\n * Draw the \"scoreboard\" showing the number\n * of passes, failures and pending tests.\n *\n * @api private\n */\n\nNyanCat.prototype.drawScoreboard = function(){\n  var stats = this.stats;\n  var colors = Base.colors;\n\n  function draw(color, n) {\n    write(' ');\n    write('\\u001b[' + color + 'm' + n + '\\u001b[0m');\n    write('\\n');\n  }\n\n  draw(colors.green, stats.passes);\n  draw(colors.fail, stats.failures);\n  draw(colors.pending, stats.pending);\n  write('\\n');\n\n  this.cursorUp(this.numberOfLines);\n};\n\n/**\n * Append the rainbow.\n *\n * @api private\n */\n\nNyanCat.prototype.appendRainbow = function(){\n  var segment = this.tick ? '_' : '-';\n  var rainbowified = this.rainbowify(segment);\n\n  for (var index = 0; index < this.numberOfLines; index++) {\n    var trajectory = this.trajectories[index];\n    if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();\n    trajectory.push(rainbowified);\n  }\n};\n\n/**\n * Draw the rainbow.\n *\n * @api private\n */\n\nNyanCat.prototype.drawRainbow = function(){\n  var self = this;\n\n  this.trajectories.forEach(function(line, index) {\n    write('\\u001b[' + self.scoreboardWidth + 'C');\n    write(line.join(''));\n    write('\\n');\n  });\n\n  this.cursorUp(this.numberOfLines);\n};\n\n/**\n * Draw the nyan cat\n *\n * @api private\n */\n\nNyanCat.prototype.drawNyanCat = function() {\n  var self = this;\n  var startWidth = this.scoreboardWidth + this.trajectories[0].length;\n  var color = '\\u001b[' + startWidth + 'C';\n  var padding = '';\n\n  write(color);\n  write('_,------,');\n  write('\\n');\n\n  write(color);\n  padding = self.tick ? '  ' : '   ';\n  write('_|' + padding + '/\\\\_/\\\\ ');\n  write('\\n');\n\n  write(color);\n  padding = self.tick ? '_' : '__';\n  var tail = self.tick ? '~' : '^';\n  var face;\n  write(tail + '|' + padding + this.face() + ' ');\n  write('\\n');\n\n  write(color);\n  padding = self.tick ? ' ' : '  ';\n  write(padding + '\"\"  \"\" ');\n  write('\\n');\n\n  this.cursorUp(this.numberOfLines);\n};\n\n/**\n * Draw nyan cat face.\n *\n * @return {String}\n * @api private\n */\n\nNyanCat.prototype.face = function() {\n  var stats = this.stats;\n  if (stats.failures) {\n    return '( x .x)';\n  } else if (stats.pending) {\n    return '( o .o)';\n  } else if(stats.passes) {\n    return '( ^ .^)';\n  } else {\n    return '( - .-)';\n  }\n}\n\n/**\n * Move cursor up `n`.\n *\n * @param {Number} n\n * @api private\n */\n\nNyanCat.prototype.cursorUp = function(n) {\n  write('\\u001b[' + n + 'A');\n};\n\n/**\n * Move cursor down `n`.\n *\n * @param {Number} n\n * @api private\n */\n\nNyanCat.prototype.cursorDown = function(n) {\n  write('\\u001b[' + n + 'B');\n};\n\n/**\n * Generate rainbow colors.\n *\n * @return {Array}\n * @api private\n */\n\nNyanCat.prototype.generateColors = function(){\n  var colors = [];\n\n  for (var i = 0; i < (6 * 7); i++) {\n    var pi3 = Math.floor(Math.PI / 3);\n    var n = (i * (1.0 / 6));\n    var r = Math.floor(3 * Math.sin(n) + 3);\n    var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);\n    var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);\n    colors.push(36 * r + 6 * g + b + 16);\n  }\n\n  return colors;\n};\n\n/**\n * Apply rainbow to the given `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nNyanCat.prototype.rainbowify = function(str){\n  var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];\n  this.colorIndex += 1;\n  return '\\u001b[38;5;' + color + 'm' + str + '\\u001b[0m';\n};\n\n/**\n * Stdout helper.\n */\n\nfunction write(string) {\n  process.stdout.write(string);\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nNyanCat.prototype = new F;\nNyanCat.prototype.constructor = NyanCat;\n\n\n}); // module: reporters/nyan.js\n\nrequire.register(\"reporters/progress.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `Progress`.\n */\n\nexports = module.exports = Progress;\n\n/**\n * General progress bar color.\n */\n\nBase.colors.progress = 90;\n\n/**\n * Initialize a new `Progress` bar test reporter.\n *\n * @param {Runner} runner\n * @param {Object} options\n * @api public\n */\n\nfunction Progress(runner, options) {\n  Base.call(this, runner);\n\n  var self = this\n    , options = options || {}\n    , stats = this.stats\n    , width = Base.window.width * .50 | 0\n    , total = runner.total\n    , complete = 0\n    , max = Math.max;\n\n  // default chars\n  options.open = options.open || '[';\n  options.complete = options.complete || '▬';\n  options.incomplete = options.incomplete || Base.symbols.dot;\n  options.close = options.close || ']';\n  options.verbose = false;\n\n  // tests started\n  runner.on('start', function(){\n    console.log();\n    cursor.hide();\n  });\n\n  // tests complete\n  runner.on('test end', function(){\n    complete++;\n    var incomplete = total - complete\n      , percent = complete / total\n      , n = width * percent | 0\n      , i = width - n;\n\n    cursor.CR();\n    process.stdout.write('\\u001b[J');\n    process.stdout.write(color('progress', '  ' + options.open));\n    process.stdout.write(Array(n).join(options.complete));\n    process.stdout.write(Array(i).join(options.incomplete));\n    process.stdout.write(color('progress', options.close));\n    if (options.verbose) {\n      process.stdout.write(color('progress', ' ' + complete + ' of ' + total));\n    }\n  });\n\n  // tests are complete, output some stats\n  // and the failures if any\n  runner.on('end', function(){\n    cursor.show();\n    console.log();\n    self.epilogue();\n  });\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nProgress.prototype = new F;\nProgress.prototype.constructor = Progress;\n\n\n}); // module: reporters/progress.js\n\nrequire.register(\"reporters/spec.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `Spec`.\n */\n\nexports = module.exports = Spec;\n\n/**\n * Initialize a new `Spec` test reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction Spec(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , indents = 0\n    , n = 0;\n\n  function indent() {\n    return Array(indents).join('  ')\n  }\n\n  runner.on('start', function(){\n    console.log();\n  });\n\n  runner.on('suite', function(suite){\n    ++indents;\n    console.log(color('suite', '%s%s'), indent(), suite.title);\n  });\n\n  runner.on('suite end', function(suite){\n    --indents;\n    if (1 == indents) console.log();\n  });\n\n  runner.on('pending', function(test){\n    var fmt = indent() + color('pending', '  - %s');\n    console.log(fmt, test.title);\n  });\n\n  runner.on('pass', function(test){\n    if ('fast' == test.speed) {\n      var fmt = indent()\n        + color('checkmark', '  ' + Base.symbols.ok)\n        + color('pass', ' %s ');\n      cursor.CR();\n      console.log(fmt, test.title);\n    } else {\n      var fmt = indent()\n        + color('checkmark', '  ' + Base.symbols.ok)\n        + color('pass', ' %s ')\n        + color(test.speed, '(%dms)');\n      cursor.CR();\n      console.log(fmt, test.title, test.duration);\n    }\n  });\n\n  runner.on('fail', function(test, err){\n    cursor.CR();\n    console.log(indent() + color('fail', '  %d) %s'), ++n, test.title);\n  });\n\n  runner.on('end', self.epilogue.bind(self));\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nSpec.prototype = new F;\nSpec.prototype.constructor = Spec;\n\n\n}); // module: reporters/spec.js\n\nrequire.register(\"reporters/tap.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , cursor = Base.cursor\n  , color = Base.color;\n\n/**\n * Expose `TAP`.\n */\n\nexports = module.exports = TAP;\n\n/**\n * Initialize a new `TAP` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction TAP(runner) {\n  Base.call(this, runner);\n\n  var self = this\n    , stats = this.stats\n    , n = 1\n    , passes = 0\n    , failures = 0;\n\n  runner.on('start', function(){\n    var total = runner.grepTotal(runner.suite);\n    console.log('%d..%d', 1, total);\n  });\n\n  runner.on('test end', function(){\n    ++n;\n  });\n\n  runner.on('pending', function(test){\n    console.log('ok %d %s # SKIP -', n, title(test));\n  });\n\n  runner.on('pass', function(test){\n    passes++;\n    console.log('ok %d %s', n, title(test));\n  });\n\n  runner.on('fail', function(test, err){\n    failures++;\n    console.log('not ok %d %s', n, title(test));\n    if (err.stack) console.log(err.stack.replace(/^/gm, '  '));\n  });\n\n  runner.on('end', function(){\n    console.log('# tests ' + (passes + failures));\n    console.log('# pass ' + passes);\n    console.log('# fail ' + failures);\n  });\n}\n\n/**\n * Return a TAP-safe title of `test`\n *\n * @param {Object} test\n * @return {String}\n * @api private\n */\n\nfunction title(test) {\n  return test.fullTitle().replace(/#/g, '');\n}\n\n}); // module: reporters/tap.js\n\nrequire.register(\"reporters/xunit.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Base = require('./base')\n  , utils = require('../utils')\n  , escape = utils.escape;\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date\n  , setTimeout = global.setTimeout\n  , setInterval = global.setInterval\n  , clearTimeout = global.clearTimeout\n  , clearInterval = global.clearInterval;\n\n/**\n * Expose `XUnit`.\n */\n\nexports = module.exports = XUnit;\n\n/**\n * Initialize a new `XUnit` reporter.\n *\n * @param {Runner} runner\n * @api public\n */\n\nfunction XUnit(runner) {\n  Base.call(this, runner);\n  var stats = this.stats\n    , tests = []\n    , self = this;\n\n  runner.on('pending', function(test){\n    tests.push(test);\n  });\n\n  runner.on('pass', function(test){\n    tests.push(test);\n  });\n\n  runner.on('fail', function(test){\n    tests.push(test);\n  });\n\n  runner.on('end', function(){\n    console.log(tag('testsuite', {\n        name: 'Mocha Tests'\n      , tests: stats.tests\n      , failures: stats.failures\n      , errors: stats.failures\n      , skipped: stats.tests - stats.failures - stats.passes\n      , timestamp: (new Date).toUTCString()\n      , time: (stats.duration / 1000) || 0\n    }, false));\n\n    tests.forEach(test);\n    console.log('</testsuite>');\n  });\n}\n\n/**\n * Inherit from `Base.prototype`.\n */\n\nfunction F(){};\nF.prototype = Base.prototype;\nXUnit.prototype = new F;\nXUnit.prototype.constructor = XUnit;\n\n\n/**\n * Output tag for the given `test.`\n */\n\nfunction test(test) {\n  var attrs = {\n      classname: test.parent.fullTitle()\n    , name: test.title\n    , time: (test.duration / 1000) || 0\n  };\n\n  if ('failed' == test.state) {\n    var err = test.err;\n    attrs.message = escape(err.message);\n    console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));\n  } else if (test.pending) {\n    console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));\n  } else {\n    console.log(tag('testcase', attrs, true) );\n  }\n}\n\n/**\n * HTML tag helper.\n */\n\nfunction tag(name, attrs, close, content) {\n  var end = close ? '/>' : '>'\n    , pairs = []\n    , tag;\n\n  for (var key in attrs) {\n    pairs.push(key + '=\"' + escape(attrs[key]) + '\"');\n  }\n\n  tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;\n  if (content) tag += content + '</' + name + end;\n  return tag;\n}\n\n/**\n * Return cdata escaped CDATA `str`.\n */\n\nfunction cdata(str) {\n  return '<![CDATA[' + escape(str) + ']]>';\n}\n\n}); // module: reporters/xunit.js\n\nrequire.register(\"runnable.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar EventEmitter = require('browser/events').EventEmitter\n  , debug = require('browser/debug')('mocha:runnable')\n  , milliseconds = require('./ms');\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date\n  , setTimeout = global.setTimeout\n  , setInterval = global.setInterval\n  , clearTimeout = global.clearTimeout\n  , clearInterval = global.clearInterval;\n\n/**\n * Object#toString().\n */\n\nvar toString = Object.prototype.toString;\n\n/**\n * Expose `Runnable`.\n */\n\nmodule.exports = Runnable;\n\n/**\n * Initialize a new `Runnable` with the given `title` and callback `fn`.\n *\n * @param {String} title\n * @param {Function} fn\n * @api private\n */\n\nfunction Runnable(title, fn) {\n  this.title = title;\n  this.fn = fn;\n  this.async = fn && fn.length;\n  this.sync = ! this.async;\n  this._timeout = 2000;\n  this._slow = 75;\n  this.timedOut = false;\n}\n\n/**\n * Inherit from `EventEmitter.prototype`.\n */\n\nfunction F(){};\nF.prototype = EventEmitter.prototype;\nRunnable.prototype = new F;\nRunnable.prototype.constructor = Runnable;\n\n\n/**\n * Set & get timeout `ms`.\n *\n * @param {Number|String} ms\n * @return {Runnable|Number} ms or self\n * @api private\n */\n\nRunnable.prototype.timeout = function(ms){\n  if (0 == arguments.length) return this._timeout;\n  if ('string' == typeof ms) ms = milliseconds(ms);\n  debug('timeout %d', ms);\n  this._timeout = ms;\n  if (this.timer) this.resetTimeout();\n  return this;\n};\n\n/**\n * Set & get slow `ms`.\n *\n * @param {Number|String} ms\n * @return {Runnable|Number} ms or self\n * @api private\n */\n\nRunnable.prototype.slow = function(ms){\n  if (0 === arguments.length) return this._slow;\n  if ('string' == typeof ms) ms = milliseconds(ms);\n  debug('timeout %d', ms);\n  this._slow = ms;\n  return this;\n};\n\n/**\n * Return the full title generated by recursively\n * concatenating the parent's full title.\n *\n * @return {String}\n * @api public\n */\n\nRunnable.prototype.fullTitle = function(){\n  return this.parent.fullTitle() + ' ' + this.title;\n};\n\n/**\n * Clear the timeout.\n *\n * @api private\n */\n\nRunnable.prototype.clearTimeout = function(){\n  clearTimeout(this.timer);\n};\n\n/**\n * Inspect the runnable void of private properties.\n *\n * @return {String}\n * @api private\n */\n\nRunnable.prototype.inspect = function(){\n  return JSON.stringify(this, function(key, val){\n    if ('_' == key[0]) return;\n    if ('parent' == key) return '#<Suite>';\n    if ('ctx' == key) return '#<Context>';\n    return val;\n  }, 2);\n};\n\n/**\n * Reset the timeout.\n *\n * @api private\n */\n\nRunnable.prototype.resetTimeout = function(){\n  var self = this;\n  var ms = this.timeout() || 1e9;\n\n  this.clearTimeout();\n  this.timer = setTimeout(function(){\n    self.callback(new Error('timeout of ' + ms + 'ms exceeded'));\n    self.timedOut = true;\n  }, ms);\n};\n\n/**\n * Whitelist these globals for this test run\n *\n * @api private\n */\nRunnable.prototype.globals = function(arr){\n  var self = this;\n  this._allowedGlobals = arr;\n};\n\n/**\n * Run the test and invoke `fn(err)`.\n *\n * @param {Function} fn\n * @api private\n */\n\nRunnable.prototype.run = function(fn){\n  var self = this\n    , ms = this.timeout()\n    , start = new Date\n    , ctx = this.ctx\n    , finished\n    , emitted;\n\n  if (ctx) ctx.runnable(this);\n\n  // called multiple times\n  function multiple(err) {\n    if (emitted) return;\n    emitted = true;\n    self.emit('error', err || new Error('done() called multiple times'));\n  }\n\n  // finished\n  function done(err) {\n    if (self.timedOut) return;\n    if (finished) return multiple(err);\n    self.clearTimeout();\n    self.duration = new Date - start;\n    finished = true;\n    fn(err);\n  }\n\n  // for .resetTimeout()\n  this.callback = done;\n\n  // explicit async with `done` argument\n  if (this.async) {\n    this.resetTimeout();\n\n    try {\n      this.fn.call(ctx, function(err){\n        if (err instanceof Error || toString.call(err) === \"[object Error]\") return done(err);\n        if (null != err) return done(new Error('done() invoked with non-Error: ' + err));\n        done();\n      });\n    } catch (err) {\n      done(err);\n    }\n    return;\n  }\n\n  if (this.asyncOnly) {\n    return done(new Error('--async-only option in use without declaring `done()`'));\n  }\n\n  // sync or promise-returning\n  try {\n    if (!this.pending) {\n      callFn(this.fn);\n    } else {\n      done();\n    }\n  } catch (err) {\n    done(err);\n  }\n\n  function callFn(fn) {\n    var result = fn.call(ctx);\n    if (result && typeof result.then === 'function') {\n      self.resetTimeout();\n      result.then(\n        function(){\n          done();\n        },\n        done\n      );\n    } else {\n      done();\n    }\n  }\n};\n\n}); // module: runnable.js\n\nrequire.register(\"runner.js\", function(module, exports, require){\n/**\n * Module dependencies.\n */\n\nvar EventEmitter = require('browser/events').EventEmitter\n  , debug = require('browser/debug')('mocha:runner')\n  , Test = require('./test')\n  , utils = require('./utils')\n  , filter = utils.filter\n  , keys = utils.keys;\n\n/**\n * Non-enumerable globals.\n */\n\nvar globals = [\n  'setTimeout',\n  'clearTimeout',\n  'setInterval',\n  'clearInterval',\n  'XMLHttpRequest',\n  'Date'\n];\n\n/**\n * Expose `Runner`.\n */\n\nmodule.exports = Runner;\n\n/**\n * Initialize a `Runner` for the given `suite`.\n *\n * Events:\n *\n *   - `start`  execution started\n *   - `end`  execution complete\n *   - `suite`  (suite) test suite execution started\n *   - `suite end`  (suite) all tests (and sub-suites) have finished\n *   - `test`  (test) test execution started\n *   - `test end`  (test) test completed\n *   - `hook`  (hook) hook execution started\n *   - `hook end`  (hook) hook complete\n *   - `pass`  (test) test passed\n *   - `fail`  (test, err) test failed\n *   - `pending`  (test) test pending\n *\n * @api public\n */\n\nfunction Runner(suite) {\n  var self = this;\n  this._globals = [];\n  this._abort = false;\n  this.suite = suite;\n  this.total = suite.total();\n  this.failures = 0;\n  this.on('test end', function(test){ self.checkGlobals(test); });\n  this.on('hook end', function(hook){ self.checkGlobals(hook); });\n  this.grep(/.*/);\n  this.globals(this.globalProps().concat(extraGlobals()));\n}\n\n/**\n * Wrapper for setImmediate, process.nextTick, or browser polyfill.\n *\n * @param {Function} fn\n * @api private\n */\n\nRunner.immediately = global.setImmediate || process.nextTick;\n\n/**\n * Inherit from `EventEmitter.prototype`.\n */\n\nfunction F(){};\nF.prototype = EventEmitter.prototype;\nRunner.prototype = new F;\nRunner.prototype.constructor = Runner;\n\n\n/**\n * Run tests with full titles matching `re`. Updates runner.total\n * with number of tests matched.\n *\n * @param {RegExp} re\n * @param {Boolean} invert\n * @return {Runner} for chaining\n * @api public\n */\n\nRunner.prototype.grep = function(re, invert){\n  debug('grep %s', re);\n  this._grep = re;\n  this._invert = invert;\n  this.total = this.grepTotal(this.suite);\n  return this;\n};\n\n/**\n * Returns the number of tests matching the grep search for the\n * given suite.\n *\n * @param {Suite} suite\n * @return {Number}\n * @api public\n */\n\nRunner.prototype.grepTotal = function(suite) {\n  var self = this;\n  var total = 0;\n\n  suite.eachTest(function(test){\n    var match = self._grep.test(test.fullTitle());\n    if (self._invert) match = !match;\n    if (match) total++;\n  });\n\n  return total;\n};\n\n/**\n * Return a list of global properties.\n *\n * @return {Array}\n * @api private\n */\n\nRunner.prototype.globalProps = function() {\n  var props = utils.keys(global);\n\n  // non-enumerables\n  for (var i = 0; i < globals.length; ++i) {\n    if (~utils.indexOf(props, globals[i])) continue;\n    props.push(globals[i]);\n  }\n\n  return props;\n};\n\n/**\n * Allow the given `arr` of globals.\n *\n * @param {Array} arr\n * @return {Runner} for chaining\n * @api public\n */\n\nRunner.prototype.globals = function(arr){\n  if (0 == arguments.length) return this._globals;\n  debug('globals %j', arr);\n  this._globals = this._globals.concat(arr);\n  return this;\n};\n\n/**\n * Check for global variable leaks.\n *\n * @api private\n */\n\nRunner.prototype.checkGlobals = function(test){\n  if (this.ignoreLeaks) return;\n  var ok = this._globals;\n\n  var globals = this.globalProps();\n  var isNode = process.kill;\n  var leaks;\n\n  if (test) {\n    ok = ok.concat(test._allowedGlobals || []);\n  }\n\n  if(this.prevGlobalsLength == globals.length) return;\n  this.prevGlobalsLength = globals.length;\n\n  leaks = filterLeaks(ok, globals);\n  this._globals = this._globals.concat(leaks);\n\n  if (leaks.length > 1) {\n    this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));\n  } else if (leaks.length) {\n    this.fail(test, new Error('global leak detected: ' + leaks[0]));\n  }\n};\n\n/**\n * Fail the given `test`.\n *\n * @param {Test} test\n * @param {Error} err\n * @api private\n */\n\nRunner.prototype.fail = function(test, err){\n  ++this.failures;\n  test.state = 'failed';\n\n  if ('string' == typeof err) {\n    err = new Error('the string \"' + err + '\" was thrown, throw an Error :)');\n  }\n\n  this.emit('fail', test, err);\n};\n\n/**\n * Fail the given `hook` with `err`.\n *\n * Hook failures work in the following pattern:\n * - If bail, then exit\n * - Failed `before` hook skips all tests in a suite and subsuites,\n *   but jumps to corresponding `after` hook\n * - Failed `before each` hook skips remaining tests in a\n *   suite and jumps to corresponding `after each` hook,\n *   which is run only once\n * - Failed `after` hook does not alter\n *   execution order\n * - Failed `after each` hook skips remaining tests in a\n *   suite and subsuites, but executes other `after each`\n *   hooks\n *\n * @param {Hook} hook\n * @param {Error} err\n * @api private\n */\n\nRunner.prototype.failHook = function(hook, err){\n  this.fail(hook, err);\n  if (this.suite.bail()) {\n    this.emit('end');\n  }\n};\n\n/**\n * Run hook `name` callbacks and then invoke `fn()`.\n *\n * @param {String} name\n * @param {Function} function\n * @api private\n */\n\nRunner.prototype.hook = function(name, fn){\n  var suite = this.suite\n    , hooks = suite['_' + name]\n    , self = this\n    , timer;\n\n  function next(i) {\n    var hook = hooks[i];\n    if (!hook) return fn();\n    if (self.failures && suite.bail()) return fn();\n    self.currentRunnable = hook;\n\n    hook.ctx.currentTest = self.test;\n\n    self.emit('hook', hook);\n\n    hook.on('error', function(err){\n      self.failHook(hook, err);\n    });\n\n    hook.run(function(err){\n      hook.removeAllListeners('error');\n      var testError = hook.error();\n      if (testError) self.fail(self.test, testError);\n      if (err) {\n        self.failHook(hook, err);\n\n        // stop executing hooks, notify callee of hook err\n        return fn(err);\n      }\n      self.emit('hook end', hook);\n      delete hook.ctx.currentTest;\n      next(++i);\n    });\n  }\n\n  Runner.immediately(function(){\n    next(0);\n  });\n};\n\n/**\n * Run hook `name` for the given array of `suites`\n * in order, and callback `fn(err, errSuite)`.\n *\n * @param {String} name\n * @param {Array} suites\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.hooks = function(name, suites, fn){\n  var self = this\n    , orig = this.suite;\n\n  function next(suite) {\n    self.suite = suite;\n\n    if (!suite) {\n      self.suite = orig;\n      return fn();\n    }\n\n    self.hook(name, function(err){\n      if (err) {\n        var errSuite = self.suite;\n        self.suite = orig;\n        return fn(err, errSuite);\n      }\n\n      next(suites.pop());\n    });\n  }\n\n  next(suites.pop());\n};\n\n/**\n * Run hooks from the top level down.\n *\n * @param {String} name\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.hookUp = function(name, fn){\n  var suites = [this.suite].concat(this.parents()).reverse();\n  this.hooks(name, suites, fn);\n};\n\n/**\n * Run hooks from the bottom up.\n *\n * @param {String} name\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.hookDown = function(name, fn){\n  var suites = [this.suite].concat(this.parents());\n  this.hooks(name, suites, fn);\n};\n\n/**\n * Return an array of parent Suites from\n * closest to furthest.\n *\n * @return {Array}\n * @api private\n */\n\nRunner.prototype.parents = function(){\n  var suite = this.suite\n    , suites = [];\n  while (suite = suite.parent) suites.push(suite);\n  return suites;\n};\n\n/**\n * Run the current test and callback `fn(err)`.\n *\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.runTest = function(fn){\n  var test = this.test\n    , self = this;\n\n  if (this.asyncOnly) test.asyncOnly = true;\n\n  try {\n    test.on('error', function(err){\n      self.fail(test, err);\n    });\n    test.run(fn);\n  } catch (err) {\n    fn(err);\n  }\n};\n\n/**\n * Run tests in the given `suite` and invoke\n * the callback `fn()` when complete.\n *\n * @param {Suite} suite\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.runTests = function(suite, fn){\n  var self = this\n    , tests = suite.tests.slice()\n    , test;\n\n\n  function hookErr(err, errSuite, after) {\n    // before/after Each hook for errSuite failed:\n    var orig = self.suite;\n\n    // for failed 'after each' hook start from errSuite parent,\n    // otherwise start from errSuite itself\n    self.suite = after ? errSuite.parent : errSuite;\n\n    if (self.suite) {\n      // call hookUp afterEach\n      self.hookUp('afterEach', function(err2, errSuite2) {\n        self.suite = orig;\n        // some hooks may fail even now\n        if (err2) return hookErr(err2, errSuite2, true);\n        // report error suite\n        fn(errSuite);\n      });\n    } else {\n      // there is no need calling other 'after each' hooks\n      self.suite = orig;\n      fn(errSuite);\n    }\n  }\n\n  function next(err, errSuite) {\n    // if we bail after first err\n    if (self.failures && suite._bail) return fn();\n\n    if (self._abort) return fn();\n\n    if (err) return hookErr(err, errSuite, true);\n\n    // next test\n    test = tests.shift();\n\n    // all done\n    if (!test) return fn();\n\n    // grep\n    var match = self._grep.test(test.fullTitle());\n    if (self._invert) match = !match;\n    if (!match) return next();\n\n    // pending\n    if (test.pending) {\n      self.emit('pending', test);\n      self.emit('test end', test);\n      return next();\n    }\n\n    // execute test and hook(s)\n    self.emit('test', self.test = test);\n    self.hookDown('beforeEach', function(err, errSuite){\n\n      if (err) return hookErr(err, errSuite, false);\n\n      self.currentRunnable = self.test;\n      self.runTest(function(err){\n        test = self.test;\n\n        if (err) {\n          self.fail(test, err);\n          self.emit('test end', test);\n          return self.hookUp('afterEach', next);\n        }\n\n        test.state = 'passed';\n        self.emit('pass', test);\n        self.emit('test end', test);\n        self.hookUp('afterEach', next);\n      });\n    });\n  }\n\n  this.next = next;\n  next();\n};\n\n/**\n * Run the given `suite` and invoke the\n * callback `fn()` when complete.\n *\n * @param {Suite} suite\n * @param {Function} fn\n * @api private\n */\n\nRunner.prototype.runSuite = function(suite, fn){\n  var total = this.grepTotal(suite)\n    , self = this\n    , i = 0;\n\n  debug('run suite %s', suite.fullTitle());\n\n  if (!total) return fn();\n\n  this.emit('suite', this.suite = suite);\n\n  function next(errSuite) {\n    if (errSuite) {\n      // current suite failed on a hook from errSuite\n      if (errSuite == suite) {\n        // if errSuite is current suite\n        // continue to the next sibling suite\n        return done();\n      } else {\n        // errSuite is among the parents of current suite\n        // stop execution of errSuite and all sub-suites\n        return done(errSuite);\n      }\n    }\n\n    if (self._abort) return done();\n\n    var curr = suite.suites[i++];\n    if (!curr) return done();\n    self.runSuite(curr, next);\n  }\n\n  function done(errSuite) {\n    self.suite = suite;\n    self.hook('afterAll', function(){\n      self.emit('suite end', suite);\n      fn(errSuite);\n    });\n  }\n\n  this.hook('beforeAll', function(err){\n    if (err) return done();\n    self.runTests(suite, next);\n  });\n};\n\n/**\n * Handle uncaught exceptions.\n *\n * @param {Error} err\n * @api private\n */\n\nRunner.prototype.uncaught = function(err){\n  debug('uncaught exception %s', err.message);\n  var runnable = this.currentRunnable;\n  if (!runnable || 'failed' == runnable.state) return;\n  runnable.clearTimeout();\n  err.uncaught = true;\n  this.fail(runnable, err);\n\n  // recover from test\n  if ('test' == runnable.type) {\n    this.emit('test end', runnable);\n    this.hookUp('afterEach', this.next);\n    return;\n  }\n\n  // bail on hooks\n  this.emit('end');\n};\n\n/**\n * Run the root suite and invoke `fn(failures)`\n * on completion.\n *\n * @param {Function} fn\n * @return {Runner} for chaining\n * @api public\n */\n\nRunner.prototype.run = function(fn){\n  var self = this\n    , fn = fn || function(){};\n\n  function uncaught(err){\n    self.uncaught(err);\n  }\n\n  debug('start');\n\n  // callback\n  this.on('end', function(){\n    debug('end');\n    process.removeListener('uncaughtException', uncaught);\n    fn(self.failures);\n  });\n\n  // run suites\n  this.emit('start');\n  this.runSuite(this.suite, function(){\n    debug('finished running');\n    self.emit('end');\n  });\n\n  // uncaught exception\n  process.on('uncaughtException', uncaught);\n\n  return this;\n};\n\n/**\n * Cleanly abort execution\n *\n * @return {Runner} for chaining\n * @api public\n */\nRunner.prototype.abort = function(){\n  debug('aborting');\n  this._abort = true;\n}\n\n/**\n * Filter leaks with the given globals flagged as `ok`.\n *\n * @param {Array} ok\n * @param {Array} globals\n * @return {Array}\n * @api private\n */\n\nfunction filterLeaks(ok, globals) {\n  return filter(globals, function(key){\n    // Firefox and Chrome exposes iframes as index inside the window object\n    if (/^d+/.test(key)) return false;\n\n    // in firefox\n    // if runner runs in an iframe, this iframe's window.getInterface method not init at first\n    // it is assigned in some seconds\n    if (global.navigator && /^getInterface/.test(key)) return false;\n\n    // an iframe could be approached by window[iframeIndex]\n    // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak\n    if (global.navigator && /^\\d+/.test(key)) return false;\n\n    // Opera and IE expose global variables for HTML element IDs (issue #243)\n    if (/^mocha-/.test(key)) return false;\n\n    var matched = filter(ok, function(ok){\n      if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);\n      return key == ok;\n    });\n    return matched.length == 0 && (!global.navigator || 'onerror' !== key);\n  });\n}\n\n/**\n * Array of globals dependent on the environment.\n *\n * @return {Array}\n * @api private\n */\n\n function extraGlobals() {\n  if (typeof(process) === 'object' &&\n      typeof(process.version) === 'string') {\n\n    var nodeVersion = process.version.split('.').reduce(function(a, v) {\n      return a << 8 | v;\n    });\n\n    // 'errno' was renamed to process._errno in v0.9.11.\n\n    if (nodeVersion < 0x00090B) {\n      return ['errno'];\n    }\n  }\n\n  return [];\n }\n\n}); // module: runner.js\n\nrequire.register(\"suite.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar EventEmitter = require('browser/events').EventEmitter\n  , debug = require('browser/debug')('mocha:suite')\n  , milliseconds = require('./ms')\n  , utils = require('./utils')\n  , Hook = require('./hook');\n\n/**\n * Expose `Suite`.\n */\n\nexports = module.exports = Suite;\n\n/**\n * Create a new `Suite` with the given `title`\n * and parent `Suite`. When a suite with the\n * same title is already present, that suite\n * is returned to provide nicer reporter\n * and more flexible meta-testing.\n *\n * @param {Suite} parent\n * @param {String} title\n * @return {Suite}\n * @api public\n */\n\nexports.create = function(parent, title){\n  var suite = new Suite(title, parent.ctx);\n  suite.parent = parent;\n  if (parent.pending) suite.pending = true;\n  title = suite.fullTitle();\n  parent.addSuite(suite);\n  return suite;\n};\n\n/**\n * Initialize a new `Suite` with the given\n * `title` and `ctx`.\n *\n * @param {String} title\n * @param {Context} ctx\n * @api private\n */\n\nfunction Suite(title, ctx) {\n  this.title = title;\n  this.ctx = ctx;\n  this.suites = [];\n  this.tests = [];\n  this.pending = false;\n  this._beforeEach = [];\n  this._beforeAll = [];\n  this._afterEach = [];\n  this._afterAll = [];\n  this.root = !title;\n  this._timeout = 2000;\n  this._slow = 75;\n  this._bail = false;\n}\n\n/**\n * Inherit from `EventEmitter.prototype`.\n */\n\nfunction F(){};\nF.prototype = EventEmitter.prototype;\nSuite.prototype = new F;\nSuite.prototype.constructor = Suite;\n\n\n/**\n * Return a clone of this `Suite`.\n *\n * @return {Suite}\n * @api private\n */\n\nSuite.prototype.clone = function(){\n  var suite = new Suite(this.title);\n  debug('clone');\n  suite.ctx = this.ctx;\n  suite.timeout(this.timeout());\n  suite.slow(this.slow());\n  suite.bail(this.bail());\n  return suite;\n};\n\n/**\n * Set timeout `ms` or short-hand such as \"2s\".\n *\n * @param {Number|String} ms\n * @return {Suite|Number} for chaining\n * @api private\n */\n\nSuite.prototype.timeout = function(ms){\n  if (0 == arguments.length) return this._timeout;\n  if ('string' == typeof ms) ms = milliseconds(ms);\n  debug('timeout %d', ms);\n  this._timeout = parseInt(ms, 10);\n  return this;\n};\n\n/**\n * Set slow `ms` or short-hand such as \"2s\".\n *\n * @param {Number|String} ms\n * @return {Suite|Number} for chaining\n * @api private\n */\n\nSuite.prototype.slow = function(ms){\n  if (0 === arguments.length) return this._slow;\n  if ('string' == typeof ms) ms = milliseconds(ms);\n  debug('slow %d', ms);\n  this._slow = ms;\n  return this;\n};\n\n/**\n * Sets whether to bail after first error.\n *\n * @parma {Boolean} bail\n * @return {Suite|Number} for chaining\n * @api private\n */\n\nSuite.prototype.bail = function(bail){\n  if (0 == arguments.length) return this._bail;\n  debug('bail %s', bail);\n  this._bail = bail;\n  return this;\n};\n\n/**\n * Run `fn(test[, done])` before running tests.\n *\n * @param {Function} fn\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.beforeAll = function(title, fn){\n  if (this.pending) return this;\n  if ('function' === typeof title) {\n    fn = title;\n    title = fn.name;\n  }\n  title = '\"before all\" hook' + (title ? ': ' + title : '');\n\n  var hook = new Hook(title, fn);\n  hook.parent = this;\n  hook.timeout(this.timeout());\n  hook.slow(this.slow());\n  hook.ctx = this.ctx;\n  this._beforeAll.push(hook);\n  this.emit('beforeAll', hook);\n  return this;\n};\n\n/**\n * Run `fn(test[, done])` after running tests.\n *\n * @param {Function} fn\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.afterAll = function(title, fn){\n  if (this.pending) return this;\n  if ('function' === typeof title) {\n    fn = title;\n    title = fn.name;\n  }\n  title = '\"after all\" hook' + (title ? ': ' + title : '');\n\n  var hook = new Hook(title, fn);\n  hook.parent = this;\n  hook.timeout(this.timeout());\n  hook.slow(this.slow());\n  hook.ctx = this.ctx;\n  this._afterAll.push(hook);\n  this.emit('afterAll', hook);\n  return this;\n};\n\n/**\n * Run `fn(test[, done])` before each test case.\n *\n * @param {Function} fn\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.beforeEach = function(title, fn){\n  if (this.pending) return this;\n  if ('function' === typeof title) {\n    fn = title;\n    title = fn.name;\n  }\n  title = '\"before each\" hook' + (title ? ': ' + title : '');\n\n  var hook = new Hook(title, fn);\n  hook.parent = this;\n  hook.timeout(this.timeout());\n  hook.slow(this.slow());\n  hook.ctx = this.ctx;\n  this._beforeEach.push(hook);\n  this.emit('beforeEach', hook);\n  return this;\n};\n\n/**\n * Run `fn(test[, done])` after each test case.\n *\n * @param {Function} fn\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.afterEach = function(title, fn){\n  if (this.pending) return this;\n  if ('function' === typeof title) {\n    fn = title;\n    title = fn.name;\n  }\n  title = '\"after each\" hook' + (title ? ': ' + title : '');\n\n  var hook = new Hook(title, fn);\n  hook.parent = this;\n  hook.timeout(this.timeout());\n  hook.slow(this.slow());\n  hook.ctx = this.ctx;\n  this._afterEach.push(hook);\n  this.emit('afterEach', hook);\n  return this;\n};\n\n/**\n * Add a test `suite`.\n *\n * @param {Suite} suite\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.addSuite = function(suite){\n  suite.parent = this;\n  suite.timeout(this.timeout());\n  suite.slow(this.slow());\n  suite.bail(this.bail());\n  this.suites.push(suite);\n  this.emit('suite', suite);\n  return this;\n};\n\n/**\n * Add a `test` to this suite.\n *\n * @param {Test} test\n * @return {Suite} for chaining\n * @api private\n */\n\nSuite.prototype.addTest = function(test){\n  test.parent = this;\n  test.timeout(this.timeout());\n  test.slow(this.slow());\n  test.ctx = this.ctx;\n  this.tests.push(test);\n  this.emit('test', test);\n  return this;\n};\n\n/**\n * Return the full title generated by recursively\n * concatenating the parent's full title.\n *\n * @return {String}\n * @api public\n */\n\nSuite.prototype.fullTitle = function(){\n  if (this.parent) {\n    var full = this.parent.fullTitle();\n    if (full) return full + ' ' + this.title;\n  }\n  return this.title;\n};\n\n/**\n * Return the total number of tests.\n *\n * @return {Number}\n * @api public\n */\n\nSuite.prototype.total = function(){\n  return utils.reduce(this.suites, function(sum, suite){\n    return sum + suite.total();\n  }, 0) + this.tests.length;\n};\n\n/**\n * Iterates through each suite recursively to find\n * all tests. Applies a function in the format\n * `fn(test)`.\n *\n * @param {Function} fn\n * @return {Suite}\n * @api private\n */\n\nSuite.prototype.eachTest = function(fn){\n  utils.forEach(this.tests, fn);\n  utils.forEach(this.suites, function(suite){\n    suite.eachTest(fn);\n  });\n  return this;\n};\n\n}); // module: suite.js\n\nrequire.register(\"test.js\", function(module, exports, require){\n\n/**\n * Module dependencies.\n */\n\nvar Runnable = require('./runnable');\n\n/**\n * Expose `Test`.\n */\n\nmodule.exports = Test;\n\n/**\n * Initialize a new `Test` with the given `title` and callback `fn`.\n *\n * @param {String} title\n * @param {Function} fn\n * @api private\n */\n\nfunction Test(title, fn) {\n  Runnable.call(this, title, fn);\n  this.pending = !fn;\n  this.type = 'test';\n}\n\n/**\n * Inherit from `Runnable.prototype`.\n */\n\nfunction F(){};\nF.prototype = Runnable.prototype;\nTest.prototype = new F;\nTest.prototype.constructor = Test;\n\n\n}); // module: test.js\n\nrequire.register(\"utils.js\", function(module, exports, require){\n/**\n * Module dependencies.\n */\n\nvar fs = require('browser/fs')\n  , path = require('browser/path')\n  , join = path.join\n  , debug = require('browser/debug')('mocha:watch');\n\n/**\n * Ignored directories.\n */\n\nvar ignore = ['node_modules', '.git'];\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param  {String} html\n * @return {String}\n * @api private\n */\n\nexports.escape = function(html){\n  return String(html)\n    .replace(/&/g, '&amp;')\n    .replace(/\"/g, '&quot;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;');\n};\n\n/**\n * Array#forEach (<=IE8)\n *\n * @param {Array} array\n * @param {Function} fn\n * @param {Object} scope\n * @api private\n */\n\nexports.forEach = function(arr, fn, scope){\n  for (var i = 0, l = arr.length; i < l; i++)\n    fn.call(scope, arr[i], i);\n};\n\n/**\n * Array#map (<=IE8)\n *\n * @param {Array} array\n * @param {Function} fn\n * @param {Object} scope\n * @api private\n */\n\nexports.map = function(arr, fn, scope){\n  var result = [];\n  for (var i = 0, l = arr.length; i < l; i++)\n    result.push(fn.call(scope, arr[i], i));\n  return result;\n};\n\n/**\n * Array#indexOf (<=IE8)\n *\n * @parma {Array} arr\n * @param {Object} obj to find index of\n * @param {Number} start\n * @api private\n */\n\nexports.indexOf = function(arr, obj, start){\n  for (var i = start || 0, l = arr.length; i < l; i++) {\n    if (arr[i] === obj)\n      return i;\n  }\n  return -1;\n};\n\n/**\n * Array#reduce (<=IE8)\n *\n * @param {Array} array\n * @param {Function} fn\n * @param {Object} initial value\n * @api private\n */\n\nexports.reduce = function(arr, fn, val){\n  var rval = val;\n\n  for (var i = 0, l = arr.length; i < l; i++) {\n    rval = fn(rval, arr[i], i, arr);\n  }\n\n  return rval;\n};\n\n/**\n * Array#filter (<=IE8)\n *\n * @param {Array} array\n * @param {Function} fn\n * @api private\n */\n\nexports.filter = function(arr, fn){\n  var ret = [];\n\n  for (var i = 0, l = arr.length; i < l; i++) {\n    var val = arr[i];\n    if (fn(val, i, arr)) ret.push(val);\n  }\n\n  return ret;\n};\n\n/**\n * Object.keys (<=IE8)\n *\n * @param {Object} obj\n * @return {Array} keys\n * @api private\n */\n\nexports.keys = Object.keys || function(obj) {\n  var keys = []\n    , has = Object.prototype.hasOwnProperty // for `window` on <=IE8\n\n  for (var key in obj) {\n    if (has.call(obj, key)) {\n      keys.push(key);\n    }\n  }\n\n  return keys;\n};\n\n/**\n * Watch the given `files` for changes\n * and invoke `fn(file)` on modification.\n *\n * @param {Array} files\n * @param {Function} fn\n * @api private\n */\n\nexports.watch = function(files, fn){\n  var options = { interval: 100 };\n  files.forEach(function(file){\n    debug('file %s', file);\n    fs.watchFile(file, options, function(curr, prev){\n      if (prev.mtime < curr.mtime) fn(file);\n    });\n  });\n};\n\n/**\n * Ignored files.\n */\n\nfunction ignored(path){\n  return !~ignore.indexOf(path);\n}\n\n/**\n * Lookup files in the given `dir`.\n *\n * @return {Array}\n * @api private\n */\n\nexports.files = function(dir, ret){\n  ret = ret || [];\n\n  fs.readdirSync(dir)\n  .filter(ignored)\n  .forEach(function(path){\n    path = join(dir, path);\n    if (fs.statSync(path).isDirectory()) {\n      exports.files(path, ret);\n    } else if (path.match(/\\.(js|coffee|litcoffee|coffee.md)$/)) {\n      ret.push(path);\n    }\n  });\n\n  return ret;\n};\n\n/**\n * Compute a slug from the given `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nexports.slug = function(str){\n  return str\n    .toLowerCase()\n    .replace(/ +/g, '-')\n    .replace(/[^-\\w]/g, '');\n};\n\n/**\n * Strip the function definition from `str`,\n * and re-indent for pre whitespace.\n */\n\nexports.clean = function(str) {\n  str = str\n    .replace(/\\r\\n?|[\\n\\u2028\\u2029]/g, \"\\n\").replace(/^\\uFEFF/, '')\n    .replace(/^function *\\(.*\\) *{/, '')\n    .replace(/\\s+\\}$/, '');\n\n  var spaces = str.match(/^\\n?( *)/)[1].length\n    , tabs = str.match(/^\\n?(\\t*)/)[1].length\n    , re = new RegExp('^\\n?' + (tabs ? '\\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm');\n\n  str = str.replace(re, '');\n\n  return exports.trim(str);\n};\n\n/**\n * Escape regular expression characters in `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nexports.escapeRegexp = function(str){\n  return str.replace(/[-\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n};\n\n/**\n * Trim the given `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nexports.trim = function(str){\n  return str.replace(/^\\s+|\\s+$/g, '');\n};\n\n/**\n * Parse the given `qs`.\n *\n * @param {String} qs\n * @return {Object}\n * @api private\n */\n\nexports.parseQuery = function(qs){\n  return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){\n    var i = pair.indexOf('=')\n      , key = pair.slice(0, i)\n      , val = pair.slice(++i);\n\n    obj[key] = decodeURIComponent(val);\n    return obj;\n  }, {});\n};\n\n/**\n * Highlight the given string of `js`.\n *\n * @param {String} js\n * @return {String}\n * @api private\n */\n\nfunction highlight(js) {\n  return js\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\\/\\/(.*)/gm, '<span class=\"comment\">//$1</span>')\n    .replace(/('.*?')/gm, '<span class=\"string\">$1</span>')\n    .replace(/(\\d+\\.\\d+)/gm, '<span class=\"number\">$1</span>')\n    .replace(/(\\d+)/gm, '<span class=\"number\">$1</span>')\n    .replace(/\\bnew *(\\w+)/gm, '<span class=\"keyword\">new</span> <span class=\"init\">$1</span>')\n    .replace(/\\b(function|new|throw|return|var|if|else)\\b/gm, '<span class=\"keyword\">$1</span>')\n}\n\n/**\n * Highlight the contents of tag `name`.\n *\n * @param {String} name\n * @api private\n */\n\nexports.highlightTags = function(name) {\n  var code = document.getElementsByTagName(name);\n  for (var i = 0, len = code.length; i < len; ++i) {\n    code[i].innerHTML = highlight(code[i].innerHTML);\n  }\n};\n\n}); // module: utils.js\n// The global object is \"self\" in Web Workers.\nglobal = (function() { return this; })();\n\n/**\n * Save timer references to avoid Sinon interfering (see GH-237).\n */\n\nvar Date = global.Date;\nvar setTimeout = global.setTimeout;\nvar setInterval = global.setInterval;\nvar clearTimeout = global.clearTimeout;\nvar clearInterval = global.clearInterval;\n\n/**\n * Node shims.\n *\n * These are meant only to allow\n * mocha.js to run untouched, not\n * to allow running node code in\n * the browser.\n */\n\nvar process = {};\nprocess.exit = function(status){};\nprocess.stdout = {};\n\nvar uncaughtExceptionHandlers = [];\n\n/**\n * Remove uncaughtException listener.\n */\n\nprocess.removeListener = function(e, fn){\n  if ('uncaughtException' == e) {\n    global.onerror = function() {};\n    var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn);\n    if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); }\n  }\n};\n\n/**\n * Implements uncaughtException listener.\n */\n\nprocess.on = function(e, fn){\n  if ('uncaughtException' == e) {\n    global.onerror = function(err, url, line){\n      fn(new Error(err + ' (' + url + ':' + line + ')'));\n      return true;\n    };\n    uncaughtExceptionHandlers.push(fn);\n  }\n};\n\n/**\n * Expose mocha.\n */\n\nvar Mocha = global.Mocha = require('mocha'),\n    mocha = global.mocha = new Mocha({ reporter: 'html' });\n\n// The BDD UI is registered by default, but no UI will be functional in the\n// browser without an explicit call to the overridden `mocha.ui` (see below).\n// Ensure that this default UI does not expose its methods to the global scope.\nmocha.suite.removeAllListeners('pre-require');\n\nvar immediateQueue = []\n  , immediateTimeout;\n\nfunction timeslice() {\n  var immediateStart = new Date().getTime();\n  while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {\n    immediateQueue.shift()();\n  }\n  if (immediateQueue.length) {\n    immediateTimeout = setTimeout(timeslice, 0);\n  } else {\n    immediateTimeout = null;\n  }\n}\n\n/**\n * High-performance override of Runner.immediately.\n */\n\nMocha.Runner.immediately = function(callback) {\n  immediateQueue.push(callback);\n  if (!immediateTimeout) {\n    immediateTimeout = setTimeout(timeslice, 0);\n  }\n};\n\n/**\n * Function to allow assertion libraries to throw errors directly into mocha.\n * This is useful when running tests in a browser because window.onerror will\n * only receive the 'message' attribute of the Error.\n */\nmocha.throwError = function(err) {\n  Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) {\n    fn(err);\n  });\n  throw err;\n};\n\n/**\n * Override ui to ensure that the ui functions are initialized.\n * Normally this would happen in Mocha.prototype.loadFiles.\n */\n\nmocha.ui = function(ui){\n  Mocha.prototype.ui.call(this, ui);\n  this.suite.emit('pre-require', global, null, this);\n  return this;\n};\n\n/**\n * Setup mocha with the given setting options.\n */\n\nmocha.setup = function(opts){\n  if ('string' == typeof opts) opts = { ui: opts };\n  for (var opt in opts) this[opt](opts[opt]);\n  return this;\n};\n\n/**\n * Run mocha, returning the Runner.\n */\n\nmocha.run = function(fn){\n  var options = mocha.options;\n  mocha.globals('location');\n\n  var query = Mocha.utils.parseQuery(global.location.search || '');\n  if (query.grep) mocha.grep(query.grep);\n  if (query.invert) mocha.invert();\n\n  return Mocha.prototype.run.call(mocha, function(){\n    // The DOM Document is not available in Web Workers.\n    if (global.document) {\n      Mocha.utils.highlightTags('code');\n    }\n    if (fn) fn();\n  });\n};\n\n/**\n * Expose the process shim.\n */\n\nMocha.process = process;\n})();\n"
  },
  {
    "path": "tests/mocha-includes.js",
    "content": "global.acorn = require(\"acorn\");\nglobal.chai = require(\"chai\");\nglobal.assert = chai.assert;\nglobal.should = require(\"chai\").should();\nglobal.expect = require(\"chai\").expect;\nglobal.AssertionError = require(\"chai\").AssertionError;\n\nglobal.ScanJS = require(\"../common/scan.js\");\nvar fs = require(\"fs\");\nvar signatures = JSON.parse(fs.readFileSync(\"../common/rules.json\", \"utf8\"));\nScanJS.parser(acorn);\nScanJS.loadRules(signatures);\n"
  }
]