[
  {
    "path": ".csslint.rc",
    "content": "{\n  \"empty-rules\": false,\n  \"empty-rules-reason\": \"LESS creates some empty rules\",\n\n  \"bulletproof-font-face\": false,\n  \"buttetproof-font-face-reason\": \"This only seems to apply when you provide multiple formats, and we aren't doing that\",\n\n  \"qualified-headings\": false,\n  \"qualified-headings-reason\": \"This happens as part of the reset, we reset headings inside .towtruck (though technically we aren't using headings so we could remove that reset)\",\n\n  \"adjoining-classes\": false,\n  \"adjoining-classes-reason\": \".class1.class2 isn't supported in some older browsers, but we don't support those\",\n\n  \"vendor-prefix\": false,\n  \"vendor-prefix-reason\": \"We have some vendor prefixes in vendor-prefix-specific selectors, and CSSLint complains about that.\",\n  \"compatible-vendor-prefixes\": false,\n  \"compatible-vendor-prefixes-reason\": \"Same as vendor-prefix\",\n\n  \"duplicate-background-images\": false,\n  \"duplicate-background-images-reason\": \"LESS explodes out some background images, creating duplicates, but they aren't duplicated in the source.\",\n\n  \"fallback-colors\": false,\n  \"fallback-colors-reason\": \"Some old browsers don't support RGBA, but we don't care about those browsers\"\n\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n.DS_Store\n.env*\naddon/Profile\ndump.rdb\napp/http/public/recorder.css\nbuild\ntest-build\ntogetherjs.mozillalabs.com\naddon/togetherjs.xpi\ntogetherjs/togetherjs.css\ntogetherjs/togetherjsPackage.js\n"
  },
  {
    "path": ".jshintrc",
    "content": "{\n    // JSHint configurations for node-jshint.\n    // install with \"npm install -g jshint\"\n    // run with \"jshint <file(s)> --config config.json\"\n\n    \"asi\"       : false, // Semicolons required! we minify.\n    \"undef\"     : false, // var early, var often\n\n    // Predefined globals whom JSHint will accept the existence of.\n    \"browser\"   : true,\n\n    // Require curly braces\n    \"curly\": true,\n    // Require hasOwnProperty check\n    \"forin\": true,\n    \"indent\": 2,\n    // No arguments.callee/caller\n    \"noarg\": true,\n    // Warn about unused variables\n    \"unused\": true,\n    // No trailing whitespace\n    \"trailing\": true\n}"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"0.10\"\nbefore_install:\n - npm install -g npm\n - npm install -g grunt-cli\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Thanks for your interest in contributing to TogetherJS!\n\nIf you found a bug, if at all possible give us a URL where we can try\nTogetherJS.  Don't worry about tags or milestones or assigning the\nticket.  But a URL is extremely helpful!\n\n## Contributing\n\nThe [Contributing](https://togetherjs.com/docs/contributing.html)\ndocument on the site gives some more information.  Some relevant\npoints:\n\n* [Javascript style guide](https://github.com/ianb/javascript)\n\n* If you want to work on a ticket, please leave a comment to that\n  effect.  It gives us a chance to suggest where you'd look in the\n  code to implement the feature or fix the bug, and makes it less\n  likely that people's contributions will conflict.\n\n* Anything in the\n  [Blue Sky](https://github.com/mozilla/togetherjs/issues?milestone=23&page=1&state=open)\n  you are likely to find something that we're interested in having in\n  TogetherJS, but that we aren't working on.\n\n* If you have an idea of your own you'd like to implement, please open\n  a ticket describing it.  That will let other people know you are\n  working on it, and give other people an opportunity to give feedback\n  or implementation notes.\n\n## Where to start?\n\nYou should look at the\n[Contribution Wanted](https://github.com/mozilla/togetherjs/issues?labels=contribution-wanted&milestone=&page=1&state=open)\ntag to see tickets that fall into two categories:\n\n1. A good introductory task to get started on.\n\n2. Something that requires particular skills (that the core team does\n   not have) that would make a contribution particular valuable.\n"
  },
  {
    "path": "Gruntfile.js",
    "content": "/*jshint forin:false */\n\nvar fs = require(\"fs\");\nvar path = require('path');\nvar nunjucks = require(\"nunjucks\");\nvar marked = require(\"marked\");\nvar docco = require(\"docco\");\n\nvar vars = {\n  enableExample: false,\n  enableHome: false,\n  GA_ACCOUNT: \"UA-35433268-28\",\n  base: \"\"\n};\n\nvar TESTDIR = \"test-build\";\n\nmodule.exports = function (grunt) {\n\n  if (! grunt.option(\"dest\")) {\n    grunt.option(\"dest\", \"build\");\n  }\n\n  var dumpLineNumbers = false;\n  if (grunt.option(\"less-line-numbers\")) {\n    grunt.verbose.writeln(\"Enabling LESS line numbers\");\n    dumpLineNumbers = true;\n  }\n\n  function copyLink(src, dest) {\n    if (grunt.file.isDir(src)) {\n      grunt.file.mkdir(dest);\n      return;\n    }\n    var destDir = path.dirname(dest);\n    if (! grunt.file.exists(destDir)) {\n      grunt.file.mkdir(destDir);\n    }\n    if (! grunt.option(\"no-hardlink\")) {\n      try {\n        if (grunt.file.exists(dest)) {\n          grunt.file.delete(dest);\n        }\n        fs.linkSync(src, dest);\n      } catch (e) {\n        grunt.file.copy(src, dest);\n      }\n    } else {\n      grunt.file.copy(src, dest);\n    }\n  }\n\n  function copyMany(src, dest, patterns) {\n    var paths = grunt.file.expand({cwd: src}, patterns);\n    paths.forEach(function (p) {\n      var srcPath = path.join(src, p);\n      var destPath = path.join(dest, p);\n      copyLink(srcPath, destPath);\n    });\n  }\n\n\n  var libs = [];\n  grunt.file.expand(\n    [\"togetherjs/*.js\", \"!togetherjs/randomutil.js\", \"!togetherjs/recorder.js\", \"!togetherjs/togetherjs.js\"]\n  ).forEach(function (filename) {\n    filename = filename.replace(/^togetherjs\\//, \"\");\n    filename = filename.replace(/\\.js$/, \"\");\n    libs.push(filename);\n  });\n  var langs = [];\n  grunt.file.expand(\"togetherjs/locale/*.json\").forEach(function (langFilename) {\n    var lang = path.basename(langFilename).replace(/\\.json/, \"\");\n    langs.push(lang);\n    libs.push(\"templates-\" + lang);\n  });\n\n  grunt.initConfig({\n    pkg: grunt.file.readJSON('package.json'),\n\n    less: {\n      development: {\n        files: {\n          \"<%= grunt.option('dest') || 'build' %>/togetherjs/togetherjs.css\": \"togetherjs/togetherjs.less\",\n          \"<%= grunt.option('dest') || 'build' %>/togetherjs/recorder.css\": \"togetherjs/recorder.less\"\n        },\n        options: {\n          dumpLineNumbers: dumpLineNumbers\n        }\n      }\n    },\n\n    requirejs: {\n      compile: {\n        options: {\n          baseUrl: \"togetherjs/\",\n          //paths: requirejsPaths,\n          include: [\"libs/almond\"].concat(libs),\n          //Wrap any build bundle in a start and end text specified by wrap.\n          //Use this to encapsulate the module code so that define/require are\n          //not globals. The end text can expose some globals from your file,\n          //making it easy to create stand-alone libraries that do not mandate\n          //the end user use requirejs.\n          wrap: {\n            start: \"(function() {\",\n            end: \"TogetherJS.require = TogetherJS._requireObject = require;\\nTogetherJS._loaded = true;\\nrequire([\\\"session\\\"]);\\n}());\"\n          },\n          optimize: \"none\",\n          out: function writer(text) {\n            var dest = path.join(grunt.option(\"dest\"), \"togetherjs/togetherjsPackage.js\");\n            grunt.file.write(dest, text);\n          }\n        }\n      }\n    },\n\n    jshint: {\n      options: {\n        curly: true,\n        browser: true,\n        globals: {\n          define: true\n        }\n      },\n      all: [\n        \"Gruntfile\",\n        \"togetherjs/*.js\"\n      ]\n    },\n\n    csslint: {\n      // Check here for options: https://github.com/stubbornella/csslint/wiki/Rules\n      options: {\n        csslintrc: \".csslint.rc\"\n      },\n      src: [path.join(grunt.option(\"dest\"), \"togetherjs/togetherjs.css\")]\n    },\n\n    watch: {\n      main: {\n        files: [\"togetherjs/**/*\", \"Gruntfile.js\"],\n        tasks: [\"build\"],\n        options: {\n          nospawn: true\n        }\n      },\n      site: {\n        files: [\"togetherjs/**/*\", \"Gruntfile.js\", \"site/**/*\", \"!**/*_flymake*\", \"!**/*~\", \"!**/.*\"],\n        tasks: [\"build\", \"buildsite\"]\n      },\n      // FIXME: I thought I wouldn't have to watch for\n      // togetherjs/**/*.js, but because the hard links are regularly\n      // broken by git, this needs to be run often, and it's easy to\n      // forget.  Then between git action the build will be over-run,\n      // but that's harmless.\n      minimal: {\n        files: [\"togetherjs/**/*.less\", \"togetherjs/togetherjs.js\", \"togetherjs/templates-localized.js\", \n                \"togetherjs/**/*.html\", \"togetherjs/**/*.js\", \"!**/*_flymake*\", \"togetherjs/locales/**/*.json\"],\n        tasks: [\"build\"]\n      }\n    },\n\n    'http-server': {\n      'test': {\n        // the server root directory\n        root: '.',\n        cache: 30,\n        //showDir: true,\n        //autoIndex: true,\n        // run in parallel with other tasks\n        runInBackground: true\n      }\n    },\n\n    'phantom-tests': grunt.file.expand({\n      cwd:\"togetherjs/tests/\"\n    }, \"test_*.js\", \"func_*.js\", \"interactive.js\", \"!test_ot.js\").\n    reduce(function(o, k) { o[k] = {}; return o; }, {})\n\n  });\n\n  grunt.loadNpmTasks(\"grunt-contrib-less\");\n  grunt.loadNpmTasks(\"grunt-contrib-csslint\");\n  grunt.loadNpmTasks(\"grunt-contrib-jshint\");\n  grunt.loadNpmTasks(\"grunt-contrib-requirejs\");\n  grunt.loadNpmTasks(\"grunt-contrib-watch\");\n  grunt.loadNpmTasks('grunt-contrib-copy');\n\n  grunt.registerTask(\"config-requirejs\", function() {\n    // configure the requirejs paths based on the current options\n    var requirejsPaths = {\n      jquery: \"libs/jquery-1.11.1.min\",\n      walkabout: \"libs/walkabout/walkabout\",\n      esprima: \"libs/walkabout/lib/esprima\",\n      falafel: \"libs/walkabout/lib/falafel\",\n      tinycolor: \"libs/tinycolor\",\n      whrandom: \"libs/whrandom/random\",\n      jqueryui: \"libs/jquery-ui.min\",\n      jquerypunch: \"libs/jquery.ui.touch-punch.min\",\n      // Make sure we get the built form of this one:\n      templates: path.join(\"..\", grunt.option(\"dest\"), \"togetherjs/templates\")\n    };\n    langs.forEach(function(lang) {\n      requirejsPaths[\"templates-\" + lang] =\n        path.join(\"..\", grunt.option(\"dest\"), \"togetherjs\", \"templates-\" + lang);\n    });\n    grunt.config.merge({\n      requirejs: {\n        compile: {\n          options: {\n            paths: requirejsPaths\n          }\n        }\n      }\n    });\n    grunt.task.run(\"requirejs\");\n  });\n\n  grunt.registerTask(\"copylib\", \"copy the library\", function () {\n    var pattern = [\"**\", \"!togetherjs.js\", \"!templates-localized.js\", \"!**/*.less\", \"!#*\", \"!**/*_flymake*\", \"!**/*.md\", \"!**/*.tmp\", \"!**/#*\"];\n    grunt.log.writeln(\"Copying files from \" + \"togetherjs/\".cyan + \" to \" + path.join(grunt.option(\"dest\"), \"togetherjs\").cyan);\n    if (grunt.option(\"exclude-tests\")) {\n      pattern.push(\"!tests/\");\n      pattern.push(\"!tests/**\");\n      grunt.log.writeln(\"  (excluding tests)\");\n    }\n    copyMany(\n      \"togetherjs/\", path.join(grunt.option(\"dest\"), \"togetherjs\"),\n      pattern\n      );\n  });\n\n  grunt.registerTask(\"copysite\", \"copy the site (not library)\", function () {\n    grunt.log.writeln(\"Copying files from \" + \"site/\".cyan + \" to \" + grunt.option(\"dest\").cyan);\n    copyMany(\n      \"site/\", grunt.option(\"dest\"),\n      [\"**\", \"!**/*.tmpl\", \"!**/*.html\", \"!public/**\", \"!**/*_flymake*\", \"!**/*.md\"]);\n    copyMany(\n      \"site/public/\", grunt.option(\"dest\"),\n      [\"**\"]);\n  });\n\n  grunt.registerTask(\"build\", [\"copylib\", \"maybeless\", \"substitute\", \"config-requirejs\"]);\n  grunt.registerTask(\"buildsite\", [\"copysite\", \"render\", \"rendermd\", \"docco\"]);\n  grunt.registerTask(\"devwatch\", [\"build\", \"watch:minimal\"]);\n  // For some reason doing [\"build\", \"buildsite\", \"watch:site\"]\n  // doesn't work, it gets through buildsite and doesn't watch;\n  // instead just doing watch:site seems okay:\n  grunt.registerTask(\"sitewatch\", [\"buildsite\", \"watch:site\"]);\n\n  function escapeString(s) {\n    if (typeof s != \"string\") {\n      throw new Error(\"Not a string: \" + s);\n    }\n    var data = JSON.stringify(s);\n    return data.substr(1, data.length-2);\n  }\n\n  grunt.registerTask(\n    \"substitute\",\n    \"Substitute templates-localized.js and parameters in togetherjs.js\",\n    function () {\n      // FIXME: I could use grunt.file.copy(..., {process: function (content, path) {}}) here\n      var baseUrl = grunt.option(\"base-url\") || \"\"; // baseURL to be entered by the user\n      if (! baseUrl) {\n        grunt.log.writeln(\"No --base-url, using auto-detect\");\n      }\n      var destBase = grunt.option(\"dest\") || \"build\"; // where to put the built files. If not indicated then into build/\n      var hubUrl = grunt.option(\"hub-url\") || process.env.HUB_URL || \"https://hub.togetherjs.com\"; // URL of the hub server\n      grunt.log.writeln(\"Using hub URL \" + hubUrl.cyan);\n      var gitCommit = process.env.GIT_COMMIT || \"\";\n      var subs = {\n        __interface_html__: grunt.file.read(\"togetherjs/interface.html\"),\n        __help_txt__: grunt.file.read(\"togetherjs/help.txt\"), \n        __walkthrough_html__: grunt.file.read(\"togetherjs/walkthrough.html\"),\n        __baseUrl__: baseUrl,\n        __hubUrl__: hubUrl,\n        __gitCommit__: gitCommit\n      };\n\n      function substituteContent(content, s) {\n        for (var v in s) {\n          var re = new RegExp(v, \"g\");\n          if (typeof s[v] != \"string\") {\n            grunt.log.error(\"Substitution variable \" + v.cyan + \" is not a string\")\n          }\n          content = content.replace(re, escapeString(s[v]));\n        }\n        return content;\n      }\n\n      var filenames = {\n        \"togetherjs.js\": {\n          src: \"togetherjs/togetherjs.js\",\n          extraVariables: {__min__: \"no\"}\n        },\n        \"togetherjs-min.js\": {\n          src: \"togetherjs/togetherjs.js\",\n          extraVariables: {__min__: \"yes\"}\n        }\n      };\n\n      for (var dest in filenames) {\n        var info = filenames[dest];\n        var src = info.src;\n        var extraVariables = info.extraVariables;\n        dest = destBase + \"/\" + dest;\n        var content = fs.readFileSync(src, \"UTF-8\");\n        var s = subs;\n\n        if (extraVariables) {\n          s = Object.create(subs);\n          for (var a in extraVariables) {\n            s[a] = extraVariables[a];\n          }\n        }\n        content = substituteContent(content, s);\n        grunt.log.writeln(\"writing \" + src.cyan + \" to \" + dest.cyan);\n        grunt.file.write(dest, content);\n      }\n\n      grunt.file.expand(\"togetherjs/locale/*.json\").forEach(function (langFilename) {\n        var templates = grunt.file.read(\"togetherjs/templates-localized.js\");\n        var lang = path.basename(langFilename).replace(/\\.json/, \"\");\n        var translation = JSON.parse(grunt.file.read(langFilename));\n        var dest = path.join(grunt.option(\"dest\"), \"togetherjs/templates-\" + lang + \".js\");\n        \n        var translatedInterface = translateFile(\"togetherjs/interface.html\", translation);\n        var translatedHelp = translateFile(\"togetherjs/help.txt\", translation);\n        var translatedWalkthrough = translateFile(\"togetherjs/walkthrough.html\", translation);\n\n        var vars = subs;\n        \n        subs.__interface_html__ = translatedInterface;\n        subs.__help_txt__ = translatedHelp;\n        subs.__walkthrough_html__ = translatedWalkthrough;\n        subs.__names__ = translation.names;\n        templates = substituteContent(templates, subs);\n\n        grunt.file.write(dest, templates);\n        grunt.log.writeln(\"writing \" + dest.cyan + \" based on \" + langFilename.cyan);\n      });\n\n      return true;\n    }\n  );\n\n      \n  function translateFile(source, translation) {\n    var env = new nunjucks.Environment(new nunjucks.FileSystemLoader(\"./\"));\n    var tmpl = env.getTemplate(source);\n    return tmpl.render({\n      gettext: function (string) {\n        return translation[string] || string;\n      }\n    });\n  }\n\n  grunt.registerTask(\"maybeless\", \"Maybe compile togetherjs.less\", function () {\n    var sources = grunt.file.expand([\"togetherjs/**/*.less\", \"site/**/*.less\"]);\n    var found = false;\n    sources.forEach(function (fn) {\n      var source = fs.statSync(fn);\n      var destFn = grunt.option(\"dest\") + \"/\" + fn.substr(0, fn.length-4) + \"css\";\n      if (! fs.existsSync(destFn)) {\n        found = true;\n        return;\n      }\n      var dest = fs.statSync(destFn);\n      if (source.mtime.getTime() > dest.mtime.getTime()) {\n        grunt.log.writeln(\"Destination LESS out of date: \" + destFn.cyan);\n        found = true;\n      }\n    });\n    if (found) {\n      grunt.task.run(\"less\");\n    } else {\n      grunt.log.writeln(\"No .less files need regenerating.\");\n    }\n  });\n\n  grunt.registerTask(\"render\", \"Render the site\", function () {\n    var env = new nunjucks.Environment(new nunjucks.FileSystemLoader(\"site/\"));\n    var sources = grunt.file.expand({cwd: \"site/\"}, \"**/*.html\");\n    sources.forEach(function (source) {\n      var dest = grunt.option(\"dest\") + \"/\" + source;\n      grunt.log.writeln(\"Rendering \" + source.cyan + \" to \" + dest.cyan);\n      var data = grunt.file.read(\"site/\" + source);\n      var tmplVars = Object.create(vars);\n      while (true) {\n        var match = /\\{\\#\\s+set\\s+([^\\s]+)\\s+([^#]+)\\s*\\#\\}/.exec(data);\n        if (! match) {\n          break;\n        }\n        tmplVars[match[1]] = JSON.parse(match[2]);\n        grunt.log.writeln(\"  Found variable \" + match[1] + \" = \" + match[2]);\n        data = data.substr(match.index + match[0].length);\n      }\n      tmplVars.base = path.relative(path.dirname(\"site/\" + source), \"site/\");\n      if (tmplVars.base && tmplVars.base.search(/\\/$/) == -1) {\n        tmplVars.base += \"/\";\n      }\n      if (tmplVars.absoluteLinks) {\n        tmplVars.base = \"/\";\n      }\n      tmplVars.base = tmplVars.base.replace(/\\\\/g, '/');\n      var tmpl = env.getTemplate(source);\n      var result = tmpl.render(tmplVars);\n      grunt.file.write(dest, result);\n    });\n  });\n\n  function parseMarkdownOutput(doc) {\n    var title = (/<h1[^>]*>(.*)<\\/h1>/i).exec(doc);\n    title = title[1];\n    var body = doc.replace(/<h1[^>]*>.*<\\/h1>/i, \"\");\n    return {\n      title: title,\n      body: body\n    };\n  }\n\n  function addHeaderIds(doc) {\n    var result = [];\n    while (doc) {\n      var match = (/(<h\\d)>(.*)(<\\/h\\d>)/i).exec(doc);\n      if (! match) {\n        result.push(doc);\n        break;\n      }\n      var id = match[2];\n      id = id.toLowerCase();\n      id = id.replace(/ +/g, \"-\");\n      id = id.replace(/[^a-z0-9_\\-]/g, \"\");\n      var header = match[1] + ' id=\"' + id + '\">' + match[2] + match[3];\n      result.push(doc.substr(0, match.index));\n      result.push(header);\n      doc = doc.substr(match.index + match[0].length);\n    }\n    return result.join(\"\");\n  }\n\n  function highlight(code, lang) {\n    var hjs = require(\"highlight.js\");\n    var aliases = {\n      html: \"xml\",\n      js: \"javascript\"\n    };\n    lang = aliases[lang] || lang;\n    try {\n      if (lang) {\n        return hjs.highlight(lang, code).value;\n      } else {\n        return hjs.highlightAuto(code).value;\n      }\n    } catch (e) {\n      grunt.fail.fatal(\"Error highlighting: \" + e);\n      throw e;\n    }\n  }\n\n  marked.setOptions({highlight: highlight});\n\n  grunt.registerTask(\"rendermd\", \"Render the site Markdown files\", function () {\n    var env = new nunjucks.Environment(new nunjucks.FileSystemLoader(\"site/\"));\n    var sources = grunt.file.expand({cwd: \"site/\"}, \"**/*.md\", \"!**/README.md\");\n    sources.forEach(function (source) {\n      var basename = source.replace(/\\.md$/, \"\");\n      var dest = grunt.option(\"dest\") + \"/\" + basename + \".html\";\n      grunt.log.writeln(\"Rendering \" + source.cyan + \" to \" + dest.cyan);\n      var data = grunt.file.read(\"site/\" + source);\n      var templateName = \"generic-markdown.tmpl\";\n      var match = (/template:\\s*([a-zA-Z_\\-0-9.]*)/).exec(data);\n      if (match) {\n        templateName = match[1];\n      }\n      var html = marked(data, {\n        smartypants: true\n      });\n      var parsed = parseMarkdownOutput(html);\n      parsed.body = addHeaderIds(parsed.body);\n      var tmpl = env.getTemplate(templateName);\n      var tmplVars = Object.create(vars);\n      tmplVars.markdownBody = parsed.body;\n      tmplVars.title = parsed.title;\n      tmplVars.base = path.relative(path.dirname(\"site/\" + source), \"site/\");\n      if (tmplVars.base && tmplVars.base.search(/\\/$/) == -1) {\n        tmplVars.base += \"/\";\n      }\n      tmplVars.base = tmplVars.base.replace(/\\\\/g, '/');\n      var result = tmpl.render(tmplVars);\n      grunt.file.write(dest, result);\n    });\n  });\n\n  function doccoFormat(source, sections) {\n    sections.forEach(function (section) {\n      var code = highlight(section.codeText, \"javascript\");\n      code = code.replace(/\\s+$/, '');\n      section.codeHtml = \"<div class='highlight'><pre>\" + code + \"</pre></div>\";\n      section.docsHtml = marked(section.docsText);\n    });\n  }\n\n  grunt.registerTask(\"docco\", \"Create comment-separating source code\", function () {\n    var env = new nunjucks.Environment(new nunjucks.FileSystemLoader(\"site/\"));\n    var sources = grunt.file.expand({cwd: \"togetherjs/\"}, \"*.js\");\n    sources.sort();\n    var sourceDescriptions = JSON.parse(grunt.file.read(\"togetherjs/module-descriptions.json\"));\n    var sourceList = [];\n    sources.forEach(function (source) {\n      var name = source.replace(/\\.js$/, \"\");\n      sourceList.push({\n        name: name,\n        link: source + \".html\",\n        description: marked(sourceDescriptions[name] || \"\", {smartypants: true})\n      });\n    });\n    sources.forEach(function (source) {\n      var sourceName = source.replace(/\\.js$/, \"\");\n      var dest = grunt.option(\"dest\") + \"/source/\" + source + \".html\";\n      grunt.log.writeln(\"Rendering \" + source.cyan + \" to \" + dest.cyan);\n      var code = grunt.file.read(\"togetherjs/\" + source);\n      var sections = docco.parse(source, code, {languages:{}});\n      doccoFormat(source, sections);\n      sections.forEach(function (section, i) {\n        section.index = i;\n        section.empty = section.codeText.replace(/\\s/gm, \"\") === \"\";\n      });\n      var first = marked.lexer(sections[0].docsText)[0];\n      var hasTitle = first && first.type == 'heading' && first.depth == 1;\n      var title = hasTitle ? first.text : path.basename(source, \".js\");\n      var tmpl = env.getTemplate(\"source-code.tmpl\");\n      var tmplVars = Object.create(vars);\n      tmplVars.title = title;\n      tmplVars.sections = sections;\n      tmplVars.source = source;\n      tmplVars.sourceName = sourceName;\n      tmplVars.sourceDescription = marked(sourceDescriptions[sourceName] || \"\", {smartypants: true});\n      tmplVars.base = \"../\";\n      tmplVars.sourceList = sourceList;\n      var result = tmpl.render(tmplVars);\n      grunt.file.write(dest, result);\n    });\n    var tmplVars = Object.create(vars);\n    tmplVars.title = \"TogetherJS Source Code\";\n    tmplVars.sourceList = sourceList;\n    tmplVars.base = \"../\";\n    var tmpl = env.getTemplate(\"source-code-index.tmpl\");\n    grunt.file.write(grunt.option(\"dest\") + \"/source/index.html\", tmpl.render(tmplVars));\n  });\n\n  grunt.registerTask(\"buildaddon\", \"Build the Firefox addon and move the XPI into the site\", function () {\n    var done = this.async();\n    grunt.util.spawn({\n      cmd: \"cfx\",\n      args: [\"xpi\"],\n      opts: {\n        cwd: \"addon/\"\n      }\n    }, function (error, result, code) {\n      if (error) {\n        grunt.log.error(\"Error running cfx xpi: \" + error.toString().cyan);\n        grunt.fail.fatal(\"Error creating XPI\");\n        done();\n        return;\n      }\n      var dest = path.join(grunt.option(\"dest\"), \"togetherjs.xpi\");\n      grunt.file.copy(\"addon/togetherjs.xpi\", dest);\n      grunt.log.writeln(\"Created \" + dest.cyan);\n      done();\n    });\n  });\n\n  grunt.registerTask(\"publish\", \"Publish to togetherjs.mozillalabs.com/public/\", function () {\n    if (! grunt.file.isDir(\"togetherjs.mozillalabs.com\")) {\n      grunt.log.writeln(\"Error: you must check out togetherjs.mozillalabs.com\");\n      grunt.log.writeln(\"Use:\");\n      grunt.log.writeln(\"  $ git clone -b togetherjs.mozillalabs.com git:git@github.com:mozilla/togetherjs.git togetherjs.mozillalabs.com\");\n      grunt.log.writeln(\"  $ cd togetherjs.mozillalabs.com/.git\");\n      grunt.log.writeln(\"  $ echo '[remote \\\"staging\\\"]\\n\\turl = git@heroku.com:togetherjs-staging.git\\n\\tpush = refs/heads/togetherjs.mozillalabs.com:refs/heads/master\\n[remote \\\"production\\\"]\\n\\turl = git@heroku.com:togetherjs.git\\n\\tpush = refs/heads/togetherjs.mozillalabs.com:refs/heads/master\\n' >> config\");\n      grunt.fail.fatal(\"Must checkout togetherjs.mozillalabs.com\");\n      return;\n    }\n    var versions = \"togetherjs.mozillalabs.com/public/versions\";\n    if (! grunt.file.isDir(versions)) {\n      grunt.log.writeln(\"Error: \" + versions.cyan + \" does not exist\");\n      grunt.fail.fatal(\"No versions/ directory\");\n      return;\n    }\n    var tmp = \"togetherjs.mozillalabs.com/public_versions_tmp\";\n    fs.rename(versions, tmp);\n    grunt.file.delete(\"togetherjs.mozillalabs.com/public\");\n    grunt.file.mkdir(\"togetherjs.mozillalabs.com/public\");\n    fs.rename(tmp, versions);\n    if (! grunt.option(\"base-url\")) {\n      grunt.option(\"base-url\", \"https://togetherjs.com\");\n    }\n    grunt.option(\"dest\", \"togetherjs.mozillalabs.com/public\");\n    grunt.option(\"exclude-tests\", true);\n    grunt.option(\"no-hardlink\", true);\n    grunt.task.run([\"build\", \"buildsite\", \"buildaddon\"]);\n    grunt.task.run([\"movecss\"]);\n    grunt.log.writeln(\"To actually publish you must do:\");\n    grunt.log.writeln(\"  $ cd togetherjs.mozillalabs.com/\");\n    grunt.log.writeln(\"  $ git add -A\");\n    grunt.log.writeln(\"  $ git commit -a -m 'Publish'\");\n    grunt.log.writeln(\"  $ git push && git push staging\");\n  });\n\n  grunt.registerTask(\"publishversion\", \"Publish to togetherjs.mozillalabs.com/public/versions/\", function () {\n    var version = grunt.option(\"togetherjs-version\");\n    if (! version) {\n      grunt.log.error(\"You must provide a --togetherjs-version=X.Y argument\");\n      grunt.fail.fatal(\"No --togetherjs-version\");\n      return;\n    }\n    if (! grunt.file.isDir(\"togetherjs.mozillalabs.com/public/versions\")) {\n      grunt.log.error(\"The directory togetherjs.mozillalabs.com/public/versions does not exist\");\n      grunt.fail.fatal();\n      return;\n    }\n    var destDir = \"togetherjs.mozillalabs.com/public/versions/\" + version;\n    if (grunt.file.exists(destDir)) {\n      grunt.log.error(\"The directory \" + destDir + \" already exists\");\n      grunt.log.error(\"  Delete it first to re-create version\");\n      grunt.fail.fatal();\n      return;\n    }\n    grunt.option(\"base-url\", \"https://togetherjs.com/versions/\" + version);\n    grunt.option(\"dest\", destDir);\n    grunt.option(\"exclude-tests\", true);\n    grunt.option(\"no-hardlink\", true);\n    grunt.task.run([\"build\"]);\n    grunt.task.run([\"movecss\"]);\n    var readme = grunt.file.read(\"togetherjs.mozillalabs.com/public/versions/README.md\");\n    readme += \"  * [\" + version + \"](./\" + version + \"/togetherjs.js)\\n\";\n    grunt.file.write(\"togetherjs.mozillalabs.com/public/versions/README.md\", readme);\n  });\n\n  grunt.registerTask(\"movecss\", \"Publish generated css files to dest\", function () {\n    // Can't figure out how to parameterize the less task, hence this lame move\n    [\"togetherjs/togetherjs.css\", \"togetherjs/recorder.css\"].forEach(function (css) {\n      var src = path.join(\"build\", css);\n      var dest = path.join(grunt.option(\"dest\"), css);\n      grunt.file.copy(src, dest);\n      grunt.log.writeln(\"Copying \" + src.cyan + \" to \" + dest.cyan);\n    });\n  });\n\n  grunt.loadNpmTasks('grunt-contrib-watch');\n\n  grunt.registerTask('dev', function() {\n    grunt.util.spawn({\n      cmd: 'node',\n      args: ['devserver.js']\n    });\n    grunt.task.run('watch');\n  });\n\n  grunt.registerTask(\"test\", \"Run jshint and test suite\", [\"jshint\", \"phantom\"]);\n  grunt.loadNpmTasks('grunt-http-server');\n\n  grunt.registerTask(\"phantom\", [\"phantom-setup\", \"phantom-tests\"]);\n\n  grunt.registerTask(\"phantom-setup\", \"Run jdoctest test suite in phantomjs\",\n    function() {\n      var done = this.async();\n      // find unused ports for web server and hub\n      var freeport = require(\"freeport\");\n      freeport(function(err1, hubPort) {\n        freeport(function(err2, webPort) {\n          if (err1 || err2) { return done(err1 || err2); }\n\n          // build togetherjs using these default ports\n          grunt.option(\"base-url\", \"http://localhost:\"+webPort+\"/\"+TESTDIR+\"/\");\n          grunt.option(\"hub-url\", \"http://localhost:\"+hubPort);\n          grunt.option(\"no-hardlink\", true);\n          grunt.option(\"dest\", TESTDIR);\n          // make sure the web server will use the right port\n          grunt.config.merge({\n            'http-server': {\n              test: {\n                port: webPort,\n                host: \"localhost\"\n              }\n            }\n          });\n          // spawn a hub, using the hub port\n          var hub = require(\"./hub/server\");\n          hub.startServer(hubPort, \"localhost\");\n          // build & start the web server\n          grunt.task.run(\"build\", \"http-server:test\");\n          // ok, now we can run the tests in phantomjs!\n          done();\n        });\n      });\n    });\n\n  // PhantomJS event handlers\n  var phantomjs = require(\"grunt-lib-phantomjs\").init(grunt);\n  var phantomStatus;\n\n  phantomjs.on('fail.load', function(url) {\n    phantomjs.halt();\n    grunt.verbose.write('Running PhantomJS...').or.write('...');\n    grunt.log.error('PhantomJS unable to load \"' + url + '\" URI.');\n    phantomStatus.failed += 1;\n    phantomStatus.total += 1;\n  });\n\n  phantomjs.on('fail.timeout', function() {\n    phantomjs.halt();\n    grunt.log.writeln();\n    grunt.log.error('PhantomJS timed out.');\n    phantomStatus.failed += 1;\n    phantomStatus.total += 1;\n  });\n\n  phantomjs.on('doctestjs.pass', function(result) {\n    phantomStatus.total += 1;\n    grunt.verbose.ok(\"Passed: \"+result.example.summary);\n  });\n\n  phantomjs.on('doctestjs.fail', function(result) {\n    phantomStatus.failed += 1;\n    phantomStatus.total += 1;\n    grunt.log.error(\"Failed: \"+result.example.expr);\n    grunt.log.subhead(\"Expected:\");\n    grunt.log.writeln(result.example.expected);\n    grunt.log.subhead(\"Got:\");\n    grunt.log.writeln(result.got);\n  });\n\n  phantomjs.on('doctestjs.end', function() {\n    phantomjs.halt();\n  });\n\n  // Pass through console.log statements (when verbose)\n  phantomjs.on('console', grunt.verbose.writeln);\n\n  grunt.registerMultiTask(\"phantom-tests\", function() {\n    grunt.task.requires('phantom-setup');\n    var url = grunt.option('base-url') +\n      \"togetherjs/tests/index.html?name=\" + this.target;\n    grunt.verbose.writeln(\"Running tests at: \"+url);\n\n    // Merge task-specific and/or target-specific options with these defaults.\n    var options = this.options({\n      // PhantomJS timeout, in ms.\n      timeout: 10000,\n      // JDoctest-PhantomJS bridge file to be injected.\n      inject: path.join(__dirname, 'phantomjs', 'bridge.js'),\n      //screenshot: true,\n      page: {\n        // leave room for the togetherjs sidebar\n        viewportSize: { width: 1024, height: 1024 }\n      }\n    });\n\n    // Reset test status\n    phantomStatus = {failed: 0, passed: 0, total: 0, start: Date.now()};\n\n    // Start phantomjs on this URL\n    var done = this.async();\n    phantomjs.spawn(url, {\n      options: options,\n      done: function() {\n        var duration = Date.now() - phantomStatus.start;\n        // Log results.\n        if (phantomStatus.failed > 0) {\n          grunt.warn(phantomStatus.failed + '/' + phantomStatus.total +\n                     ' assertions failed (' + duration + 'ms)');\n        } else if (phantomStatus.total === 0) {\n          grunt.warn('0/0 assertions ran (' + duration + 'ms)');\n        } else {\n          grunt.verbose.writeln();\n          grunt.log.ok(phantomStatus.total + ' assertions passed (' + duration + 'ms)');\n        }\n        // All done!\n        done();\n      }\n    });\n  });\n\n  grunt.registerTask('default', 'start');\n\n};\n"
  },
  {
    "path": "LICENSE.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\" />\n  <meta name=\"generator\" content=\"pandoc\" />\n  <title>Mozilla Public License, version 2.0</title>\n  <!--[if lt IE 9]>\n    <script src=\"http://html5shim.googlecode.com/svn/trunk/html5.js\"></script>\n  <![endif]-->\n\n  <link href='http://fonts.googleapis.com/css?family=Crimson+Text' rel='stylesheet' type='text/css'>\n  <link href='http://fonts.googleapis.com/css?family=Lora' rel='stylesheet' type='text/css'>\n  <link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css'>\n\n  <style type=\"text/css\">\n\tbody { \tfont-family: 'Crimson Text', serif; \n\t\tmax-width: 30em; \n\t\tmargin-left:auto;\n\t\tmargin-right:auto;\n\t\ttext-align: justify;\n\t\t-moz-hyphens: auto;\n\t\tfont-size: 110%\n\t\t}\n\n\th1, h2, h3 { \n\t\tfont-family: 'Lora', serif;\n\t     \tfont-variant: small-caps;\n\t\t}\n\n\th1 { \n\t\ttext-align: center;\n\t\t-moz-hyphens: none;\n\t\tfont-size: 160%;\n\t\t}\n\th2 {\n\t\tfont-size: 140%;\n\t\t-moz-hyphens: none;\n\t\ttext-align: left;\n\t\t}\n\th3 {\t\n\t\tfont-size: 120%;\n\t\t-moz-hyphens: none;\n\t\ttext-align: left;\t\t\n\t\t}\n\n\tblockquote { \t\n\t\tfont-family: 'Droid Sans Mono', mono;\n\t\ttext-align: left; \n\t\t-moz-hyphens: none;\n\t\t}\n\t\n\tcode {\n\t\tfont-family: 'Droid Sans Mono', mono;\n\t\t}\n\n\tem {\n\t\tbackground: #FEFD80;\n\t\tborder: 30px solid #FEFD80;\n\t\tfloat: left;\n\t\tline-height: 1.25em;\n    \t\tmargin-left: 10px;\n\t\tmargin-right: 10px;\n\t\tmargin-bottom: 10px;\n\t\tmargin-top:-10px;\n/*\t\ttext-transform: uppercase; */\n\t\tfont-style: normal;\n\t}\n\n\tdt {\tfont-family: 'Lora', serif;\n\t\tfont-weight: bold; \n\t\tfont-size: 100%;\n\t\t}\n\n  </style>\n</head>\n<body>\n<h1 id=\"mozilla-public-license-version-2.0\">Mozilla Public License<br>Version 2.0</h1>\n<h2 id=\"definitions\">1. Definitions</h2>\n<dl>\n<dt>1.1. “Contributor”</dt>\n<dd><p>means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software.</p>\n</dd>\n<dt>1.2. “Contributor Version”</dt>\n<dd><p>means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor’s Contribution.</p>\n</dd>\n<dt>1.3. “Contribution”</dt>\n<dd><p>means Covered Software of a particular Contributor.</p>\n</dd>\n<dt>1.4. “Covered Software”</dt>\n<dd><p>means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof.</p>\n</dd>\n<dt>1.5. “Incompatible With Secondary Licenses”</dt>\n<dd><p>means</p>\n<ol type=\"a\">\n<li><p>that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or</p></li>\n<li><p>that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License.</p></li>\n</ol>\n</dd>\n<dt>1.6. “Executable Form”</dt>\n<dd><p>means any form of the work other than Source Code Form.</p>\n</dd>\n<dt>1.7. “Larger Work”</dt>\n<dd><p>means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software.</p>\n</dd>\n<dt>1.8. “License”</dt>\n<dd><p>means this document.</p>\n</dd>\n<dt>1.9. “Licensable”</dt>\n<dd><p>means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License.</p>\n</dd>\n<dt>1.10. “Modifications”</dt>\n<dd><p>means any of the following:</p>\n<ol type=\"a\">\n<li><p>any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or</p></li>\n<li><p>any new file in Source Code Form that contains any Covered Software.</p></li>\n</ol>\n</dd>\n<dt>1.11. “Patent Claims” of a Contributor</dt>\n<dd><p>means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version.</p>\n</dd>\n<dt>1.12. “Secondary License”</dt>\n<dd><p>means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses.</p>\n</dd>\n<dt>1.13. “Source Code Form”</dt>\n<dd><p>means the form of the work preferred for making modifications.</p>\n</dd>\n<dt>1.14. “You” (or “Your”)</dt>\n<dd><p>means an individual or a legal entity exercising rights under this License. For legal entities, “You” includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, “control” means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.</p>\n</dd>\n</dl>\n<h2 id=\"license-grants-and-conditions\">2. License Grants and Conditions</h2>\n<h3 id=\"grants\">2.1. Grants</h3>\n<p>Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license:</p>\n<ol type=\"a\">\n<li><p>under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and</p></li>\n<li><p>under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version.</p></li>\n</ol>\n<h3 id=\"effective-date\">2.2. Effective Date</h3>\n<p>The licenses granted in Section&nbsp;2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution.</p>\n<h3 id=\"limitations-on-grant-scope\">2.3. Limitations on Grant Scope</h3>\n<p>The licenses granted in this Section&nbsp;2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section&nbsp;2.1(b) above, no patent license is granted by a Contributor:</p>\n<ol type=\"a\">\n<li><p>for any code that a Contributor has removed from Covered Software; or</p></li>\n<li><p>for infringements caused by: (i) Your and any other third party’s modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or</p></li>\n<li><p>under Patent Claims infringed by Covered Software in the absence of its Contributions.</p></li>\n</ol>\n<p>This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section&nbsp;3.4).</p>\n<h3 id=\"subsequent-licenses\">2.4. Subsequent Licenses</h3>\n<p>No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section&nbsp;10.2) or under the terms of a Secondary License (if permitted under the terms of Section&nbsp;3.3).</p>\n<h3 id=\"representation\">2.5. Representation</h3>\n<p>Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License.</p>\n<h3 id=\"fair-use\">2.6. Fair Use</h3>\n<p>This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents.</p>\n<h3 id=\"conditions\">2.7. Conditions</h3>\n<p>Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section&nbsp;2.1.</p>\n<h2 id=\"responsibilities\">3. Responsibilities</h2>\n<h3 id=\"distribution-of-source-form\">3.1. Distribution of Source Form</h3>\n<p>All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients’ rights in the Source Code Form.</p>\n<h3 id=\"distribution-of-executable-form\">3.2. Distribution of Executable Form</h3>\n<p>If You distribute Covered Software in Executable Form then:</p>\n<ol type=\"a\">\n<li><p>such Covered Software must also be made available in Source Code Form, as described in Section&nbsp;3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and</p></li>\n<li><p>You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients’ rights in the Source Code Form under this License.</p></li>\n</ol>\n<h3 id=\"distribution-of-a-larger-work\">3.3. Distribution of a Larger Work</h3>\n<p>You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s).</p>\n<h3 id=\"notices\">3.4. Notices</h3>\n<p>You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies.</p>\n<h3 id=\"application-of-additional-terms\">3.5. Application of Additional Terms</h3>\n<p>You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction.</p>\n<h2 id=\"inability-to-comply-due-to-statute-or-regulation\">4. Inability to Comply Due to Statute or Regulation</h2>\n<p>If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.</p>\n<h2 id=\"termination\">5. Termination</h2>\n<p>5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice.</p>\n<p>5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section&nbsp;2.1 of this License shall terminate.</p>\n<p>5.3. In the event of termination under Sections&nbsp;5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination.</p>\n<h2 id=\"disclaimer-of-warranty\">6. Disclaimer of Warranty</h2>\n<p><em>Covered Software is provided under this License on an “as is” basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer.</em></p>\n<h2 id=\"limitation-of-liability\">7. Limitation of Liability</h2>\n<p><em>Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party’s negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You.</em></p>\n<h2 id=\"litigation\">8. Litigation</h2>\n<p>Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party’s ability to bring cross-claims or counter-claims.</p>\n<h2 id=\"miscellaneous\">9. Miscellaneous</h2>\n<p>This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor.</p>\n<h2 id=\"versions-of-the-license\">10. Versions of the License</h2>\n<h3 id=\"new-versions\">10.1. New Versions</h3>\n<p>Mozilla Foundation is the license steward. Except as provided in Section&nbsp;10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number.</p>\n<h3 id=\"effect-of-new-versions\">10.2. Effect of New Versions</h3>\n<p>You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward.</p>\n<h3 id=\"modified-versions\">10.3. Modified Versions</h3>\n<p>If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License).</p>\n<h3 id=\"distributing-source-code-form-that-is-incompatible-with-secondary-licenses\">10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses</h3>\n<p>If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached.</p>\n<h2 id=\"exhibit-a---source-code-form-license-notice\">Exhibit A - Source Code Form License Notice</h2>\n<blockquote>\n<p>This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.</p>\n</blockquote>\n<p>If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice.</p>\n<p>You may add additional accurate notices of copyright ownership.</p>\n<h2 id=\"exhibit-b---incompatible-with-secondary-licenses-notice\">Exhibit B - “Incompatible With Secondary Licenses” Notice</h2>\n<blockquote>\n<p>This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.</p>\n</blockquote>\n</body>\n</html>\n"
  },
  {
    "path": "Procfile",
    "content": "web: node hub/server.js\n"
  },
  {
    "path": "README.md",
    "content": "TogetherJS - Surprisingly easy collaboration\n============================================\n\nWhat is TogetherJS?\n-----------------\n\nTogetherJS is a service for your website that makes it surprisingly easy to collaborate in real-time.\n\nUsing TogetherJS two people can interact on the same page, seeing each other's cursors, edits, and browsing a site together.  The TogetherJS service is included by the web site owner, and a web site can customize and configure aspects of TogetherJS's behavior on the site.\n\nFor more information and to see TogetherJS in action, visit [togetherjs.com](https://togetherjs.com/)\n\nIf you want to integrate TogetherJS onto your site see [the wiki](https://github.com/mozilla/togetherjs/wiki) and specifically [Getting Started](https://github.com/mozilla/togetherjs/wiki/Developers:-Getting-Started).\n\nContributing\n============\n\nThe remainder of this document is about contributing to TogetherJS - but reports, fixes, features, etc.  Look back at those other links if you are looking for something else.\n\nBug Reports\n-----------\n\nPlease submit bug reports as [github issues](https://github.com/mozilla/togetherjs/issues/new).  Don't worry about labels or milestones.  If you use the in-app feedback to give us a bug report that's fine too.\n\nRoadmap & Plans\n---------------\n\nTo see what we're planning or at least considering to do with TogetherJS, look at [see our bug tracker](https://github.com/mozilla/togetherjs/issues?state=open).\n\nSetting up a development environment\n------------------------------------\n\nTogetherJS has two main pieces:\n\n* The [server](https://github.com/mozilla/togetherjs/blob/develop/hub/server.js), which echos messages back and forth between users.  The server doesn't do much, you may gaze upon its incredibly boring [history](https://github.com/mozilla/togetherjs/commits/develop/hub/server.js).\n\n* The client in [`togetherjs/`](https://github.com/mozilla/togetherjs/tree/develop/togetherjs) which does all the real work.\n\nThere is a TogetherJS hub server deployed at `https://hub.togetherjs.com` - and there's little need for other server deployments.  If you want to try TogetherJS out we recommend you use our hub server.  Note if you include TogetherJS on an https site, you must use an https hub server.\n\nThe files need to be lightly \"built\": we use [LESS](http://lesscss.org/) for styles, and a couple files are generated.  To develop you need to build the library using [Grunt](http://gruntjs.com/).\n\nTo build a copy of the library, check out TogetherJS:\n\n```sh\n$ git clone git://github.com/mozilla/togetherjs.git\n$ cd togetherjs\n```\n\nThen [install npm](http://nodejs.org/download/) and run:\n\n```sh\n$ npm install\n$ npm install -g grunt-cli\n```\n\nThis will install a bunch of stuff, most of which is only used for development.  The only \"server\" dependency is [WebSocket-Node](https://github.com/Worlize/WebSocket-Node) (and if you use our hub then you don't need to worry about the server).  By default everything is installed locally, i.e., in `node_modules/`.  This works just fine, but it is useful to install the `grunt` command-line program globally, which `npm install -g grunt-cli` does.\n\nNow you can build TogetherJS, like:\n\n```sh\n$ grunt build buildsite --no-hardlink\n```\n\nThis will create a copy of the entire `togetherjs.com` site in `build/`.  You'll need to setup a local web server of your own pointed to the `build/` directory. To start a server on port 8080, run:\n\n```sh\n$ node devserver.js\n```\n\nIf you want to develop with TogetherJS you probably want the files built continually.  To do this use:\n\n```sh\n$ grunt devwatch\n```\n\nThis will rebuild when changes are detected.  Note that Grunt is configured to create [hard links](http://en.wikipedia.org/wiki/Hard_link) instead of copying so that most changes you make to files in `togetherjs/` don't need to be rebuilt to show up in `build/togetherjs/`.  `--no-hardlink` turns this behavior off.\n\nYou may wish to create a static copy of the TogetherJS client to distribute and use on your website.  To do this run:\n\n```sh\n$ grunt build --base-url https://myapp.com --no-hardlink --dest static-myapp\n```\n\nThen `static-myapp/togetherjs.js` and `static-myapp/togetherjs-min.js` will be in place, and the rest of the code will be under `static-myapp/togetherjs/`.  You would deploy these on your server.\n\nRunning a local server\n----------------------\nYou shouldn't need to run your own version of the hub server.  But if you\nhappen to make changes to the server, you can change the default hub\nURL by setting the HUB_URL environment variable when building.  For example:\n```\n$ HUB_URL=http://localhost:8080 grunt devwatch\n```\n\nTesting\n-------\n\nTests are in `togetherjs/tests/` -- these are [doctest.js](http://doctestjs.org/) tests.  To actually run the tests build togetherjs, serve it up, and go to `http://localhost:PORT/togetherjs/tests/` -- from there the tests are linked to from the top of the page.  The actual tests are `*.js` files in `togetherjs/tests/`, generally `test_*.js` for unit-style tests, and `func_*.js` for functional tests.\n\nThe \"Manual testing\" link is something that lets you simulate different conditions in TogetherJS without setting up a second browser/client.\n\nThere is unfortunately no automated runner for these tests.  It might be nice if [Karma](http://karma-runner.github.io/) could be setup with doctest.js in general, but so far that isn't done.\n\nLicense\n-------\n\nThis 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 file,\nYou can obtain one at [http://mozilla.org/MPL/2.0/](http://mozilla.org/MPL/2.0/).\n"
  },
  {
    "path": "addon/.gitignore",
    "content": "Profile*"
  },
  {
    "path": "addon/Procfile",
    "content": "profilea: cfx run --binary /Applications/FirefoxNightly.app -p ProfileA \nprofileb: sleep 1; cfx run --binary /Applications/FirefoxNightly.app -p ProfileB \n"
  },
  {
    "path": "addon/README.md",
    "content": "The Firefox Addon simply adds togetherjs.js to a window - when you turn\nit on the tab gets togetherjs for that one tab, and when you turn it off\nit stops.\n"
  },
  {
    "path": "addon/data/attachment.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\nself.port.on(\"Config\", function (config) {\n  var doc = unsafeWindow.document;\n  unsafeWindow._TogetherJSBookmarklet = true;\n  unsafeWindow.TogetherJSConfig_hubBase = config.hubBase;\n  if (config.shareId) {\n    unsafeWindow._TogetherJSShareId = config.shareId;\n  }\n  var script = doc.createElement(\"script\");\n  script.src = config.url;\n  console.log(\"Attaching:\", script.outerHTML, \"to:\", window.location.href);\n  doc.head.appendChild(script);\n});\n\n// FIXME: need to bind to session.on(\"close\") and emit this:\n// self.port.emit(\"Close\");\n"
  },
  {
    "path": "addon/data/button.html",
    "content": "<div>\n  <a id=\"togetherjs-button\" href=\"#\">togetherjs</span>\n</div>\n"
  },
  {
    "path": "addon/data/button.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\nself.port.on(\"TogetherJSOn\", function () {\n  document.getElementById(\"togetherjs-button\").innerHTML = \"truckin'\";\n});\n\nself.port.on(\"TogetherJSOff\", function () {\n  document.getElementById(\"togetherjs-button\").innerHTML = \"togetherjs\";\n});\n"
  },
  {
    "path": "addon/data/startup-help.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Welcome to TogetherJS</title>\n  </head>\n  <body>\n\n<p>Thanks for checking out TogetherJS.</p>\n\n<p>You should see a link/button at the bottom right of the\nbrowser: <span style=\"text-decoration: underline; color:\n#00f\">togetherjs</span> &mdash; if you don't then you need to show the\nAdd-on Bar:</p>\n\n<p>Go to <strong>View &gt; Toolbars &gt; Add-on bar</strong> to\ndisplay the bar\n(or <a href=\"http://support.mozilla.org/en-US/kb/add-on-bar-quick-access-to-add-ons\">read\nmore here</a>).</p>\n\n<p>Once you see the button, click it to start sharing your session.\nOnce you are sharing you have to tell someone else (more instructions\nhere) </p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "addon/lib/main.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\nconst widgets = require(\"widget\");\nconst data = require(\"self\").data;\nconst tabs = require(\"tabs\");\nconst { StartupPanel } = require(\"./startup-panel\");\nconst { Page } = require(\"page-worker\");\nconst simplePrefs = require('simple-prefs');\n\nvar button = widgets.Widget({\n  id: \"togetherjs-starter\",\n  label: \"Start TogetherJS\",\n  contentURL: data.url(\"button.html\"),\n  contentScriptFile: data.url(\"button.js\"),\n  onClick: function () {\n    console.log(\"Starting TogetherJS because of click\");\n    startTogetherJS();\n  },\n  width: 48\n});\n\nStartupPanel({\n  name: \"TogetherJS\",\n  contentURL: data.url(\"startup-help.html\")\n});\n\nvar autoDomains = [];\nfunction updateAutoDomains() {\n  var domains = simplePrefs.prefs.autoDomains;\n  domains = domains.split(/,/g);\n  autoDomains = [];\n  domains.forEach(function (item) {\n    if (item.search(/^\\s*$/) === 0) {\n      return;\n    }\n    item = item.replace(/^\\s+/, \"\").replace(/\\s+$/, \"\");\n    item = item.split(/;/);\n    var domain = item[0];\n    var shareId = item[1] || null;\n    if (domain.indexOf(\"//\") == -1) {\n      // Just a plain domain\n      domain = \"^https?:\\\\/\\\\/\" + domain;\n    }\n    domain = new RegExp(domain, \"i\");\n    autoDomains.push({domain: domain, shareId: shareId});\n  });\n}\nsimplePrefs.on(\"autoDomains\", updateAutoDomains);\nupdateAutoDomains();\n\n\nfunction startTogetherJS(shareId) {\n  var tab = tabs.activeTab;\n  if (tab.togetherjsCloser) {\n    tab.togetherjsCloser();\n    return;\n  }\n  tab.togetherjsCloser = function () {\n    tab.togetherjsCloser = null;\n    button.port.emit(\"TogetherJSOff\");\n    tab.removeListener(\"ready\", attachWorker);\n  };\n  var worker;\n  function attachWorker() {\n    worker = tab.attach({\n      contentScriptFile: [\n        data.url(\"attachment.js\")\n      ]\n    });\n    worker.port.on(\"Close\", function () {\n      tab.togetherjsCloser();\n    });\n    worker.port.emit(\"Config\", {url: simplePrefs.prefs.togetherjsJs, hubBase: simplePrefs.prefs.hubBase, shareId: shareId || null});\n  }\n  button.port.emit(\"TogetherJSOn\");\n  tab.on(\"ready\", attachWorker);\n  attachWorker();\n}\n// Need poll for back button code\n\ntabs.on(\"open\", watchTab);\n\nfunction watchTab(tab) {\n  tab.on(\"ready\", function () {\n    if (tabs.activeTab == tab && tab.url.indexOf(\"#&togetherjs\") != -1) {\n      console.log(\"Starting TogetherJS on share link\", tab.url);\n      startTogetherJS();\n    }\n    if (tabs.activeTab == tab && ! tab.togetherjsCloser) {\n      var started = false;\n      autoDomains.forEach(function (matcher) {\n        console.log(\"matcher\", matcher, matcher.domain);\n        if ((! started) && tab.url.search(matcher.domain) != -1) {\n          console.log(\"Start TogetherJS autoDomain\");\n          startTogetherJS(matcher.shareId);\n          started = true;\n        }\n      });\n    }\n  });\n}\n\nfor (var i=0; i<tabs.length; i++) {\n  watchTab(tabs[i]);\n}\n\ntabs.on(\"activate\", function () {\n  if (tabs.activeTab.togetherjsCloser) {\n    button.port.emit(\"TogetherJSOn\");\n  } else {\n    button.port.emit(\"TogetherJSOff\");\n  }\n});\n"
  },
  {
    "path": "addon/lib/startup-panel.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// Shows a panel (typically describing the addon) the first time an addon is installed.\n\nconst { Panel } = require(\"panel\");\nconst ss = require(\"simple-storage\");\nconst { setTimeout } = require(\"timers\");\nconst { publicConstructor } = require(\"api-utils\");\nconst { env } = require('api-utils/environment');\nconst self = require(\"self\");\n\n// Show panel 1 second after startup:\nvar DEFAULT_TIMEOUT = 1000;\n\nfunction StartupPanel(options) {\n  this.name = options.name;\n  if (! this.name) {\n    throw 'You must give the panel a name';\n  }\n  options.width = options.width || 400;\n  options.height = options.height || 400;\n  // FIXME: should append this if necessary:\n  options.contentScript = SCRIPT;\n  this.options = options;\n  var seen = ss.storage[this.name + '-seen'];\n  if (env.SHOW_STARTUP_PANEL) {\n    // Primarily for development/testing\n    seen = false;\n  }\n  if (self.loadReason == \"install\" || self.loadReason == \"enable\") {\n    // Re-installed or re-enabled:\n    seen = false;\n  }\n  if (! seen) {\n    setTimeout(this.display.bind(this), options.startupTimeout || DEFAULT_TIMEOUT);\n  }\n};\n\nStartupPanel.prototype = {\n  display: function () {\n    this.panel = Panel(this.options);\n    this.panel.on(\"hide\", (function () {\n      ss.storage[this.name + '-seen'] = true;\n    }).bind(this));\n    this.panel.port.on(\"Close\", (function () {\n      this.panel.hide();\n    }).bind(this));\n    this.panel.show();\n  }\n};\n\nvar SCRIPT = [\n'window.addEventListener(\"load\", function () {',\n'  var el = document.getElementById(\"close\");',\n'  if (! el) {',\n'    el = document.createElement(\"A\");',\n'    el.innerHTML = \"&times;\";',\n'    el.href = \"#\";',\n'    el.setAttribute(\"style\", \"position: absolute; font-weight: bold; top: 2px; right: 6px; text-decoration: none; color: #000;\");',\n'    document.body.appendChild(el);',\n'  }',\n'  el.addEventListener(\"click\", function () {',\n'    self.port.emit(\"Close\");',\n'  }, false);',\n'}, false);'\n].join(\"\\n\");\n\nexports.StartupPanel = publicConstructor(StartupPanel);\n"
  },
  {
    "path": "addon/package.json",
    "content": "{\n    \"preferences\": [\n        {\n            \"title\": \"togetherjs.js location\", \n            \"type\": \"string\", \n            \"description\": \"This is where to find the script to inject\", \n            \"value\": \"https://togetherjs.com/togetherjs.js\", \n            \"name\": \"togetherjsJs\"\n        }, \n        {\n            \"title\": \"Hub URL\", \n            \"type\": \"string\", \n            \"description\": \"Override the location of the hub\", \n            \"value\": \"https://hub.togetherjs.com\", \n            \"name\": \"hubBase\"\n        }, \n        {\n            \"title\": \"Auto domains\", \n            \"type\": \"string\", \n            \"description\": \"Domains on which to automatically start TogetherJS (comma-separated)\", \n            \"value\": \"\", \n            \"name\": \"autoDomains\"\n        }\n    ], \n    \"license\": \"MPL 2.0\", \n    \"author\": \"\", \n    \"description\": \"Runs TogetherJS\", \n    \"version\": \"0.1\", \n    \"fullName\": \"TogetherJS\", \n    \"id\": \"jid1-9cBzV13kcAXp8A\", \n    \"name\": \"togetherjs\"\n}\n"
  },
  {
    "path": "client",
    "content": ""
  },
  {
    "path": "devserver.js",
    "content": "var\nhttp = require(\"http\"),\nurl  = require(\"url\"),\npath = require(\"path\"),\nfs   = require(\"fs\"),\nport = process.argv[2] || process.env['PORT'] || 8080;\n\nhttp.createServer(function(request, response) {\n\n  var uri = url.parse(request.url).pathname\n  var filename = path.join(process.cwd(), 'build', uri);\n\n  fs.exists(filename, function(exists) {\n    if(!exists) {\n      response.writeHead(404, {\"Content-Type\": \"text/plain\"});\n      response.write(\"404 Not Found\\n\");\n      response.end();\n      return;\n    }\n\n    if (fs.statSync(filename).isDirectory()) filename += '/index.html';\n\n    fs.readFile(filename, \"binary\", function(err, file) {\n      if(err) {\n        response.writeHead(500, {\"Content-Type\": \"text/plain\"});\n        response.write(err + \"\\n\");\n        response.end();\n        return;\n      }\n\n      response.writeHead(200);\n      response.write(file, \"binary\");\n      response.end();\n    });\n  });\n}).listen(parseInt(port, 10));\n\nconsole.log(\"Static file server running at\\n  => http://localhost:\" + port + \"/\\nCTRL + C to shutdown\");\n"
  },
  {
    "path": "hub/server.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// New Relic Server monitoring support\nif ( process.env.NEW_RELIC_HOME ) {\n  require(\"newrelic\");\n}\n\nvar SAMPLE_STATS_INTERVAL = 60*1000; // 1 minute\nvar SAMPLE_LOAD_INTERVAL = 5*60*1000; // 5 minutes\nvar EMPTY_ROOM_LOG_TIMEOUT = 3*60*1000; // 3 minutes\nvar WEBSOCKET_COMPAT = true;\n\nvar WebSocketServer = WEBSOCKET_COMPAT ?\n  require(\"./websocket-compat\").server :\n  require(\"websocket\").server;\nvar http = require('http');\nvar parseUrl = require('url').parse;\nvar fs = require('fs');\n\n// FIXME: not sure what logger to use\n//var logger = require('../../lib/logger');\n\n// LOG_LEVEL values:\n// 0: show everything (including debug)\n// 1: don't show debug, do show logger.log\n// 2: don't show logger.log and debug, do show logger.info (and STATS)\n// 3: don't show info, do show warn\n// 4: don't show warn, do show error\n// 5: don't show anything\n// Stats are at level 2\n\nvar thisSource = \"// What follows is the source for the server.\\n\" +\n    \"// Obviously we can't prove this is the actual source, but if it isn't then we're \\n\" +\n    \"// a bunch of lying liars, so at least you have us on record.\\n\\n\" +\n    fs.readFileSync(__filename);\n\nvar Logger = function (level, filename, stdout) {\n  this.level = level;\n  this.filename = filename;\n  this.stdout = !!stdout;\n  this._open();\n  process.on(\"SIGUSR2\", (function () {\n    this._open();\n  }).bind(this));\n};\n\nLogger.prototype = {\n\n  write: function () {\n    if (this.stdout) {\n      console.log.apply(console, arguments);\n    }\n    if (this.file) {\n      var s = [];\n      for (var i=0; i<arguments.length; i++) {\n        var a = arguments[i];\n        if (typeof a == \"string\") {\n          s.push(a);\n        } else {\n          s.push(JSON.stringify(a));\n        }\n      }\n      s = s.join(\" \") + \"\\n\";\n      this.file.write(this.date() + \" \" + s);\n    }\n  },\n\n  date: function () {\n    return (new Date()).toISOString();\n  },\n\n  _open: function () {\n    if (this.file) {\n      this.file.end(this.date() + \" Logs rotating\\n\");\n      this.file = null;\n    }\n    if (this.filename) {\n      this.file = fs.createWriteStream(this.filename, {flags: 'a', mode: parseInt('644', 8), encoding: \"UTF-8\"});\n    }\n  }\n\n};\n\n[[\"error\", 4], [\"warn\", 3], [\"info\", 2], [\"log\", 1], [\"debug\", 0]].forEach(function (nameLevel) {\n  var name = nameLevel[0];\n  var level = nameLevel[1];\n  Logger.prototype[name] = function () {\n    if (logLevel <= level) {\n      if (name != \"log\") {\n        this.write.apply(this, [name.toUpperCase()].concat(Array.prototype.slice.call(arguments)));\n      } else {\n        this.write.apply(this, arguments);\n      }\n    }\n  };\n});\n\nvar logger = new Logger(0, null, true);\n\nvar server = http.createServer(function(request, response) {\n  var url = parseUrl(request.url, true);\n  var protocol = request.headers[\"forwarded-proto\"] || \"http:\";\n  var host = request.headers.host;\n  var base = protocol + \"//\" + host;\n\n  if (url.pathname == '/status') {\n    response.end(\"OK\");\n  } else if (url.pathname == '/load') {\n    var load = getLoad();\n    response.writeHead(200, {\"Content-Type\": \"text/plain\"});\n    response.end(\"OK \" + load.connections + \" connections \" +\n                 load.sessions + \" sessions; \" +\n                 load.solo + \" are single-user and \" +\n                 (load.sessions - load.solo) + \" active sessions\");\n  } else if (url.pathname == '/server-source') {\n    response.writeHead(200, {\"Content-Type\": \"text/plain\"});\n    response.end(thisSource);\n  } else if (url.pathname == '/findroom') {\n    if (request.method == \"OPTIONS\") {\n      // CORS preflight\n      corsAccept(request, response);\n      return;\n    }\n    var prefix = url.query.prefix;\n    var max = parseInt(url.query.max, 10);\n    if (! (prefix && max)) {\n      write400(\"You must include a valid prefix=CHARS&max=NUM portion of the URL\", response);\n      return;\n    }\n    if (prefix.search(/[^a-zA-Z0-9]/) != -1) {\n      write400(\"Invalid prefix\", response);\n      return;\n    }\n    findRoom(prefix, max, response);\n  } else {\n    write404(response);\n  }\n});\n\nfunction corsAccept(request, response) {\n  response.writeHead(200, {\n    \"Access-Control-Allow-Origin\": \"*\"\n  });\n  response.end();\n}\n\nfunction write500(error, response) {\n  response.writeHead(500, {\"Content-Type\": \"text/plain\"});\n  if (typeof error != \"string\") {\n    error = \"\\n\" + JSON.stringify(error, null, \"  \");\n  }\n  response.end(\"Error: \" + error);\n}\n\nfunction write404(response) {\n  response.writeHead(404, {\"Content-Type\": \"text/plain\"});\n  response.end(\"Resource not found\");\n}\n\nfunction write400(error, response) {\n  response.writeHead(400, {\"Content-Type\": \"text/plain\", \"Access-Control-Allow-Origin\": \"*\"});\n  response.end(\"Bad request: \" + error);\n}\n\nfunction findRoom(prefix, max, response) {\n  response.writeHead(200, {\n    \"Content-Type\": \"application/json\",\n    \"Access-Control-Allow-Origin\": \"*\"\n  });\n  var smallestNumber;\n  var smallestRooms = [];\n  for (var candidate in allConnections) {\n    if (candidate.indexOf(prefix + \"__\") === 0) {\n      var count = allConnections[candidate].length;\n      if (count < max && (smallestNumber === undefined || count <= smallestNumber)) {\n        if (smallestNumber === undefined || count < smallestNumber) {\n          smallestNumber = count;\n          smallestRooms = [candidate];\n        } else {\n          smallestRooms.push(candidate);\n        }\n      }\n    }\n  }\n  var room;\n  if (! smallestRooms.length) {\n    room = prefix + \"__\" + generateId();\n  } else {\n    room = pickRandom(smallestRooms);\n  }\n  response.end(JSON.stringify({name: room}));\n}\n\nfunction generateId(length) {\n  length = length || 10;\n  var letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV0123456789';\n  var s = '';\n  for (var i=0; i<length; i++) {\n    s += letters.charAt(Math.floor(Math.random() * letters.length));\n  }\n  return s;\n}\n\nfunction pickRandom(seq) {\n  return seq[Math.floor(Math.random() * seq.length)];\n}\n\nfunction startServer(port, host) {\n  server.listen(port, host, function() {\n    logger.info('HUB Server listening on port ' + port + \" interface: \" + host + \" PID: \" + process.pid);\n  });\n}\n\nvar wsServer = new WebSocketServer({\n    httpServer: server,\n    // 10Mb max size (1Mb is default, maybe this bump is unnecessary)\n    maxReceivedMessageSize: 0x1000000,\n    // The browser doesn't seem to break things up into frames (not sure what this means)\n    // and the default of 64Kb was exceeded; raised to 1Mb\n    maxReceivedFrameSize: 0x100000,\n    // Using autoaccept because the origin is somewhat dynamic\n    // FIXME: make this smarter?\n    autoAcceptConnections: false\n});\n\nfunction originIsAllowed(origin) {\n  // Unfortunately the origin will be whatever page you are sharing,\n  // which could be any origin\n  return true;\n}\n\nvar allConnections = {};\nvar connectionStats = {};\n\nvar ID = 0;\n\nwsServer.on('request', function(request) {\n  if (!originIsAllowed(request.origin)) {\n    // Make sure we only accept requests from an allowed origin\n    request.reject();\n    logger.info('Connection from origin ' + request.origin + ' rejected.');\n    return;\n  }\n\n  var id = request.httpRequest.url.replace(/^\\/+hub\\/+/, '').replace(/\\//g, \"\");\n  if (! id) {\n    request.reject(404, 'No ID Found');\n    return;\n  }\n\n  // FIXME: we should use a protocol here instead of null, but I can't\n  // get it to work.  \"Protocol\" is what the two clients are using\n  // this channel for (we don't bother to specify this)\n  var connection = request.accept(null, request.origin);\n  connection.ID = ID++;\n  if (! allConnections[id]) {\n    allConnections[id] = [];\n    connectionStats[id] = {\n      created: Date.now(),\n      sample: [],\n      clients: {},\n      domains: {},\n      urls: {},\n      firstDomain: null,\n      totalMessageChars: 0,\n      totalMessages: 0,\n      connections: 0\n    };\n  }\n  allConnections[id].push(connection);\n  connectionStats[id].connections++;\n  connectionStats[id].lastLeft = null;\n  logger.debug('Connection accepted to ' + JSON.stringify(id) + ' ID:' + connection.ID);\n  connection.sendUTF(JSON.stringify({\n    type: \"init-connection\",\n    peerCount: allConnections[id].length-1\n  }));\n  connection.on('message', function(message) {\n    var parsed;\n    try {\n      parsed = JSON.parse(message.utf8Data);\n    } catch (e) {\n      logger.warn('Error parsing JSON: ' + JSON.stringify(message.utf8Data) + \": \" + e);\n      return;\n    }\n    connectionStats[id].clients[parsed.clientId] = true;\n    var domain = null;\n    if (parsed.url) {\n      domain = parseUrl(parsed.url).hostname;\n      connectionStats[id].urls[parsed.url] = true;\n    }\n    if ((! connectionStats[id].firstDomain) && domain) {\n      connectionStats[id].firstDomain = domain;\n    }\n    connectionStats[id].domains[domain] = true;\n    connectionStats[id].totalMessageChars += message.utf8Data.length;\n    connectionStats[id].totalMessages++;\n    logger.debug('Message on ' + id + ' bytes: ' +\n                 (message.utf8Data && message.utf8Data.length) +\n                 ' conn ID: ' + connection.ID + ' data:' + message.utf8Data.substr(0, 20) +\n                 ' connections: ' + allConnections[id].length);\n    for (var i=0; i<allConnections[id].length; i++) {\n      var c = allConnections[id][i];\n      if (c == connection && !parsed[\"server-echo\"]) {\n        continue;\n      }\n      if (message.type === 'utf8') {\n        c.sendUTF(message.utf8Data);\n      } else if (message.type === 'binary') {\n        c.sendBytes(message.binaryData);\n      }\n    }\n  });\n  connection.on('close', function(reasonCode, description) {\n    if (! allConnections[id]) {\n      // Got cleaned up entirely, somehow?\n      logger.info(\"Connection ID\", id, \"was cleaned up entirely before last connection closed\");\n      return;\n    }\n    var index = allConnections[id].indexOf(connection);\n    if (index != -1) {\n      allConnections[id].splice(index, 1);\n    }\n    if (! allConnections[id].length) {\n      delete allConnections[id];\n      connectionStats[id].lastLeft = Date.now();\n    }\n    logger.debug('Peer ' + connection.remoteAddress + ' disconnected, ID: ' + connection.ID);\n  });\n});\n\nsetInterval(function () {\n  for (var id in connectionStats) {\n    if (connectionStats[id].lastLeft && Date.now() - connectionStats[id].lastLeft > EMPTY_ROOM_LOG_TIMEOUT) {\n      logStats(id, connectionStats[id]);\n      delete connectionStats[id];\n      continue;\n    }\n    var totalClients = countClients(connectionStats[id].clients);\n    var connections = 0;\n    if (allConnections[id]) {\n      connections = allConnections[id].length;\n    }\n    connectionStats[id].sample.push({\n      time: Date.now(),\n      totalClients: totalClients,\n      connections: connections\n    });\n  }\n}, SAMPLE_STATS_INTERVAL);\n\nsetInterval(function () {\n  var load = getLoad();\n  load.time = Date.now();\n  logger.info(\"LOAD\", JSON.stringify(load));\n}, SAMPLE_LOAD_INTERVAL);\n\nfunction getLoad() {\n  var sessions = 0;\n  var connections = 0;\n  var empty = 0;\n  var solo = 0;\n  for (var id in allConnections) {\n    if (allConnections[id].length) {\n      sessions++;\n      connections += allConnections[id].length;\n      if (allConnections[id].length == 1) {\n        solo++;\n      }\n    } else {\n      empty++;\n    }\n  }\n  return {\n    sessions: sessions,\n    connections: connections,\n    empty: empty,\n    solo: solo\n  };\n}\n\nfunction countClients(clients) {\n  var n = 0;\n  for (var clientId in clients) {\n    n++;\n  }\n  return n;\n}\n\nfunction logStats(id, stats) {\n  logger.info(\"STATS\", JSON.stringify({\n    id: id,\n    created: stats.created,\n    sample: stats.sample,\n    totalClients: countClients(stats.clients),\n    totalMessageChars: stats.totalMessageChars,\n    totalMessages: stats.totalMessages,\n    domain: stats.firstDomain || null,\n    domainCount: countClients(stats.domains),\n    urls: countClients(stats.urls)\n  }));\n}\n\nif (require.main == module) {\n  var ops = require('optimist')\n      .usage(\"Usage: $0 [--port 8080] [--host=localhost] [--log=filename] [--log-level=N]\")\n      .describe(\"port\", \"The port to server on (default $HUB_SERVER_PORT, $PORT, $VCAP_APP_PORT, or 8080\")\n      .describe(\"host\", \"The interface to serve on (default $HUB_SERVER_HOST, $HOST, $VCAP_APP_HOST, 127.0.0.1).  Use 0.0.0.0 to make it public\")\n      .describe(\"log-level\", \"The level of logging to do, from 0 (very verbose) to 5 (nothing) (default $LOG_LEVEL or 0)\")\n      .describe(\"log\", \"A file to log to (default $LOG_FILE or stdout)\")\n      .describe(\"stdout\", \"Log to both stdout and the log file\");\n  var port = ops.argv.port || process.env.HUB_SERVER_PORT || process.env.VCAP_APP_PORT ||\n      process.env.PORT || 8080;\n  var host = ops.argv.host || process.env.HUB_SERVER_HOST || process.env.VCAP_APP_HOST ||\n      process.env.HOST || '127.0.0.1';\n  var logLevel = process.env.LOG_LEVEL || 0;\n  var logFile = process.env.LOG_FILE || ops.argv.log;\n  var stdout = ops.argv.stdout || !logFile;\n  if (ops.argv['log-level']) {\n    logLevel = parseInt(ops.argv['log-level'], 10);\n  }\n  logger = new Logger(logLevel, logFile, stdout);\n  if (ops.argv.h || ops.argv.help) {\n    console.log(ops.help());\n    process.exit();\n  } else {\n    startServer(port, host);\n  }\n}\n\nexports.startServer = startServer;\n"
  },
  {
    "path": "hub/websocket-compat.js",
    "content": "/*\n * A hacked websocket module which retains compatibility with the old\n * Hixie-76 version of the standard, needed for phantom JS (and,\n * presumably, very old browsers).\n *\n * This file released into the public domain\n * by C. Scott Ananian <cscott@cscott.net> 2014-08-26\n *\n * Based on https://gist.github.com/toshirot/1428579\n */\nvar events = require(\"events\");\nvar util = require(\"util\");\n\nvar WebSocketRequest = require('websocket').request;\nvar WebSocketServer = require('websocket').server;\n\n// Copy helpers from WebSocketServer to WebSocketRequest\n\nWebSocketRequest.prototype.connections = [];\nWebSocketRequest.prototype.handleRequestAccepted =\n  WebSocketServer.prototype.handleRequestAccepted;\nWebSocketRequest.prototype.handleConnectionClose =\n  WebSocketServer.prototype.handleConnectionClose;\nWebSocketRequest.prototype.broadcastUTF =\n  WebSocketServer.prototype.broadcastUTF;\n\nvar miksagoServerFactory = require('websocket-server');\nvar miksagoConnection = require('../node_modules/websocket-server/lib/ws/connection');\n\nvar CompatWebSocketServer = function(options) {\n  events.EventEmitter.call(this); // superclass constructor\n  var self = this;\n  var handleConnection;\n\n  // node-websocket-server (hixie-75 and hixie-76 support)\n  var miksagoServer = miksagoServerFactory.createServer();\n  miksagoServer.server = options.httpServer;\n  miksagoServer.addListener('connection', function(connection) {\n    // Add remoteAddress property\n    connection.remoteAddress = connection._socket.remoteAddress;\n\n    // We want to use \"sendUTF\" regardless of the server implementation\n    connection.sendUTF = connection.send;\n    handleConnection(connection);\n  });\n\n  // WebSocket-Node config (modern websocket support)\n  var wsServerConfig =  {\n    // All options *except* 'httpServer' are required when bypassing\n    // WebSocketServer.\n    maxReceivedFrameSize: options.maxReceivedFrameSize || 0x10000,\n    maxReceivedMessageSize: options.maxReceivedMessageSize || 0x100000,\n    fragmentOutgoingMessages: true,\n    fragmentationThreshold: 0x4000,\n    keepalive: true,\n    keepaliveInterval: 20000,\n    assembleFragments: true,\n    // autoAcceptConnections is not applicable when bypassing WebSocketServer\n    // autoAcceptConnections: false,\n    disableNagleAlgorithm: true,\n    closeTimeout: 5000\n  };\n\n  // Handle the upgrade event ourselves instead of using WebSocketServer\n  var wsRequest={};\n  options.httpServer.on('upgrade', function(req, socket, head) {\n    if (typeof req.headers['sec-websocket-version'] !== 'undefined') {\n\n      // WebSocket hybi-08/-09/-10 connection (WebSocket-Node)\n      wsRequest = new WebSocketRequest(socket, req, wsServerConfig);\n      try {\n        wsRequest.readHandshake();\n      } catch (e) {\n        wsRequest.reject(\n          e.httpCode ? e.httpCode : 400,\n          e.message,\n          e.headers\n        );\n        return;\n      }\n      wsRequest.once('requestAccepted', function(connection) {\n        wsRequest.handleRequestAccepted(connection);\n      });\n      self.emit('request', wsRequest);\n\n    } else {\n\n      // WebSocket hixie-75/-76/hybi-00 connection (node-websocket-server)\n      if (req.method === 'GET' &&\n          (req.headers.upgrade && req.headers.connection) &&\n          req.headers.upgrade.toLowerCase() === 'websocket' &&\n          req.headers.connection.toLowerCase() === 'upgrade') {\n        new miksagoConnection(\n          miksagoServer.manager, miksagoServer.options, req, socket, head\n        );\n      }\n    }\n  });\n\n  // A connection handler for old-style websockets\n  handleConnection = function(connection) {\n    // fake a request\n    self.emit('request', new CompatRequest(self, connection));\n  };\n};\nutil.inherits(CompatWebSocketServer, events.EventEmitter);\n\nvar CompatRequest = function(server, connection) {\n  this._server = server;\n  this._connection = connection;\n  this.origin = connection._options.origin || '*';\n  this.httpRequest = connection._req;\n  // create wrapper right away in order to install event handlers promptly\n  this._connectionWrapper = new CompatConnection(server, connection);\n};\nCompatRequest.prototype.reject = function(code, message) {\n  this._connection.reject(message || \"no reason\");\n};\nCompatRequest.prototype.accept = function(proto, origin) {\n  // this is faked: we've already accepted the connection\n  return this._connectionWrapper;\n};\n\nvar CompatConnection = function(server, connection) {\n  var self = this;\n  events.EventEmitter.call(this); // superclass constructor\n\n  this._server = server;\n  this._connection = connection;\n  this.remoteAddress = connection.remoteAddress;\n\n  connection.addListener('message', function(wsMessage) {\n    // make the argument compatible with WebSocket-Node\n    self.emit('message', {\n      type: 'utf8',\n      utf8Data: wsMessage\n    });\n  });\n\n  connection.addListener('close', function() {\n    self.emit('close');\n  });\n};\nutil.inherits(CompatConnection, events.EventEmitter);\n\nCompatConnection.prototype.sendUTF = function(message) {\n  return this._connection.sendUTF(message);\n};\n\nmodule.exports.server = CompatWebSocketServer;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"togetherjs\",\n  \"version\": \"0.4.0a\",\n  \"main\": \"hub/server.js\",\n  \"description\": \"Collaborative help system\",\n  \"keywords\": [],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/mozilla/togetherjs.git\"\n  },\n  \"dependencies\": {\n    \"ejs\": \"~2.5.5\",\n    \"ejs-locals\": \"~1.0.2\",\n    \"express\": \"~3.0.6\",\n    \"grunt-amd-check\": \"~0.5.1\",\n    \"habitat\": \"~0.4.0\",\n    \"less\": \"~1.3.1\",\n    \"less-middleware\": \"~0.1.9\",\n    \"newrelic\": \"0.9.20\",\n    \"node-static\": \"~0.6.5\",\n    \"optimist\": \"~0.6.0\",\n    \"universal-analytics\": \"~0.1.3\",\n    \"websocket\": \"~1.0.7\",\n    \"websocket-server\": \"github:miksago/node-websocket-server#master\",\n    \"winston\": \"~0.6.2\"\n  },\n  \"devDependencies\": {\n    \"grunt-contrib-less\": \"~0.5.1\",\n    \"grunt-contrib-csslint\": \"~0.1.2\",\n    \"grunt-contrib-jshint\": \"~0.4.3\",\n    \"grunt-contrib-requirejs\": \"~0.4.1\",\n    \"grunt-contrib-watch\": \"~0.4.3\",\n    \"grunt\": \"~0.4.1\",\n    \"grunt-contrib-copy\": \"~0.4.1\",\n    \"grunt-http-server\": \"~0.0.5\",\n    \"nunjucks\": \"~0.1.8a\",\n    \"marked\": \"~0.3.4\",\n    \"docco\": \"~0.6.2\",\n    \"highlight.js\": \"~7.3.0\",\n    \"optimist\": \"~0.6.0\",\n    \"freeport\": \"~1.0.3\",\n    \"grunt-lib-phantomjs\": \"~0.6.0\"\n  },\n  \"engines\": {\n    \"node\": \"~0.12.7\",\n    \"npm\": \"^2.11.3\"\n  },\n  \"scripts\": {\n    \"start\": \"node hub/server.js\",\n    \"test\": \"grunt test\"\n  }\n}\n"
  },
  {
    "path": "phantomjs/bridge.js",
    "content": "(function (doctest) {\n  'use strict';\n\n  // Function.bind is not defined in phantomjs (!) so polyfill it\n  if (!Function.prototype.bind) {\n    Function.prototype.bind = function (oThis) {\n      if (typeof this !== \"function\") {\n        // closest thing possible to the ECMAScript 5\n        // internal IsCallable function\n        throw new TypeError(\"can't bind\");\n      }\n\n      var aArgs = Array.prototype.slice.call(arguments, 1),\n        fToBind = this,\n        fNOP = function () {},\n        fBound = function () {\n          return fToBind.apply(this instanceof fNOP && oThis\n                 ? this\n                 : oThis,\n                 aArgs.concat(Array.prototype.slice.call(arguments)));\n        };\n\n      fNOP.prototype = this.prototype;\n      fBound.prototype = new fNOP();\n\n      return fBound;\n    };\n  }\n\n  // default phantomjs background is transparent\n  document.body.bgColor = 'white';\n\n  // Send messages to the parent PhantomJS process via alert! Good times!!\n  function sendMessage() {\n    var args = [].slice.call(arguments);\n    alert(JSON.stringify(args));\n  }\n\n  // doctestjs-specific stuff.  First, be sure we don't autostart:\n  document.body.className = document.body.className.replace(/autodoctest/,'');\n\n  // Now define a custom reporter which will pass the results up to grunt\n  var PhantomReporter = function(runner) {\n    this.runner = runner;\n  };\n  PhantomReporter.prototype.logSuccess = function(example, got) {\n    this._send('doctestjs.pass', example, got);\n  };\n  PhantomReporter.prototype.logFailure = function(example, got) {\n    this._send('doctestjs.fail', example, got);\n  };\n  PhantomReporter.prototype._send = function(msg, example, got) {\n    sendMessage(msg, {\n      example: {\n        expr: example.expr,\n        summary: example.textSummary(),\n        expected: example.expected\n      },\n      got: got\n    });\n  };\n\n  // Start/finish the doctest runner.\n  window.doctestReporterHook = {\n    finish: function() {\n      sendMessage('doctestjs.end');\n    }\n  };\n  window.addEventListener('load', function() {\n    var runner = new doctest.Runner({\n      Reporter: PhantomReporter\n    });\n    var parser = new doctest.HTMLParser(runner);\n    parser.loadRemotes(function() {\n      runner.init();\n      parser.parse();\n      sendMessage('doctestjs.start');\n      runner.run();\n    });\n  });\n\n})(window.doctest);\n"
  },
  {
    "path": "site/base.tmpl",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\">\n    <title>{% block title %}\n      Mozilla Labs : TogetherJS\n    {% endblock %}</title>\n    <meta name=\"viewport\" content=\"width=320, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\"/>\n    <meta name=\"description\" content=\"Real time collaboration features for your website or app.\">\n    <meta name=\"author\" content=\"\">\n    <link rel=\"shortcut icon\" href=\"{{ base }}images/fav-icon.ico\">\n\n    <!-- use this block to set togetherjs config -->\n    {% block configs %}{% endblock %}\n\n    <script src=\"{{ base }}js/jquery-1.10.2.min.js\"></script>\n    <script src=\"{{ base }}js/bootstrap.min.js\"></script>\n    <script src=\"{{ base }}js/parallax.js\"></script>\n    <script src=\"{{ base }}js/custom.js\"></script>\n    <script src=\"{{ base }}js/scrollTo.js\"></script>\n    <script src=\"{{ base }}js/scrollspy.js\"></script>\n    <script src=\"{{ base }}js/waypoints.min.js\"></script>\n    <script src=\"{{ base }}js/how-animations.js\"></script>\n    <script src=\"{{ base }}togetherjs.js\"></script>\n\n    <!-- retina library -->\n    <script src=\"{{ base }}js/retina.js\"></script>\n\n    <script src=\"//mozorg.cdn.mozilla.net/tabzilla/tabzilla.js\"></script>\n\n    <script type=\"text/javascript\">\n      var _gaq = _gaq || [];\n      _gaq.push(['_setAccount', '{{ GA_ACCOUNT }}']);\n      _gaq.push(['_trackPageview']);\n\n      (function() {\n        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n      })();\n    </script>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"{{ base }}css/bootstrap.css\" rel=\"stylesheet\">\n    <link href=\"{{ base }}css/jumbotron.css\" rel=\"stylesheet\">\n    <link href=\"{{ base }}css/carousel.css\" rel=\"stylesheet\">\n    <link href=\"{{ base }}css/grid.css\" rel=\"stylesheet\">\n    <link href=\"{{ base }}css/style.css\" rel=\"stylesheet\">\n    <link href=\"//mozorg.cdn.mozilla.net/media/css/tabzilla-min.css\" rel=\"stylesheet\" />\n\n    {% block styles %}{% endblock %}\n\n    <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->\n    <!--[if lt IE 9]>\n      <script src=\"http://html5shim.googlecode.com/svn/trunk/html5.js\">\n      </script>\n    <![endif]-->\n    <!-- Le fav and touch icons -->\n    <link rel=\"shortcut icon\" href=\"{{ base }}assets/ico/favicon.ico\">\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"144x144\" href=\"{{ base }}assets/ico/apple-touch-icon-144-precomposed.png\">\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"114x114\" href=\"{{ base }}assets/ico/apple-touch-icon-114-precomposed.png\">\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"72x72\" href=\"{{ base }}assets/ico/apple-touch-icon-72-precomposed.png\">\n    <link rel=\"apple-touch-icon-precomposed\" href=\"{{ base }}assets/ico/apple-touch-icon-57-precomposed.png\">\n\n    <script>\n    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n    ga('create', 'UA-35433268-43', 'togetherjs.com');\n    ga('send', 'pageview');\n    </script>\n\n  </head>\n  <body {% block body_tag %}{% endblock %}>\n    <div class=\"navbar main-header\" id=\"main-navbar\">\n\n      <!-- Tabzilla -->\n      <a href=\"https://www.mozilla.org/\" id=\"tabzilla\">mozilla</a>\n\n      <!-- start container -->\n      <div class=\"container navbox\">\n        <div class=\"navbar-header\">\n          <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n            <span class=\"icon-bar\"></span>\n          </button>\n          <a class=\"navbar-brand main-logo\" href=\"{{base}}./\"></a>\n          <a class=\"navbar-brand masthead-title\" href=\"{{base}}./\">TogetherJS</a>\n        </div>\n\n        <div class=\"navbar-collapse collapse\">\n          <ul class=\"nav navbar-nav navbar-right main-nav\">\n            <li><a href=\"{{base}}./\" {% if (enableHome) %}class=\"scrollnav active\"{% endif %} >Overview</a></li>\n            <li><a class=\"documentationActive\"href=\"{{base}}./docs/\" {% if (enableMarkdown) %}class=\"scrollnav active\"{% endif %} >Documentation</a></li>\n            <li><a href=\"https://github.com/mozilla/togetherjs\" target=\"_blank\">Github</a></li>\n            <li><a href=\"mailto:togetherjs@mozilla.com\">Contact</a></li>\n          </ul>\n        </div><!--/.navbar-collapse -->\n\n      </div>\n    </div>\n\n\n    {% block body %}{% endblock %}\n\n\n        <hr>\n\n        <footer>\n\n          <section class=\"row\" id=\"footer\">\n            <div class=\"col-xs-12 col-sm-3 text-left\">\n              <p><a href=\"https://mozillalabs.com/en-US/\" target=\"_blank\"><img src=\"{{ base }}images/footer-mozilla-labs.png\"></a></p>\n            </div>\n            <div class=\"col-xs-12 col-sm-3\">\n              <ul class=\"list-unstyled text-left\">\n                <li class=\"\"><a href=\"{{ base }}./\" class=\"\">Overview</a></li>\n                <li><a href=\"{{base}}./docs/\" target=\"_blank\">Docs</a></li>\n                <li class=\"\"><a href=\"https://github.com/mozilla/togetherjs\" target=\"_blank\">GitHub</a></li>\n                <li class=\"\"><a href=\"mailto:togetherjs@mozilla.com\" target=\"_blank\">Contact</a></li>\n              </ul>\n            </div>\n            <div class=\"col-xs-12 col-sm-3\">\n              <ul class=\"list-unstyled text-left\">\n                <li class=\"\"><a href=\"https://mozillalabs.com/en-US/togetherjs/\" target=\"_blank\">About</a></li>\n                <li><a href=\"{{base}}./docs/contributing.html\">Contributing</a></li>\n                <li><a href=\"{{ base }}source/\">Source Code</a></li>\n                <li><a href=\"{{ base }}faq.html\">FAQ</a></li>\n                <li class=\"\"><a href=\"https://twitter.com/togetherjs\" target=\"_blank\">Twitter</a></li>\n              </ul>\n            </div>\n            <div class=\"col-xs-12 col-sm-3\">\n              <ul class=\"list-unstyled text-left\">\n                <li class=\"\"><a href=\"https://www.mozilla.org/privacy/websites/\" target=\"_blank\">Privacy Policy</a></li>\n                <li class=\"\"><a href=\"https://www.mozilla.org/about/legal/\" target=\"_blank\">Legal Notices</a></li>\n                <li class=\"\"><a href=\"https://www.mozilla.org/legal/fraud-report/\" target=\"_blank\">Report Trademark Abuses</a></li>\n                <li class=\"ph-credit\">Thanks to Yuan Wang for the cover photo!</li>\n              </ul>\n            </div>\n          </section>\n        </footer>\n      </section>\n\n    </div> <!-- /container -->\n\n  </body>\n</html>\n"
  },
  {
    "path": "site/bookmarklet.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block title %}TogetherJS Bookmarklet{% endblock %}\n{% block styles %}\n\n<script>\n\nfunction bookmarklet() {\n  var s = \"window._TogetherJSBookmarklet = true;\";\n  s += \"s=document.createElement('script');\";\n  s += \"s.src=\" + JSON.stringify(TogetherJS.baseUrl + \"/togetherjs.js\") + \";\";\n  s += \"document.head.appendChild(s);\";\n  s = \"(function () {\" + s + \"})();void(0)\";\n  return \"javascript:\" + encodeURIComponent(s);\n};\n\nwindow.addEventListener(\"load\", function () {\n  var el = document.getElementById(\"towtruck-bookmarklet\");\n  el.href = bookmarklet();\n}, false);\n\n</script>\n\n{% endblock %}\n\n{% block body %}\n\n<div class=\"container\">\n\n<h1>TogetherJS Bookmarklet</h1>\n\n<p>\n  To use this bookmarklet, drag the button below to your bookmark toolbar:\n</p>\n\n<p>\n  <a id=\"towtruck-bookmarklet\" class=\"button fade-half\" href=\"#\">Start TogetherJS</a>\n</p>\n\n</div>\n\n{% endblock %}\n"
  },
  {
    "path": "site/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world by @mdo and @fat.\n */\n\n/*! normalize.css v2.1.0 | MIT License | git.io/normalize */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n[hidden] {\n  display: none;\n}\n\nhtml {\n  font-family: sans-serif;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\nbody {\n  margin: 0;\n}\n\na:focus {\n  outline: thin dotted;\n}\n\na:active,\na:hover {\n  outline: 0;\n}\n\nh1 {\n  margin: 0.67em 0;\n  font-size: 2em;\n}\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\nb,\nstrong {\n  font-weight: bold;\n}\n\ndfn {\n  font-style: italic;\n}\n\nhr {\n  height: 0;\n  -moz-box-sizing: content-box;\n       box-sizing: content-box;\n}\n\nmark {\n  color: #000;\n  background: #ff0;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n\npre {\n  white-space: pre-wrap;\n}\n\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n\nsmall {\n  font-size: 80%;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  border: 0;\n}\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\nfigure {\n  margin: 0;\n}\n\nfieldset {\n  padding: 0.35em 0.625em 0.75em;\n  margin: 0 2px;\n  border: 1px solid #c0c0c0;\n}\n\nlegend {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: 100%;\n}\n\nbutton,\ninput {\n  line-height: normal;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  padding: 0;\n  box-sizing: border-box;\n}\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}\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\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  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\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  @page  {\n    margin: 2cm .5cm;\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  .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*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #333333;\n  background-color: #ffffff;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\nbutton,\ninput,\nselect[multiple],\ntextarea {\n  background-image: none;\n}\n\na {\n  color: #428bca;\n  text-decoration: none;\n}\n\na:hover,\na:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\nimg {\n  vertical-align: middle;\n}\n\n.img-responsive {\n  display: block;\n  height: auto;\n  max-width: 100%;\n}\n\n.img-rounded {\n  border-radius: 6px;\n}\n\n.img-circle {\n  border-radius: 50%;\n}\n\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\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}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 16.099999999999998px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\n\nsmall {\n  font-size: 85%;\n}\n\ncite {\n  font-style: normal;\n}\n\n.text-muted {\n  color: #999999;\n}\n\n.text-primary {\n  color: #428bca;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\n.text-danger {\n  color: #b94a48;\n}\n\n.text-success {\n  color: #468847;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\n.text-left {\n  text-align: left;\n}\n\n.text-right {\n  text-align: right;\n}\n\n.text-center {\n  text-align: center;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 500;\n  line-height: 1.1;\n}\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 {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\n\nh4,\nh5,\nh6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\nh1,\n.h1 {\n  font-size: 38px;\n}\n\nh2,\n.h2 {\n  font-size: 32px;\n}\n\nh3,\n.h3 {\n  font-size: 24px;\n}\n\nh4,\n.h4 {\n  font-size: 18px;\n}\n\nh5,\n.h5 {\n  font-size: 14px;\n}\n\nh6,\n.h6 {\n  font-size: 12px;\n}\n\nh1 small,\n.h1 small {\n  font-size: 24px;\n}\n\nh2 small,\n.h2 small {\n  font-size: 18px;\n}\n\nh3 small,\n.h3 small,\nh4 small,\n.h4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\n\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 1.428571429;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 0;\n}\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  .dl-horizontal dd:before,\n  .dl-horizontal dd:after {\n    display: table;\n    content: \" \";\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n  .dl-horizontal dd:before,\n  .dl-horizontal dd:after {\n    display: table;\n    content: \" \";\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\n\nblockquote p:last-child {\n  margin-bottom: 0;\n}\n\nblockquote small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.428571429;\n}\n\ncode,\npre {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n}\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}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.428571429;\n  color: #333333;\n  word-break: break-all;\n  word-wrap: break-word;\n  background-color: #f5f5f5;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .container .row {\n    margin-right: -15px;\n    margin-left: -15px;\n  }\n}\n\n.row .row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12,\n.col-sm-1,\n.col-sm-2,\n.col-sm-3,\n.col-sm-4,\n.col-sm-5,\n.col-sm-6,\n.col-sm-7,\n.col-sm-8,\n.col-sm-9,\n.col-sm-10,\n.col-sm-11,\n.col-sm-12,\n.col-md-1,\n.col-md-2,\n.col-md-3,\n.col-md-4,\n.col-md-5,\n.col-md-6,\n.col-md-7,\n.col-md-8,\n.col-md-9,\n.col-md-10,\n.col-md-11,\n.col-md-12,\n.col-lg-1,\n.col-lg-2,\n.col-lg-3,\n.col-lg-4,\n.col-lg-5,\n.col-lg-6,\n.col-lg-7,\n.col-lg-8,\n.col-lg-9,\n.col-lg-10,\n.col-lg-11,\n.col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11 {\n  float: left;\n}\n\n.col-xs-1 {\n  width: 8.333333333333332%;\n}\n\n.col-xs-2 {\n  width: 16.666666666666664%;\n}\n\n.col-xs-3 {\n  width: 25%;\n}\n\n.col-xs-4 {\n  width: 33.33333333333333%;\n}\n\n.col-xs-5 {\n  width: 41.66666666666667%;\n}\n\n.col-xs-6 {\n  width: 50%;\n}\n\n.col-xs-7 {\n  width: 58.333333333333336%;\n}\n\n.col-xs-8 {\n  width: 66.66666666666666%;\n}\n\n.col-xs-9 {\n  width: 75%;\n}\n\n.col-xs-10 {\n  width: 83.33333333333334%;\n}\n\n.col-xs-11 {\n  width: 91.66666666666666%;\n}\n\n.col-xs-12 {\n  width: 100%;\n}\n\n@media (min-width: 768px) {\n  .container {\n    max-width: 720px;\n  }\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11 {\n    float: left;\n  }\n  .col-sm-1 {\n    width: 8.333333333333332%;\n  }\n  .col-sm-2 {\n    width: 16.666666666666664%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-4 {\n    width: 33.33333333333333%;\n  }\n  .col-sm-5 {\n    width: 41.66666666666667%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-7 {\n    width: 58.333333333333336%;\n  }\n  .col-sm-8 {\n    width: 66.66666666666666%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-10 {\n    width: 83.33333333333334%;\n  }\n  .col-sm-11 {\n    width: 91.66666666666666%;\n  }\n  .col-sm-12 {\n    width: 100%;\n  }\n  .col-sm-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-sm-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-sm-push-3 {\n    left: 25%;\n  }\n  .col-sm-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-sm-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-sm-push-6 {\n    left: 50%;\n  }\n  .col-sm-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-sm-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-sm-push-9 {\n    left: 75%;\n  }\n  .col-sm-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-sm-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-sm-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-sm-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-sm-pull-3 {\n    right: 25%;\n  }\n  .col-sm-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-sm-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-sm-pull-6 {\n    right: 50%;\n  }\n  .col-sm-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-sm-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-sm-pull-9 {\n    right: 75%;\n  }\n  .col-sm-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-sm-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-sm-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-sm-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .col-sm-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-sm-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .col-sm-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-sm-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .col-sm-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-sm-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n}\n\n@media (min-width: 992px) {\n  .container {\n    max-width: 940px;\n  }\n  .col-md-1,\n  .col-md-2,\n  .col-md-3,\n  .col-md-4,\n  .col-md-5,\n  .col-md-6,\n  .col-md-7,\n  .col-md-8,\n  .col-md-9,\n  .col-md-10,\n  .col-md-11 {\n    float: left;\n  }\n  .col-md-1 {\n    width: 8.333333333333332%;\n  }\n  .col-md-2 {\n    width: 16.666666666666664%;\n  }\n  .col-md-3 {\n    width: 25%;\n  }\n  .col-md-4 {\n    width: 33.33333333333333%;\n  }\n  .col-md-5 {\n    width: 41.66666666666667%;\n  }\n  .col-md-6 {\n    width: 50%;\n  }\n  .col-md-7 {\n    width: 58.333333333333336%;\n  }\n  .col-md-8 {\n    width: 66.66666666666666%;\n  }\n  .col-md-9 {\n    width: 75%;\n  }\n  .col-md-10 {\n    width: 83.33333333333334%;\n  }\n  .col-md-11 {\n    width: 91.66666666666666%;\n  }\n  .col-md-12 {\n    width: 100%;\n  }\n  .col-md-push-0 {\n    left: auto;\n  }\n  .col-md-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-md-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-md-push-3 {\n    left: 25%;\n  }\n  .col-md-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-md-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-md-push-6 {\n    left: 50%;\n  }\n  .col-md-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-md-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-md-push-9 {\n    left: 75%;\n  }\n  .col-md-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-md-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-md-pull-0 {\n    right: auto;\n  }\n  .col-md-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-md-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-md-pull-3 {\n    right: 25%;\n  }\n  .col-md-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-md-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-md-pull-6 {\n    right: 50%;\n  }\n  .col-md-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-md-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-md-pull-9 {\n    right: 75%;\n  }\n  .col-md-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-md-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-md-offset-0 {\n    margin-left: 0;\n  }\n  .col-md-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-md-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-md-offset-3 {\n    margin-left: 25%;\n  }\n  .col-md-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-md-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-md-offset-6 {\n    margin-left: 50%;\n  }\n  .col-md-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-md-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-md-offset-9 {\n    margin-left: 75%;\n  }\n  .col-md-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-md-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container {\n    max-width: 1140px;\n  }\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11 {\n    float: left;\n  }\n  .col-lg-1 {\n    width: 8.333333333333332%;\n  }\n  .col-lg-2 {\n    width: 16.666666666666664%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-4 {\n    width: 33.33333333333333%;\n  }\n  .col-lg-5 {\n    width: 41.66666666666667%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-7 {\n    width: 58.333333333333336%;\n  }\n  .col-lg-8 {\n    width: 66.66666666666666%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-10 {\n    width: 83.33333333333334%;\n  }\n  .col-lg-11 {\n    width: 91.66666666666666%;\n  }\n  .col-lg-12 {\n    width: 100%;\n  }\n  .col-lg-push-0 {\n    left: auto;\n  }\n  .col-lg-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-lg-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-lg-push-3 {\n    left: 25%;\n  }\n  .col-lg-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-lg-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-lg-push-6 {\n    left: 50%;\n  }\n  .col-lg-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-lg-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-lg-push-9 {\n    left: 75%;\n  }\n  .col-lg-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-lg-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-lg-pull-0 {\n    right: auto;\n  }\n  .col-lg-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-lg-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-lg-pull-3 {\n    right: 25%;\n  }\n  .col-lg-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-lg-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-lg-pull-6 {\n    right: 50%;\n  }\n  .col-lg-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-lg-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-lg-pull-9 {\n    right: 75%;\n  }\n  .col-lg-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-lg-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-lg-offset-0 {\n    margin-left: 0;\n  }\n  .col-lg-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-lg-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .col-lg-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-lg-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .col-lg-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-lg-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .col-lg-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-lg-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n}\n\nth {\n  text-align: left;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\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.428571429;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table thead > tr > th {\n  vertical-align: bottom;\n}\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\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\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\n.table-bordered {\n  border: 1px solid #dddddd;\n}\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 #dddddd;\n}\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\n.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n  background-color: #f5f5f5;\n}\n\ntable col[class^=\"col-\"] {\n  display: table-column;\n  float: none;\n}\n\ntable td[class^=\"col-\"],\ntable th[class^=\"col-\"] {\n  display: table-cell;\n  float: none;\n}\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\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  border-color: #d6e9c6;\n}\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  background-color: #d0e9c6;\n  border-color: #c9e2b3;\n}\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  border-color: #eed3d7;\n}\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  background-color: #ebcccc;\n  border-color: #e6c1c7;\n}\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  border-color: #fbeed5;\n}\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  background-color: #faf2cc;\n  border-color: #f8e5be;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\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: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n\n  line-height: normal;\n}\n\ninput[type=\"file\"] {\n  display: block;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect optgroup {\n  font-family: inherit;\n  font-size: inherit;\n  font-style: inherit;\n}\n\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\n\n.form-control:-moz-placeholder {\n  color: #999999;\n}\n\n.form-control::-moz-placeholder {\n  color: #999999;\n}\n\n.form-control:-ms-input-placeholder {\n  color: #999999;\n}\n\n.form-control::-webkit-input-placeholder {\n  color: #999999;\n}\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.428571429;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n          transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n\n.form-control:focus {\n  border-color: #66afe9;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ntextarea.form-control {\n  height: auto;\n}\n\n.form-group {\n  margin-bottom: 15px;\n}\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  vertical-align: middle;\n}\n\n.radio label,\n.checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\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\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\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\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\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\n.input-sm {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\nselect.input-sm {\n  height: 30px;\n  line-height: 30px;\n}\n\ntextarea.input-sm {\n  height: auto;\n}\n\n.input-lg {\n  height: 45px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\nselect.input-lg {\n  height: 45px;\n  line-height: 45px;\n}\n\ntextarea.input-lg {\n  height: auto;\n}\n\n.has-warning .help-block,\n.has-warning .control-label {\n  color: #c09853;\n}\n\n.has-warning .form-control {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-warning .form-control:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.has-warning .input-group-addon {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.has-error .help-block,\n.has-error .control-label {\n  color: #b94a48;\n}\n\n.has-error .form-control {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-error .form-control:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.has-error .input-group-addon {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.has-success .help-block,\n.has-success .control-label {\n  color: #468847;\n}\n\n.has-success .form-control {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-success .form-control:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.has-success .input-group-addon {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.form-control-static {\n  padding-top: 6px;\n  margin-bottom: 0;\n}\n\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\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  }\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  }\n  .form-inline .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n\n.form-horizontal .control-label,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n  padding-top: 6px;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .container .form-horizontal .form-group {\n    margin-right: -15px;\n    margin-left: -15px;\n  }\n}\n\n.form-horizontal .form-group .row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n\n.btn {\n  display: inline-block;\n  padding: 6px 12px;\n  margin-bottom: 0;\n  font-size: 14px;\n  font-weight: bold;\n  line-height: 1.428571429;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  cursor: pointer;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n       -o-user-select: none;\n          user-select: none;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn:hover,\n.btn:focus {\n  color: #333333;\n  text-decoration: none;\n}\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, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  pointer-events: none;\n  cursor: not-allowed;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-default {\n  color: #333333;\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\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: #333333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  background-image: none;\n}\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: #ffffff;\n  border-color: #cccccc;\n}\n\n.btn-primary {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #357ebd;\n}\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: #ffffff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  background-image: none;\n}\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\n.btn-warning {\n  color: #ffffff;\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\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: #ffffff;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  background-image: none;\n}\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\n.btn-danger {\n  color: #ffffff;\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\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: #ffffff;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  background-image: none;\n}\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\n.btn-success {\n  color: #ffffff;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\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: #ffffff;\n  background-color: #47a447;\n  border-color: #398439;\n}\n\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  background-image: none;\n}\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\n.btn-info {\n  color: #ffffff;\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\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: #ffffff;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  background-image: none;\n}\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\n.btn-link {\n  font-weight: normal;\n  color: #428bca;\n  cursor: pointer;\n  border-radius: 0;\n}\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\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n\n.btn-link:hover,\n.btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n\n.btn-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\n.btn-sm,\n.btn-xs {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-xs {\n  padding: 1px 5px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  display: none;\n}\n\n.collapse.in {\n  display: block;\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n\n.input-group.col {\n  float: none;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.input-group .form-control {\n  width: 100%;\n  margin-bottom: 0;\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  height: 45px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n  height: 45px;\n  line-height: 45px;\n}\n\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn {\n  height: auto;\n}\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}\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}\n\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn {\n  height: auto;\n}\n\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n}\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\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n\n.input-group-addon {\n  padding: 6px 12px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n\n.input-group-addon.input-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n\n.input-group-addon.input-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\n}\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 > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group-addon:first-child {\n  border-right: 0;\n}\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 > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n.input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n\n.input-group-btn > .btn {\n  position: relative;\n}\n\n.input-group-btn > .btn + .btn {\n  margin-left: -4px;\n}\n\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:active {\n  z-index: 2;\n}\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 #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle:focus {\n  outline: 0;\n}\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: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 4px;\n  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n          box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n  background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 1.428571429;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #428bca;\n}\n\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #428bca;\n  outline: 0;\n}\n\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #999999;\n}\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\n.open > .dropdown-menu {\n  display: block;\n}\n\n.open > a {\n  outline: 0;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.428571429;\n  color: #999999;\n}\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\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.list-group {\n  padding-left: 0;\n  margin-bottom: 20px;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  margin-bottom: -1px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n}\n\n.list-group-item:first-child {\n  border-top-right-radius: 4px;\n  border-top-left-radius: 4px;\n}\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\n.list-group-item > .badge {\n  float: right;\n}\n\n.list-group-item > .badge + .badge {\n  margin-right: 5px;\n}\n\na.list-group-item {\n  color: #555555;\n}\n\na.list-group-item .list-group-item-heading {\n  color: #333333;\n}\n\na.list-group-item:hover,\na.list-group-item:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  z-index: 2;\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading {\n  color: inherit;\n}\n\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n  color: #e1edf7;\n}\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n\n.panel {\n  margin-bottom: 20px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.panel-body {\n  padding: 15px;\n}\n\n.panel > .list-group {\n  margin-bottom: 0;\n}\n\n.panel > .list-group .list-group-item {\n  border-width: 1px 0;\n}\n\n.panel > .list-group .list-group-item:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.panel > .list-group .list-group-item:last-child {\n  border-bottom: 0;\n}\n\n.panel-heading + .list-group .list-group-item:first-child {\n  border-top-width: 0;\n}\n\n.panel-heading {\n  padding: 10px 15px;\n  background-color: #f5f5f5;\n  border-bottom: 1px solid #dddddd;\n  border-top-right-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 17.5px;\n}\n\n.panel-title > a {\n  color: inherit;\n}\n\n.panel-footer {\n  padding: 10px 15px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dddddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n\n.panel-group .panel {\n  margin-bottom: 0;\n  overflow: hidden;\n  border-radius: 4px;\n}\n\n.panel-group .panel + .panel {\n  margin-top: 5px;\n}\n\n.panel-group .panel-heading {\n  border-bottom: 0;\n}\n\n.panel-group .panel-heading + .panel-collapse .panel-body {\n  border-top: 1px solid #dddddd;\n}\n\n.panel-group .panel-footer {\n  border-top: 0;\n}\n\n.panel-group .panel-footer + .panel-collapse .panel-body {\n  border-bottom: 1px solid #dddddd;\n}\n\n.panel-primary {\n  border-color: #428bca;\n}\n\n.panel-primary > .panel-heading {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.panel-primary > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #428bca;\n}\n\n.panel-primary > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #428bca;\n}\n\n.panel-success {\n  border-color: #d6e9c6;\n}\n\n.panel-success > .panel-heading {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.panel-success > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #d6e9c6;\n}\n\n.panel-success > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #d6e9c6;\n}\n\n.panel-warning {\n  border-color: #fbeed5;\n}\n\n.panel-warning > .panel-heading {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #fbeed5;\n}\n\n.panel-warning > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #fbeed5;\n}\n\n.panel-warning > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #fbeed5;\n}\n\n.panel-danger {\n  border-color: #eed3d7;\n}\n\n.panel-danger > .panel-heading {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.panel-danger > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #eed3d7;\n}\n\n.panel-danger > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #eed3d7;\n}\n\n.panel-info {\n  border-color: #bce8f1;\n}\n\n.panel-info > .panel-heading {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.panel-info > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #bce8f1;\n}\n\n.panel-info > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #bce8f1;\n}\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, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-lg {\n  padding: 24px;\n  border-radius: 6px;\n}\n\n.well-sm {\n  padding: 9px;\n  border-radius: 3px;\n}\n\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover,\n.close:focus {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.nav {\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav > li {\n  position: relative;\n  display: block;\n}\n\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li.disabled > a {\n  color: #999999;\n}\n\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n}\n\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n  background-color: #eeeeee;\n  border-color: #428bca;\n}\n\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.428571429;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-bottom-color: transparent;\n}\n\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-justified > li {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.nav-tabs.nav-justified > li > a {\n  text-align: center;\n}\n\n.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs.nav-justified > .active > a {\n  border-bottom-color: #ffffff;\n}\n\n.nav-pills > li {\n  float: left;\n}\n\n.nav-pills > li > a {\n  border-radius: 5px;\n}\n\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n\n.nav-justified {\n  width: 100%;\n}\n\n.nav-justified > li {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.nav-justified > li > a {\n  text-align: center;\n}\n\n.nav-tabs-justified {\n  border-bottom: 0;\n}\n\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs-justified > .active > a {\n  border-bottom-color: #ffffff;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  content: \" \";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  content: \" \";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.nav .caret {\n  border-top-color: #428bca;\n  border-bottom-color: #428bca;\n}\n\n.nav a:hover .caret {\n  border-top-color: #2a6496;\n  border-bottom-color: #2a6496;\n}\n\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 20px;\n  background-color: #f8f8f8;\n  border: 1px solid #e7e7e7;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .navbar {\n    border-radius: 4px;\n  }\n}\n\n.navbar-header {\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.navbar-header:before,\n.navbar-header:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-header:after {\n  clear: both;\n}\n\n.navbar-header:before,\n.navbar-header:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-header:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .navbar-header {\n    float: left;\n  }\n}\n\n.navbar-collapse {\n  max-height: 340px;\n  padding-right: 15px;\n  padding-left: 15px;\n  overflow-x: visible;\n  overflow-y: auto;\n  border-top: 1px solid #e6e6e6;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n  -webkit-overflow-scrolling: touch;\n}\n\n.navbar-collapse:before,\n.navbar-collapse:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-collapse:after {\n  clear: both;\n}\n\n.navbar-collapse:before,\n.navbar-collapse:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-collapse:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .navbar-collapse {\n    width: auto;\n    padding-right: 0;\n    padding-left: 0;\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}\n\n.navbar-static-top {\n  border-width: 0 0 1px;\n}\n\n@media (min-width: 768px) {\n  .navbar-static-top {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  border-width: 0 0 1px;\n}\n\n@media (min-width: 768px) {\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n}\n\n.navbar-brand {\n  float: left;\n  padding-top: 15px;\n  padding-bottom: 15px;\n  font-size: 18px;\n  line-height: 20px;\n  color: #777777;\n}\n\n.navbar-brand:hover,\n.navbar-brand:focus {\n  color: #5e5e5e;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  padding: 9px 10px;\n  margin-top: 8px;\n  margin-bottom: 8px;\n  background-color: transparent;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n}\n\n.navbar-toggle:hover,\n.navbar-toggle:focus {\n  background-color: #dddddd;\n}\n\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  background-color: #cccccc;\n  border-radius: 1px;\n}\n\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n\n@media (min-width: 768px) {\n  .navbar-toggle {\n    position: relative;\n    top: auto;\n    left: auto;\n    display: none;\n  }\n}\n\n.navbar-nav {\n  padding-top: 7.5px;\n  padding-bottom: 7.5px;\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.navbar-nav > li > a {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  line-height: 20px;\n  color: #777777;\n}\n\n.navbar-nav > li > a:hover,\n.navbar-nav > li > a:focus {\n  color: #333333;\n  background-color: transparent;\n}\n\n.navbar-nav > .active > a,\n.navbar-nav > .active > a:hover,\n.navbar-nav > .active > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n\n.navbar-nav > .disabled > a,\n.navbar-nav > .disabled > a:hover,\n.navbar-nav > .disabled > a:focus {\n  color: #cccccc;\n  background-color: transparent;\n}\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    color: #777777;\n  }\n  .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #333333;\n    background-color: transparent;\n    background-image: none;\n  }\n  .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #555555;\n    background-color: #e7e7e7;\n  }\n  .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #cccccc;\n    background-color: transparent;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-nav {\n    float: left;\n    padding-top: 0;\n    padding-bottom: 0;\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}\n\n@media (min-width: 768px) {\n  .navbar-left {\n    float: left !important;\n  }\n  .navbar-right {\n    float: right !important;\n  }\n  .navbar-right .dropdown-menu {\n    right: 0;\n    left: auto;\n  }\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 #e6e6e6;\n  border-bottom: 1px solid #e6e6e6;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\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  }\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  }\n  .navbar-form .radio input[type=\"radio\"],\n  .navbar-form .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n\n@media (max-width: 767px) {\n  .navbar-form .form-group {\n    margin-bottom: 5px;\n  }\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}\n\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.navbar-nav > .dropdown > a:hover .caret,\n.navbar-nav > .dropdown > a:focus .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n\n.navbar-nav > .open > a,\n.navbar-nav > .open > a:hover,\n.navbar-nav > .open > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n\n.navbar-nav > .open > a .caret,\n.navbar-nav > .open > a:hover .caret,\n.navbar-nav > .open > a:focus .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar-nav > .dropdown > a .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n\n.navbar-text {\n  float: left;\n  margin-top: 15px;\n  margin-bottom: 15px;\n  color: #777777;\n}\n\n@media (min-width: 768px) {\n  .navbar-text {\n    margin-right: 15px;\n    margin-left: 15px;\n  }\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar-inverse {\n  background-color: #222222;\n  border-color: #080808;\n}\n\n.navbar-inverse .navbar-brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\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: #ffffff;\n  background-color: #080808;\n}\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: #444444;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-toggle {\n  border-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #ffffff;\n}\n\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n  border-color: #101010;\n}\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: #ffffff;\n  background-color: #080808;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .navbar-nav > .open > a .caret,\n.navbar-inverse .navbar-nav > .open > a:hover .caret,\n.navbar-inverse .navbar-nav > .open > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\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 > li > a {\n    color: #999999;\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: #ffffff;\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: #ffffff;\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: #444444;\n    background-color: transparent;\n  }\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.btn-default .caret {\n  border-top-color: #333333;\n}\n\n.btn-primary .caret,\n.btn-success .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret {\n  border-top-color: #fff;\n}\n\n.dropup .btn-default .caret {\n  border-bottom-color: #333333;\n}\n\n.dropup .btn-primary .caret,\n.dropup .btn-success .caret,\n.dropup .btn-warning .caret,\n.dropup .btn-danger .caret,\n.dropup .btn-info .caret {\n  border-bottom-color: #fff;\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\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\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus {\n  outline: none;\n}\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\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar .btn-group {\n  float: left;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group,\n.btn-toolbar > .btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n}\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\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group > .btn-group {\n  float: left;\n}\n\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\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\n.btn-group > .btn-group:last-child > .btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group-xs > .btn {\n  padding: 5px 10px;\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-group-sm > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  padding-right: 8px;\n  padding-left: 8px;\n}\n\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-right: 12px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn .caret {\n  margin-left: 0;\n}\n\n.btn-lg .caret {\n  border-width: 5px;\n}\n\n.dropup .btn-lg .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n\n.btn-group-vertical > .btn-group > .btn {\n  float: none;\n}\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\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\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\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n  border-top-right-radius: 0;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:first-child > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:last-child > .btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  border-collapse: separate;\n  table-layout: fixed;\n}\n\n.btn-group-justified .btn {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\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\n.breadcrumb > li {\n  display: inline-block;\n}\n\n.breadcrumb > li + li:before {\n  padding: 0 5px;\n  color: #cccccc;\n  content: \"/\\00a0\";\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n\n.pagination > li {\n  display: inline;\n}\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.428571429;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n}\n\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  margin-left: 0;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n}\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\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n  background-color: #eeeeee;\n}\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: #ffffff;\n  cursor: default;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.pagination > .disabled > span,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n  border-color: #dddddd;\n}\n\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n  padding: 10px 16px;\n  font-size: 18px;\n}\n\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n  border-bottom-left-radius: 6px;\n  border-top-left-radius: 6px;\n}\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\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n  border-bottom-left-radius: 3px;\n  border-top-left-radius: 3px;\n}\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\n.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 15px;\n}\n\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #428bca;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n}\n\n.modal-open {\n  overflow: hidden;\n}\n\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n}\n\n.modal.fade .modal-dialog {\n  -webkit-transform: translate(0, -25%);\n      -ms-transform: translate(0, -25%);\n          transform: translate(0, -25%);\n  -webkit-transition: -webkit-transform 0.3s ease-out;\n     -moz-transition: -moz-transform 0.3s ease-out;\n       -o-transition: -o-transform 0.3s ease-out;\n          transition: transform 0.3s ease-out;\n}\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\n.modal-dialog {\n  z-index: 1050;\n  width: auto;\n  padding: 10px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.modal-content {\n  position: relative;\n  background-color: #ffffff;\n  border: 1px solid #999999;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n          box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n  background-clip: padding-box;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n\n.modal-backdrop.in {\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.modal-header {\n  min-height: 16.428571429px;\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n}\n\n.modal-header .close {\n  margin-top: -2px;\n}\n\n.modal-title {\n  margin: 0;\n  line-height: 1.428571429;\n}\n\n.modal-body {\n  position: relative;\n  padding: 20px;\n}\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\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n@media screen and (min-width: 768px) {\n  .modal-dialog {\n    right: auto;\n    left: 50%;\n    width: 600px;\n    padding-top: 30px;\n    padding-bottom: 30px;\n  }\n  .modal-content {\n    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n  }\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 12px;\n  line-height: 1.4;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-right .tooltip-arrow {\n  right: 5px;\n  bottom: 0;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\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: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\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\n.popover-content {\n  padding: 9px 14px;\n}\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\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n  content: \" \";\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n  content: \" \";\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n  content: \" \";\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n  content: \" \";\n}\n\n.alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  color: #c09853;\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  border-radius: 4px;\n}\n\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n\n.alert hr {\n  border-top-color: #f8e5be;\n}\n\n.alert .alert-link {\n  font-weight: bold;\n  color: #a47e3c;\n}\n\n.alert > p,\n.alert > ul {\n  margin-bottom: 0;\n}\n\n.alert > p + p {\n  margin-top: 5px;\n}\n\n.alert-dismissable {\n  padding-right: 35px;\n}\n\n.alert-dismissable .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n\n.alert-success .alert-link {\n  color: #356635;\n}\n\n.alert-danger {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger hr {\n  border-top-color: #e6c1c7;\n}\n\n.alert-danger .alert-link {\n  color: #953b39;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n\n.alert-info .alert-link {\n  color: #2d6987;\n}\n\n.thumbnail,\n.img-thumbnail {\n  padding: 4px;\n  line-height: 1.428571429;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\n.thumbnail {\n  display: block;\n}\n\n.thumbnail > img {\n  display: block;\n  height: auto;\n  max-width: 100%;\n}\n\n.img-thumbnail {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n}\n\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: #428bca;\n}\n\n.thumbnail > img {\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #333333;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media > .pull-left {\n  margin-right: 10px;\n}\n\n.media > .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n\n.label {\n  display: inline;\n  padding: .25em .6em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n}\n\n.label[href]:hover,\n.label[href]:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label:empty {\n  display: none;\n}\n\n.label-default {\n  background-color: #999999;\n}\n\n.label-default[href]:hover,\n.label-default[href]:focus {\n  background-color: #808080;\n}\n\n.label-primary {\n  background-color: #428bca;\n}\n\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n  background-color: #3071a9;\n}\n\n.label-success {\n  background-color: #5cb85c;\n}\n\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n\n.label-info {\n  background-color: #5bc0de;\n}\n\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\n\n.label-warning {\n  background-color: #f0ad4e;\n}\n\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n\n.label-danger {\n  background-color: #d9534f;\n}\n\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\n}\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: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n  border-radius: 10px;\n}\n\n.badge:empty {\n  display: none;\n}\n\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #ffffff;\n}\n\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\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\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\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\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, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  background-color: #428bca;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress-striped .progress-bar {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-size: 40px 40px;\n}\n\n.progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-bar-success {\n  background-color: #5cb85c;\n}\n\n.progress-striped .progress-bar-success {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n\n.progress-striped .progress-bar-info {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n\n.progress-striped .progress-bar-warning {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n\n.progress-striped .progress-bar-danger {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: block;\n  height: auto;\n  max-width: 100%;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\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: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.left {\n  background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%));\n  background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n\n.carousel-control.right {\n  right: 0;\n  left: auto;\n  background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%));\n  background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  z-index: 5;\n  display: inline-block;\n  width: 20px;\n  height: 20px;\n  margin-top: -10px;\n  margin-left: -10px;\n  font-family: serif;\n}\n\n.carousel-control .icon-prev:before {\n  content: '\\2039';\n}\n\n.carousel-control .icon-next:before {\n  content: '\\203a';\n}\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\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  border: 1px solid #ffffff;\n  border-radius: 10px;\n}\n\n.carousel-indicators .active {\n  width: 12px;\n  height: 12px;\n  margin: 0;\n  background-color: #ffffff;\n}\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: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n\n.carousel-caption .btn {\n  text-shadow: none;\n}\n\n@media screen and (min-width: 768px) {\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\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 2.1428571435;\n  color: inherit;\n  background-color: #eeeeee;\n}\n\n.jumbotron h1 {\n  line-height: 1;\n  color: inherit;\n}\n\n.jumbotron p {\n  line-height: 1.4;\n}\n\n@media screen and (min-width: 768px) {\n  .jumbotron {\n    padding: 50px 60px;\n    border-radius: 6px;\n  }\n  .jumbotron h1 {\n    font-size: 63px;\n  }\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  content: \" \";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.pull-right {\n  float: right !important;\n}\n\n.pull-left {\n  float: left !important;\n}\n\n.hide {\n  display: none !important;\n}\n\n.show {\n  display: block !important;\n}\n\n.invisible {\n  visibility: hidden;\n}\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\n.affix {\n  position: fixed;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\n@media screen and (max-width: 400px) {\n  @-ms-viewport {\n    width: 320px;\n  }\n}\n\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n.visible-xs {\n  display: block !important;\n}\n\ntr.visible-xs {\n  display: table-row !important;\n}\n\nth.visible-xs,\ntd.visible-xs {\n  display: table-cell !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-xs {\n    display: none !important;\n  }\n  tr.visible-xs {\n    display: none !important;\n  }\n  th.visible-xs,\n  td.visible-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-xs {\n    display: none !important;\n  }\n  tr.visible-xs {\n    display: none !important;\n  }\n  th.visible-xs,\n  td.visible-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-xs {\n    display: none !important;\n  }\n  tr.visible-xs {\n    display: none !important;\n  }\n  th.visible-xs,\n  td.visible-xs {\n    display: none !important;\n  }\n}\n\n.visible-sm {\n  display: none !important;\n}\n\ntr.visible-sm {\n  display: none !important;\n}\n\nth.visible-sm,\ntd.visible-sm {\n  display: none !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm {\n    display: block !important;\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\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-sm {\n    display: none !important;\n  }\n  tr.visible-sm {\n    display: none !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-sm {\n    display: none !important;\n  }\n  tr.visible-sm {\n    display: none !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: none !important;\n  }\n}\n\n.visible-md {\n  display: none !important;\n}\n\ntr.visible-md {\n  display: none !important;\n}\n\nth.visible-md,\ntd.visible-md {\n  display: none !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-md {\n    display: none !important;\n  }\n  tr.visible-md {\n    display: none !important;\n  }\n  th.visible-md,\n  td.visible-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md {\n    display: block !important;\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\n@media (min-width: 1200px) {\n  .visible-md {\n    display: none !important;\n  }\n  tr.visible-md {\n    display: none !important;\n  }\n  th.visible-md,\n  td.visible-md {\n    display: none !important;\n  }\n}\n\n.visible-lg {\n  display: none !important;\n}\n\ntr.visible-lg {\n  display: none !important;\n}\n\nth.visible-lg,\ntd.visible-lg {\n  display: none !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-lg {\n    display: none !important;\n  }\n  tr.visible-lg {\n    display: none !important;\n  }\n  th.visible-lg,\n  td.visible-lg {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-lg {\n    display: none !important;\n  }\n  tr.visible-lg {\n    display: none !important;\n  }\n  th.visible-lg,\n  td.visible-lg {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-lg {\n    display: block !important;\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\n.hidden-xs {\n  display: none !important;\n}\n\ntr.hidden-xs {\n  display: none !important;\n}\n\nth.hidden-xs,\ntd.hidden-xs {\n  display: none !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-xs {\n    display: block !important;\n  }\n  tr.hidden-xs {\n    display: table-row !important;\n  }\n  th.hidden-xs,\n  td.hidden-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-xs {\n    display: block !important;\n  }\n  tr.hidden-xs {\n    display: table-row !important;\n  }\n  th.hidden-xs,\n  td.hidden-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-xs {\n    display: block !important;\n  }\n  tr.hidden-xs {\n    display: table-row !important;\n  }\n  th.hidden-xs,\n  td.hidden-xs {\n    display: table-cell !important;\n  }\n}\n\n.hidden-sm {\n  display: block !important;\n}\n\ntr.hidden-sm {\n  display: table-row !important;\n}\n\nth.hidden-sm,\ntd.hidden-sm {\n  display: table-cell !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-sm {\n    display: none !important;\n  }\n  tr.hidden-sm {\n    display: none !important;\n  }\n  th.hidden-sm,\n  td.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-sm {\n    display: block !important;\n  }\n  tr.hidden-sm {\n    display: table-row !important;\n  }\n  th.hidden-sm,\n  td.hidden-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-sm {\n    display: block !important;\n  }\n  tr.hidden-sm {\n    display: table-row !important;\n  }\n  th.hidden-sm,\n  td.hidden-sm {\n    display: table-cell !important;\n  }\n}\n\n.hidden-md {\n  display: block !important;\n}\n\ntr.hidden-md {\n  display: table-row !important;\n}\n\nth.hidden-md,\ntd.hidden-md {\n  display: table-cell !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-md {\n    display: block !important;\n  }\n  tr.hidden-md {\n    display: table-row !important;\n  }\n  th.hidden-md,\n  td.hidden-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-md {\n    display: none !important;\n  }\n  tr.hidden-md {\n    display: none !important;\n  }\n  th.hidden-md,\n  td.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-md {\n    display: block !important;\n  }\n  tr.hidden-md {\n    display: table-row !important;\n  }\n  th.hidden-md,\n  td.hidden-md {\n    display: table-cell !important;\n  }\n}\n\n.hidden-lg {\n  display: block !important;\n}\n\ntr.hidden-lg {\n  display: table-row !important;\n}\n\nth.hidden-lg,\ntd.hidden-lg {\n  display: table-cell !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-lg {\n    display: block !important;\n  }\n  tr.hidden-lg {\n    display: table-row !important;\n  }\n  th.hidden-lg,\n  td.hidden-lg {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-lg {\n    display: block !important;\n  }\n  tr.hidden-lg {\n    display: table-row !important;\n  }\n  th.hidden-lg,\n  td.hidden-lg {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-lg {\n    display: none !important;\n  }\n  tr.hidden-lg {\n    display: none !important;\n  }\n  th.hidden-lg,\n  td.hidden-lg {\n    display: none !important;\n  }\n}\n\n.visible-print {\n  display: none !important;\n}\n\ntr.visible-print {\n  display: none !important;\n}\n\nth.visible-print,\ntd.visible-print {\n  display: none !important;\n}\n\n@media print {\n  .visible-print {\n    display: block !important;\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  .hidden-print {\n    display: none !important;\n  }\n  tr.hidden-print {\n    display: none !important;\n  }\n  th.hidden-print,\n  td.hidden-print {\n    display: none !important;\n  }\n}"
  },
  {
    "path": "site/css/carousel.css",
    "content": "/* GLOBAL STYLES\n-------------------------------------------------- */\n/* Padding below the footer and lighter body text */\n\nbody {\n  padding-bottom: 40px;\n  color: #5a5a5a;\n}\n\n\n\n/* CUSTOMIZE THE NAVBAR\n-------------------------------------------------- */\n\n/* Special class on .container surrounding .navbar, used for positioning it into place. */\n.navbar-wrapper {\n  position: relative;\n  z-index: 15;\n}\n\n\n\n/* CUSTOMIZE THE CAROUSEL\n-------------------------------------------------- */\n\n/* Carousel base class */\n.carousel {\n  padding-top: 60px;\n  padding-bottom: 60px;\n  background: #ccc;\n\n  /* Negative margin to pull up carousel. 90px is roughly margins and height of navbar. */\n  /*margin-top: -90px;*/\n}\n/* Since positioning the image, we need to help out the caption */\n.carousel-caption {\n  z-index: 10;\n}\n\n/* Declare heights because of positioning of img element */\n.carousel .item {\n  height: 500px;\n}\n.carousel-inner > .item > img {\n  position: absolute;\n  top: 0;\n  left: 0;\n  min-width: 100%;\n  height: 500px;\n}\n\n\n\n/* MARKETING CONTENT\n-------------------------------------------------- */\n\n/* Pad the edges of the mobile views a bit */\n.marketing {\n  padding-left: 15px;\n  padding-right: 15px;\n}\n\n/* Center align the text within the three columns below the carousel */\n.marketing .col-lg-4 {\n  text-align: center;\n  margin-bottom: 20px;\n}\n.marketing h2 {\n  font-weight: normal;\n}\n.marketing .col-lg-4 p {\n  margin-left: 10px;\n  margin-right: 10px;\n}\n\n\n/* Featurettes\n------------------------- */\n\n.featurette-divider {\n  margin: 80px 0; /* Space out the Bootstrap <hr> more */\n}\n.featurette {\n  padding-top: 120px; /* Vertically center images part 1: add padding above and below text. */\n  overflow: hidden; /* Vertically center images part 2: clear their floats. */\n}\n.featurette-image {\n  margin-top: -120px; /* Vertically center images part 3: negative margin up the image the same amount of the padding to center it. */\n}\n\n/* Give some space on the sides of the floated elements so text doesn't run right into it. */\n.featurette-image.pull-left {\n  margin-right: 40px;\n}\n.featurette-image.pull-right {\n  margin-left: 40px;\n}\n\n/* Thin out the marketing headings */\n.featurette-heading {\n  font-size: 50px;\n  font-weight: 300;\n  line-height: 1;\n  letter-spacing: -1px;\n}\n\n\n\n/* RESPONSIVE CSS\n-------------------------------------------------- */\n\n@media (min-width: 768px) {\n\n  /* Remve the edge padding needed for mobile */\n  .marketing {\n    padding-left: 0;\n    padding-right: 0;\n  }\n\n  /* Navbar positioning foo */\n  .navbar-wrapper {\n    margin-top: 20px;\n  }\n  /* The navbar becomes detached from the top, so we round the corners */\n  .navbar-wrapper .navbar {\n    border-radius: 4px;\n  }\n\n  /* Bump up size of carousel content */\n  .carousel-caption p {\n    margin-bottom: 20px;\n    font-size: 21px;\n    line-height: 1.4;\n  }\n\n}\n"
  },
  {
    "path": "site/css/docco.css",
    "content": "/*--------------------- Typography ----------------------------*/\n/*\n@font-face {\n    font-family: 'aller-light';\n    src: url('public/fonts/aller-light.eot');\n    src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'),\n         url('public/fonts/aller-light.woff') format('woff'),\n         url('public/fonts/aller-light.ttf') format('truetype');\n    font-weight: normal;\n    font-style: normal;\n}\n\n@font-face {\n    font-family: 'aller-bold';\n    src: url('public/fonts/aller-bold.eot');\n    src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'),\n         url('public/fonts/aller-bold.woff') format('woff'),\n         url('public/fonts/aller-bold.ttf') format('truetype');\n    font-weight: normal;\n    font-style: normal;\n}\n\n@font-face {\n    font-family: 'novecento-bold';\n    src: url('public/fonts/novecento-bold.eot');\n    src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'),\n         url('public/fonts/novecento-bold.woff') format('woff'),\n         url('public/fonts/novecento-bold.ttf') format('truetype');\n    font-weight: normal;\n    font-style: normal;\n}\n*/\n/*--------------------- Layout ----------------------------*/\n/*\nhtml { height: 100%; }\nbody {\n  font-family: \"aller-light\";\n  font-size: 14px;\n  line-height: 18px;\n  color: #30404f;\n  margin: 0; padding: 0;\n  height:100%;\n}\n#container { min-height: 100%; }\n\na {\n  color: #000;\n}\n\nb, strong {\n  font-weight: normal;\n  font-family: \"aller-bold\";\n}\n\np, ul, ol {\n  margin: 15px 0 0px;\n}\n\nh1, h2, h3, h4, h5, h6 {\n  color: #112233;\n  line-height: 1em;\n  font-weight: normal;\n  font-family: \"novecento-bold\";\n  text-transform: uppercase;\n  margin: 30px 0 15px 0;\n}\n\nh1 {\n  margin-top: 40px;\n}\n\nhr {\n  border: 0;\n  background: 1px solid #ddd;\n  height: 1px;\n  margin: 20px 0;\n}\n*/\n\npre, tt, code {\n  font-size: 12px; line-height: 16px;\n  font-family: Menlo, Monaco, Consolas, \"Lucida Console\", monospace;\n  margin: 0; padding: 0;\n  border: none;\n}\n  .annotation pre {\n    display: block;\n    margin: 0;\n    padding: 7px 10px;\n    background: #fcfcfc;\n    -moz-box-shadow:    inset 0 0 10px rgba(0,0,0,0.1);\n    -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1);\n    box-shadow:         inset 0 0 10px rgba(0,0,0,0.1);\n    overflow-x: auto;\n  }\n    .annotation pre code {\n      border: 0;\n      padding: 0;\n      background: transparent;\n    }\n\n\nblockquote {\n  border-left: 5px solid #ccc;\n  margin: 0;\n  padding: 1px 0 1px 1em;\n}\n  .sections blockquote p {\n    font-family: Menlo, Consolas, Monaco, monospace;\n    font-size: 12px; line-height: 16px;\n    color: #999;\n    margin: 10px 0 0;\n    white-space: pre-wrap;\n  }\n\nul.sections {\n  list-style: none;\n  padding:0 0 5px 0;;\n  margin:0;\n}\n\n/*\n  Force border-box so that % widths fit the parent\n  container without overlap because of margin/padding.\n\n  More Info : http://www.quirksmode.org/css/box.html\n*/\nul.sections > li > div {\n  -moz-box-sizing: border-box;    /* firefox */\n  -ms-box-sizing: border-box;     /* ie */\n  -webkit-box-sizing: border-box; /* webkit */\n  -khtml-box-sizing: border-box;  /* konqueror */\n  box-sizing: border-box;         /* css3 */\n}\n\n\n/*---------------------- Jump Page -----------------------------*/\n#jump_to, #jump_page {\n  margin: 0;\n  background: white;\n  -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;\n  -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;\n  font: 16px Arial;\n  cursor: pointer;\n  text-align: right;\n  list-style: none;\n}\n\n#jump_to a {\n  text-decoration: none;\n}\n\n#jump_to a.large {\n  display: none;\n}\n#jump_to a.small {\n  font-size: 22px;\n  font-weight: bold;\n  color: #676767;\n}\n\n#jump_to, #jump_wrapper {\n  position: fixed;\n  right: 0; top: 0;\n  padding: 10px 15px;\n  margin:0;\n}\n\n#jump_wrapper {\n  display: none;\n  padding:0;\n}\n\n#jump_to:hover #jump_wrapper {\n  display: block;\n}\n\n#jump_page {\n  padding: 5px 0 3px;\n  margin: 0 0 25px 25px;\n}\n\n#jump_page .source {\n  display: block;\n  padding: 15px;\n  text-decoration: none;\n  border-top: 1px solid #eee;\n}\n\n#jump_page .source:hover {\n  background: #f5f5ff;\n}\n\n#jump_page .source:first-child {\n}\n\n/*---------------------- Low resolutions (> 320px) ---------------------*/\n@media only screen and (min-width: 320px) {\n  .pilwrap { display: none; }\n\n  ul.sections > li > div {\n    display: block;\n    padding:5px 10px 0 10px;\n  }\n\n  ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol {\n    padding-left: 30px;\n  }\n\n  ul.sections > li > div.content {\n    background: #f5f5ff;\n    overflow-x:auto;\n    -webkit-box-shadow: inset 0 0 5px #e5e5ee;\n    box-shadow: inset 0 0 5px #e5e5ee;\n    border: 1px solid #dedede;\n    /*margin:5px 10px 5px 10px;*/\n    /*padding-bottom: 5px;*/\n  }\n\n  ul.sections > li > div.annotation pre {\n    margin: 7px 0 7px;\n    padding-left: 15px;\n  }\n\n  ul.sections > li > div.annotation p tt, .annotation code {\n    background: #f8f8ff;\n    border: 1px solid #dedede;\n    font-size: 12px;\n    padding: 0 0.2em;\n  }\n}\n\n/*----------------------  (> 481px) ---------------------*/\n@media only screen and (min-width: 481px) {\n  #container {\n    position: relative;\n  }\n  body {\n    background-color: #FFFFFF;\n    font-size: 15px;\n    line-height: 21px;\n  }\n  pre, tt, code {\n    line-height: 18px;\n  }\n  p, ul, ol {\n    margin: 0 0 15px;\n  }\n\n\n  #jump_to {\n    padding: 5px 10px;\n  }\n  #jump_wrapper {\n    padding: 0;\n  }\n  #jump_to, #jump_page {\n    font: 10px Arial;\n    text-transform: uppercase;\n  }\n  #jump_page .source {\n    padding: 5px 10px;\n  }\n  #jump_to a.large {\n    display: inline-block;\n  }\n  #jump_to a.small {\n    display: none;\n  }\n\n\n\n  #background {\n    position: absolute;\n    top: 0; bottom: 0;\n    width: 350px;\n    background: #fff;\n    border-right: 1px solid #e5e5ee;\n    z-index: -1;\n  }\n\n  ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol {\n    padding-left: 40px;\n  }\n\n  ul.sections > li {\n    white-space: nowrap;\n  }\n\n  ul.sections > li > div {\n    display: inline-block;\n  }\n\n  ul.sections > li > div.annotation {\n    max-width: 350px;\n    min-width: 350px;\n    min-height: 5px;\n    padding: 13px;\n    overflow-x: hidden;\n    white-space: normal;\n    vertical-align: top;\n    text-align: left;\n  }\n  ul.sections > li > div.annotation pre {\n    margin: 15px 0 15px;\n    padding-left: 15px;\n  }\n\n  ul.sections > li > div.content {\n    /*padding: 13px;*/\n    vertical-align: top;\n    background: #f5f5ff;\n    border: none;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n  }\n\n  .pilwrap {\n    position: relative;\n    display: inline;\n  }\n\n  .pilcrow {\n    font: 12px Arial;\n    text-decoration: none;\n    color: #454545;\n    position: absolute;\n    top: 3px; left: -20px;\n    padding: 1px 2px;\n    opacity: 0;\n    -webkit-transition: opacity 0.2s linear;\n  }\n    .for-h1 .pilcrow {\n      top: 47px;\n    }\n    .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow {\n      top: 35px;\n    }\n\n  ul.sections > li > div.annotation:hover .pilcrow {\n    opacity: 1;\n  }\n}\n\n/*---------------------- (> 1025px) ---------------------*/\n@media only screen and (min-width: 1025px) {\n\n  body {\n    font-size: 16px;\n    line-height: 24px;\n  }\n\n  #background {\n    width: 525px;\n  }\n  ul.sections > li > div.annotation {\n    max-width: 525px;\n    min-width: 525px;\n    padding: 10px 25px 1px 50px;\n  }\n  ul.sections > li > div.content {\n    /*padding: 9px 15px 16px 25px;*/\n  }\n}\n\n/*---------------------- Syntax Highlighting -----------------------------*/\n\ntd.linenos { background-color: #f0f0f0; padding-right: 10px; }\nspan.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n/*\n\ngithub.com style (c) Vasily Polovnyov <vast@whiteants.net>\n\n*/\n\npre code {\n  display: block; padding: 0.5em;\n  color: #000;\n  background: #f8f8ff\n}\n\npre .comment,\npre .template_comment,\npre .diff .header,\npre .javadoc {\n  color: #408080;\n  font-style: italic\n}\n\npre .keyword,\npre .assignment,\npre .literal,\npre .css .rule .keyword,\npre .winutils,\npre .javascript .title,\npre .lisp .title,\npre .subst {\n  color: #954121;\n  /*font-weight: bold*/\n}\n\npre .number,\npre .hexcolor {\n  color: #40a070\n}\n\npre .string,\npre .tag .value,\npre .phpdoc,\npre .tex .formula {\n  color: #219161;\n}\n\npre .title,\npre .id {\n  color: #19469D;\n}\npre .params {\n  color: #00F;\n}\n\npre .javascript .title,\npre .lisp .title,\npre .subst {\n  font-weight: normal\n}\n\npre .class .title,\npre .haskell .label,\npre .tex .command {\n  color: #458;\n  font-weight: bold\n}\n\npre .tag,\npre .tag .title,\npre .rules .property,\npre .django .tag .keyword {\n  color: #000080;\n  font-weight: normal\n}\n\npre .attribute,\npre .variable,\npre .instancevar,\npre .lisp .body {\n  color: #008080\n}\n\npre .regexp {\n  color: #B68\n}\n\npre .class {\n  color: #458;\n  font-weight: bold\n}\n\npre .symbol,\npre .ruby .symbol .string,\npre .ruby .symbol .keyword,\npre .ruby .symbol .keymethods,\npre .lisp .keyword,\npre .tex .special,\npre .input_number {\n  color: #990073\n}\n\npre .builtin,\npre .constructor,\npre .built_in,\npre .lisp .title {\n  color: #0086b3\n}\n\npre .preprocessor,\npre .pi,\npre .doctype,\npre .shebang,\npre .cdata {\n  color: #999;\n  font-weight: bold\n}\n\npre .deletion {\n  background: #fdd\n}\n\npre .addition {\n  background: #dfd\n}\n\npre .diff .change {\n  background: #0086b3\n}\n\npre .chunk {\n  color: #aaa\n}\n\npre .tex .formula {\n  opacity: 0.5;\n}\n"
  },
  {
    "path": "site/css/grid.css",
    "content": "/*THESE ARE GUIDELINES*/\n\n.container {\n/*  padding-left: 15px;\n  padding-right: 15px;*/\n}\n\n.row {\n  margin-bottom: 20px;\n}\n.row .row {\n  margin-top: 10px;\n  margin-bottom: 0;\n}\n[class*=\"col-\"] {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  border: 1px solid #ddd;\n  /*background-color: rgba(0,0,0,.15);*/\n  border: 0px solid rgba(86,61,124,.2);\n}\n\nhr {\n  margin-top: 40px;\n  margin-bottom: 40px;\n}"
  },
  {
    "path": "site/css/jumbotron.css",
    "content": "body {\n  padding-bottom: 20px;\n}\n\n/* Wrapping element */\n/* Set some basic padding to keep content from hitting the edges */\n.body-content {\n  padding-left: 15px;\n  padding-right: 15px;\n}\n\n/* Responsive: Portrait tablets and up */\n@media screen and (min-width: 768px) {\n  /* Let the jumbotron breathe */\n  .jumbotron {\n    margin-top: 20px;\n  }\n  /* Remove padding from wrapping element since we kick in the grid classes here */\n  .body-content {\n    padding: 0;\n  }\n}"
  },
  {
    "path": "site/css/responsive-video.css",
    "content": "\n/*Courtesy of\nhttps://gist.github.com/jgarber/2302238*/\n\n.flex-video {\n  position: relative;\n  padding-top: 25px;\n  padding-bottom: 67.5%;\n  height: 0;\n  margin-bottom: 16px;\n  overflow: hidden;\n}\n \n.flex-video.widescreen { padding-bottom: 57.25%; }\n.flex-video.vimeo { padding-top: 0; }\n \n.flex-video iframe,\n.flex-video object,\n.flex-video embed {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n@media only screen and (max-device-width: 800px), only screen and (device-width: 1024px) and (device-height: 600px), only screen and (width: 1280px) and (orientation: landscape), only screen and (device-width: 800px), only screen and (max-width: 767px) {\n  .flex-video { padding-top: 0; }\n}"
  },
  {
    "path": "site/css/style.css",
    "content": "/*\nColor palette based on Mozilla Style guide\nhttp://www.mozilla.org/en-US/styleguide/identity/firefox/color/\n\nBlue\n#0095DD\n\nOrange\n#FF9500\n\nDark Grey\n#3A4349\n\nRed\n#DC3726\n\nGreen\n#49BA7C\n\n*/\n\n\n/* =Global\n----------------------------------------------- */\n@font-face {\n  font-family: openSansRegular;\n  src: url('../../togetherjs/fonts/OpenSans-Regular.ttf');\n}\n\n@font-face {\n  font-family: openSansLight;\n  src: url('../../togetherjs/fonts/OpenSans-Light.ttf');\n}\n\n@font-face {\n  font-family: openSansBold;\n  src: url('../../togetherjs/fonts/OpenSans-Bold.ttf');\n}\n\nbody {\n  background-color: rgb(255, 255, 255);\n  font: 300 16px/24px openSansLight, 'Open Sans', sans-serif;\n}\n\np {\n  color: rgb(51, 51, 51);\n  font-family: 'Open Sans', sans-serif;\n  font-size: 16px;\n  line-height: 24px;\n}\n\na {\n  line-height: 1.38;\n  font-size: 14px;\n  font-family: openSansRegular, 'Open Sans', sans-serif;\n}\n\na:hover {\n  text-decoration: underline;\n}\n\nbutton {\n  padding-bottom: 2px;\n  background-color: #49BA7C;\n  font-weight: bold;\n  text-align: center;\n  color: rgb(22, 22, 22);\n  font-family: openSansLight, 'Open Sans', sans-serif;\n}\n\n.btn-primary {\n  background: #49BA7C;\n  border-color: #2aa08b;\n}\n\n.btn-primary:hover {\n  background: #74C593;\n  border-color: #34b7a0;\n}\n\nfooter a {\n  color: #0095DD;\n  text-decoration: none;\n}\n\nfooter a:hover {\n  color: #008bb2;\n}\n\n.large {\n  color: rgb(72, 72, 72);\n  display: block;\n  font-family: 'Open Sans Light', sans-serif;\n  font-weight: normal;\n  line-height: 68px;\n  margin: 20px 0px;\n}\n\nh1 {\n  color: rgb(72, 72, 72);\n  display: block;\n  font-family: 'Open Sans Light', sans-serif;\n  font-weight: normal;\n  letter-spacing: -2px;\n  line-height: 48px;\n  margin: 40px 0px;\n}\n\nh2 {\n  color: rgb(72, 72, 72);\n  display: block;\n  font-family: 'Open Sans Light', sans-serif;\n  font-weight: normal;\n  letter-spacing: -1px;\n  line-height: 32px;\n}\n\nh3 {\n  color: rgb(72, 72, 72);\n  display: block;\n  font-family: 'Open Sans Light', sans-serif;\n  font-weight: normal;\n  letter-spacing: normal;\n  line-height: 28px;\n}\n\nh4 {\n  color: rgb(72, 72, 72);\n  display: block;\n  font-family: 'Open Sans Light', sans-serif;\n  font-weight: normal;\n  letter-spacing: normal;\n  line-height: 20px;\n}\n\nh5 {\n  color: rgb(72, 72, 72);\n  display: block;\n  font-family: 'Open Sans Light', sans-serif;\n  font-weight: bold;\n  letter-spacing: normal;\n}\n\n.small, small {\n  color: rgb(51, 51, 51);\n  display: block;\n  font-family: 'Open Sans', sans-serif;\n  font-size: 12px;\n  line-height: 16px;\n}\n\n.form-control:focus {\n  border: 1px solid #2aa08b;\n  box-shadow: none;\n}\n\n/* =Tabzilla\n----------------------------------------------- */\n#tabzilla-panel,\n#tabzilla-panel *,\n#tabzilla-panel *:before,\n#tabzilla-panel *:after {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n#tabzilla-panel a {\n  font-size: 11px;\n  line-height: 12px;\n}\n\n\n/* =Header\n----------------------------------------------- */\n\n.main-header {\n  background-color: #3A4349;\n  display: block;\n  font-family: sans-serif;\n}\n\n.main-header a.main-logo {\n  width: 48px;\n  height: 48px;\n  border-radius: 50%;\n  border: 0px solid white;\n  background: url('../images/togetherjs-logo@2x.png');\n  background-size: 50% 50%;\n  background-repeat: no-repeat;\n  background-position: center center;\n  text-indent: -9999px;\n  float: left;\n  margin: 8px 0px;\n  padding: 0;\n  -webkit-transition: all 0.4s ease;\n  -moz-transition: all 0.4s ease;\n  transition: all 0.4s ease;\n  overflow: hidden;\n  -webkit-background-clip: padding-box;\n  -moz-background-clip:    padding;\n  background-clip:         padding-box;\n}\n\n/*.main-header a.main-logo:hover,\n.main-header a.main-logo:active {\n  background-color: #38c4ac;\n  -webkit-background-clip: padding-box;\n  -moz-background-clip:    padding;\n  background-clip:         padding-box;\n}*/\n\n.main-header .masthead-title {\n  font-size: 14px;\n  text-transform: uppercase;\n  font-weight: 100;\n  color: #fff;\n  margin: 7px -2px 0px;\n  letter-spacing: 1px;\n}\n\n/*.main-header .masthead-title:hover {\n  color: #f1f1f1;\n}*/\n\n.main-header .main-nav li a {\n  color: rgb(255,255,255);\n  opacity: 0.5;\n}\n\n.main-header .main-nav li a:hover {\n  color: rgb(255, 255, 255);\n  opacity: 1;\n}\n\n.main-header .navbar-header {\n  padding-left: 0px;\n}\n\n.main-header .navbar-nav > .active > a {\n  color: rgb(255, 255, 255);\n  opacity: 1;\n  background: none;\n}\n\n.main-header .main-nav li a.active {\n  color: rgb(255,255,255);\n  opacity: 1;\n}\n\n.navbar {\n  border: 0;\n  border-radius: 0;\n  margin-bottom: 0;\n}\n\n.main-header .main-nav {\n  padding: 6px 0px;\n}\n\n.main-header .navbar-toggle {\n  width: 44px;\n  background: rgb(72, 72, 72);\n  margin-top: 13px;\n  border: 1px solid #282a2c;\n}\n\n.main-header.navbar-inverse .navbar-collapse {\n  border-color: #000;\n}\n\n.navbar-collapse {\n  border-top: 1px solid #282a2c;\n}\n\n\n/* =Carousel\n----------------------------------------------- */\n\n#hero {\n  background: url('../images/bg@2x.png') 50% 0 no-repeat fixed;\n  background-size: 2042px 606px;\n\tmargin: 0px auto;\n  width: 100%;\n  //max-width: 1920px;\n  position: relative;\n}\n\n/*\n.hero {\n  .at2x('../images/bg.png', 200px, 100px);\n}\n*/\n\n#hero-section {\n  margin-bottom: 0px;\n}\n\n.hero-header-text {\n  color: rgb(255, 255, 255);\n}\n\n.hero-tagline {\n  color: rgb(255, 255, 255);\n  margin-bottom: 20px;\n  line-height: 24px;\n}\n\n#hero .container {\n  padding-top: 20px;\n}\n\n#box-left {\n  margin-top: 3%;\n}\n\n#video-area {\n  cursor: pointer;\n}\n\n#video-area img {\n  width: 100%;\n}\n\n\n\n/* =modal video\n----------------------------------------------- */\n\n#marketing-video {\n  background: rgba(0,0,0,0.8);\n  display: none;\n  position: absolute;\n  left: 0px;\n  top: 0px;\n  z-index: 99;\n  width: 100%;\n  height: 100%;\n  margin-bottom: 200px;\n}\n\n#marketing-video #frame-video {\n  padding-top: 30px;\n}\n\n.video-closebtn {\n  color: rgba(255, 255, 255, 0.5);\n  float: right;\n  cursor: pointer;\n}\n\n/* =main section\n----------------------------------------------- */\n\n#main-section .header-text {\n  margin: 40px 0px;\n}\n\n#main-section h3 {\n  color: rgb(22, 22, 22);\n  font-family: 'Open Sans Light',sans-serif;\n  font-size: 32px;\n  font-size-adjust: none;\n  font-stretch: normal;\n  font-style: normal;\n  font-variant: normal;\n  font-weight: 100;\n  margin: 40px 0px 20px;\n}\n\n#main-section p {\n  color: rgb(22, 22, 22);\n  font-family: 'Open Sans Regular',sans-serif;\n  font-size: 16px;\n  line-height: 27px;\n}\n\n#main-section #text-descrip {\n  margin: 0 15%;\n}\n\n#main-section h4 {\n  margin-top: 20px;\n  font-family: openSansBold, sans-serif;\n  text-transform: uppercase;\n  font-size: 12px;\n  font-weight: 600;\n  letter-spacing: 1px;\n  line-height: 16px;\n}\n\n/* =tour section\n----------------------------------------------- */\n\n#main-section img.why-section {\n  width: 40%;\n  height: 40%;\n  margin: 0 auto;\n}\n\n#tour h3 {\n  margin-top: 60px;\n  margin-bottom: 10px;\n}\n\n.why-connect-01 img {\n  opacity: 0;\n  position: relative;\n  top: 20px;\n}\n\n.why-connect-02 img {\n  opacity: 0;\n  position: relative;\n  top: 20px;\n}\n\n.why-connect-03 img {\n  opacity: 0;\n  position: relative;\n  top: 20px;\n}\n\n#main-section #tour img.how-section {\n  width: 100%;\n  margin: 0 auto;\n}\n\n#howto-table {\n  position: relative;\n}\n\n#howto-table td {\n  border-top: 0px;\n}\n\n.howto-animation-01 p.smtextright {\n  width: 60%;\n  float: right;\n}\n\n.howto-animation-02 p.smtextleft {\n  width: 60%;\n  float: left;\n}\n\n.howto-animation-03 p.smtextright {\n  width: 60%;\n  float: right;\n}\n\n.how-section-imganim-01 {\n  position: absolute;\n  top: 46%;\n  left: 11%;\n  z-index: 8;\n  width: 12%;\n}\n\n.how-section-imganim-02 {\n  position: absolute;\n  top: 26%;\n  left: 6%;\n  z-index: 7;\n  width: 12%;\n}\n\n.how-section-imganim-03 {\n  position: absolute;\n  top: 40%;\n  right: 45%;\n  z-index: 7;\n  width: 10%;\n  display: none;\n}\n\n.how-section-btncollab {\n  position: absolute;\n  top: 36%;\n  left: 20%;\n  width: 10%;\n}\n\n.how-section-btncollabpressed {\n  position: absolute;\n  top: 36%;\n  left: 20%;\n  width: 10%;\n  display: none;\n}\n\n.how-section-dockplacement {\n  position: absolute;\n  top: 34%;\n  left: 51%;\n  width: 30%;\n  display: none;\n}\n\n.cursor-placement-01 {\n  width: 8%;\n  left: 78%;\n  top: 33%;\n  position: absolute;\n}\n\n.cursor-placement-04 {\n  width: 8%;\n  left: 69%;\n  top: 27%;\n  position: absolute;\n}\n\n.cursor-placement-02 {\n  width: 10%;\n  position: absolute;\n  top: 57%;\n  left: 32%;\n}\n\n\n.cursor-placement-03 {\n  width: 10%;\n  position: absolute;\n  top: 65%;\n  left: 44%;\n}\n\n\n/* =examples section\n----------------------------------------------- */\n\n#main-section #examples img {\n  width: 50%;\n  margin: 0 auto;\n  background: #efefef;\n}\n\n#main-section #examples .ex-description {\n  min-height: 50px;\n}\n\n/* =customers section\n----------------------------------------------- */\n\n#main-section #customers img {\n  width: 100%;\n  margin: 0 auto;\n  background: #efefef;\n}\n\n#main-section #customers p.text-center {\n  margin: 0px 15%;\n}\n\n/* =features section\n----------------------------------------------- */\n\n#main-section #features img {\n  width: 64px;\n  height: 64px;\n}\n\n/* =tryitnow section\n----------------------------------------------- */\n\n#tryitout pre {\n  margin-top: 50px;\n}\n\n/* =footer section\n----------------------------------------------- */\n\n#footer a img {\n  width: 50%;\n}\n\n#footer .ph-credit {\n  color: rgba(72, 72, 72, 1);\n  font-size: 10px;\n  margin-top: 20px;\n}\n\n\n/* =app examples\n----------------------------------------------- */\n\n.app-example {\n  padding: 0px;\n}\n\n.app-example iframe {\n\n}\n\n.app-example .top-bar {\n  width: 100%;\n  background: #c8c8c8;\n  height: 30px;\n  border-top-left-radius: 4px;\n  border-top-right-radius: 4px;\n}\n\n.app-example .top-bar .red-circle {\n  text-shadow: none;\n  width: 30px;\n  height: 30px;\n  font-size: 20px;\n}\n\n.app-example .top-bar .yellow-circle {\n  margin: 10px 6px;\n  border-radius: 50px;\n  width: 10px;\n  height: 10px;\n  background: #e6c646;\n  border: none;\n  padding: 4px;\n  display: none;\n}\n\n.app-example .top-bar .yellow-circle:hover {\n cursor: default;\n display: none;\n}\n\n.app-example .top-bar .green-circle {\n  margin: 10px 6px;\n  border-radius: 50%;\n  width: 10px;\n  height: 10px;\n  background: #5ccc8b;\n  border: none;\n  padding: 4px;\n  display: none;\n}\n\n.app-example .top-bar .green-circle:hover {\n cursor: default;\n display: none;\n}\n\n.app-example .address-bar {\n  padding: 14px;\n  background: #e6e6e6;\n}\n\n.app-example .address-bar input:hover {\n cursor: default;\n}\n\n.app-example .modal-header {\n  padding: 0px;\n}\n\n.app-example .modal-body {\n  padding: 0px;\n}\n\n.app-example .modal-footer {\n  margin-top: 0px;\n}\n\n.app-example .col-xs-12 {\n  padding: 0px;\n  height: 600px;\n}\n\n\n/* =animations\n----------------------------------------------- */\n\n.hero-header-text\n{\n  position:relative;\n  animation:moveDown 1s 1;\n  -webkit-animation:moveDown 1s 1; /*Safari and Chrome*/\n}\n\n@keyframes moveDown\n{\n  from {top:-10px; opacity: 0;}\n  to {top:0px; opacity: 1;}\n}\n\n@-webkit-keyframes moveDown /*Safari and Chrome*/\n{\n  from {top:-10px; opacity: 0;}\n  to {top:0px; opacity: 1;}\n}\n\n.hero-tagline\n{\n  position:relative;\n  animation:moveUp 1s 1;\n  -webkit-animation:moveUp 1s 1; /*Safari and Chrome*/\n}\n\n@keyframes moveUp\n{\n  from {top:20px; opacity: 0;}\n  to {top:0px; opacity: 1;}\n}\n\n@-webkit-keyframes moveUp /*Safari and Chrome*/\n{\n  from {top:20px; opacity: 0;}\n  to {top:0px; opacity: 1;}\n}\n\n.main-get-started\n{\n  position:relative;\n  animation:moveUp 1s 1;\n  -webkit-animation:moveUp 1s 1; /*Safari and Chrome*/\n}\n\n@keyframes moveUp\n{\n  from {top:20px; opacity: 0;}\n  to {top:0px; opacity: 1;}\n}\n\n@-webkit-keyframes moveUp /*Safari and Chrome*/\n{\n  from {top:20px; opacity: 0;}\n  to {top:0px; opacity: 1;}\n}\n\n\n#video-area {\n  position:relative;\n  animation:moveRight 1s 1;\n  -webkit-animation:moveRight 1s 1; /*Safari and Chrome*/\n}\n\n@keyframes moveRight\n{\n  from {right:-200px; opacity: 0;}\n  to {right:0px; opacity: 1;}\n}\n\n@-webkit-keyframes moveRight /*Safari and Chrome*/\n{\n  from {right:-200px; opacity: 0;}\n  to {right:0px; opacity: 1;}\n}\n\n\n\n/* =responsive hacks\n----------------------------------------------- */\n\n/* Extra small devices (phones, up to 480px) */\n@media (max-width: 480px) {\n\n  #features .media > .pull-left {\n    margin-top: 20px;\n  }\n\n  #howto-table td {\n    width: 50%;\n  }\n\n  .cursor-placement-01 {\n    top: 25% !important;\n    left: 78%;\n  }\n\n  .cursor-placement-04 {\n    top: 19%;\n    left: 69%;\n  }\n\n  .cursor-placement-02 {\n    top: 62% !important;\n    left: 42%;\n  }\n\n  .cursor-placement-03 {\n    top: 45% !important;\n    left: 50%;\n  }\n\n  .how-section-btncollab {\n    top: 32% !important;\n  }\n\n  .how-section-btncollabpressed {\n    top: 32% !important;\n  }\n\n  .how-section-dockplacement {\n    top: 28% !important;\n  }\n\n  .how-section-imganim-01 {\n    top: 46% !important;\n  }\n\n  .how-section-imganim-02 {\n    top: 26% !important;\n  }\n\n  .how-section-imganim-03 {\n    top: 40% !important;\n  }\n\n  .howto-animation-01 p.smtextright {\n    width: auto;\n    float: none;\n  }\n\n  .howto-animation-02 p.smtextleft {\n    width: auto;\n    float: none;\n  }\n\n  .howto-animation-03 p.smtextright {\n    width: auto;\n    float: none;\n  }\n\n  .large {\n    font-size: 48px;\n    line-height: 48px;\n    letter-spacing: normal;\n  }\n\n  h1 {\n    font-size: 32px;\n    line-height: 32px;\n  }\n\n  h2 {\n    font-size: 28px;\n    line-height: 30px;\n  }\n\n  #main-section h3 {\n    font-size: 24px;\n    line-height: 26px;\n  }\n\n  #main-section p {\n    font-size: 14px;\n    line-height: 26px;\n  }\n\n  h3 {\n    font-size: 20px;\n    line-height: 20px;\n  }\n\n  h4 {\n    font-size: 14px;\n    line-height: 20px;\n    font-weight: bold;\n  }\n\n  p {\n    font-size: 14px;\n  }\n\n  #marketing-video #frame-video {\n    margin: 26px;\n  }\n\n  a#tabzilla {\n    display: none;\n  }\n\n  .how-section-imganim-01 {\n    top: 26%;\n  }\n\n  .how-section-imganim-02 {\n    top: 16%;\n  }\n\n  .how-section-imganim-03 {\n    top: 20%;\n  }\n\n  .how-section-btncollab {\n    top: 22%;\n    left: 22%;\n  }\n\n  .how-section-btncollabpressed {\n    top: 22%;\n    left: 22%;\n  }\n\n  .how-section-dockplacement {\n    top: 18%;\n    left: 50%;\n  }\n\n  .cursor-placement-01 {\n    top: 13%;\n    left: 78%;\n  }\n\n  .cursor-placement-04 {\n    top: 17%;\n    left: 69%;\n  }\n\n  .cursor-placement-02 {\n    top: 32%;\n    left: 42%;\n  }\n\n  .cursor-placement-03 {\n    top: 25%;\n    left: 50%;\n  }\n\n  #footer .col-xs-12 {\n    padding-top: 0px;\n    padding-bottom: 0px;\n  }\n\n  #footer a {\n    font-size: 11px;\n  }\n\n  #footer a img {\n    width: 60px;\n    height: 10px;\n  }\n\n  #main-section #examples .ex-description {\n    min-height: 0px;\n  }\n\n  #main-section #examples .ex-title {\n    min-height: 0px;\n  }\n\n  #tryitout pre {\n    margin-top: -30px;\n  }\n\n}\n\n/* Smaller devices (tablets, 480px and up) */\n@media (min-width: 480px) {\n\n  #features .media > .pull-left {\n    margin-top: 10px;\n  }\n\n  #tryitout pre {\n    margin-top: -26px;\n  }\n\n  #howto-table td {\n    width: 50%;\n  }\n\n  .howto-animation-01 p.smtextright {\n    width: auto;\n    float: none;\n  }\n\n  .howto-animation-02 p.smtextleft {\n    width: auto;\n    float: none;\n  }\n\n  .howto-animation-03 p.smtextright {\n    width: auto;\n    float: none;\n  }\n\n  .large {\n    font-size: 48px;\n    line-height: 48px;\n    letter-spacing: normal;\n  }\n\n  h1 {\n    font-size: 32px;\n  }\n\n  h2 {\n    font-size: 28px;\n  }\n\n  h3 {\n    font-size: 24px;\n  }\n\n  h4 {\n    font-size: 15px;\n    font-weight: bold;\n  }\n\n  p {\n    font-size: 14px;\n  }\n\n  #marketing-video #frame-video {\n    margin: 26px;\n  }\n\n  a#tabzilla {\n    display: inherit;\n  }\n\n  #footer a img {\n    width: 100px;\n    height: 17px;\n  }\n\n  #main-section #examples .ex-description {\n    min-height: 0px;\n  }\n\n  #main-section img.why-section {\n    width: 30%;\n    height: 30%;\n  }\n\n\n}\n\n/* Small devices (tablets, 768px and up) */\n@media (min-width: 768px) {\n\n  #features li.media {\n    min-height: 140px;\n  }\n\n  #tryitout pre {\n    margin-top: 50px;\n  }\n\n  .large {\n    font-size: 72px;\n    line-height: 100%;\n    letter-spacing: normal;\n  }\n\n  h1 {\n    font-size: 48px;\n    line-height: 100%;\n  }\n\n  h2 {\n    font-size: 32px;\n    line-height: 100%;\n  }\n\n  h3 {\n    font-size: 28px;\n    line-height: 100%;\n  }\n\n  h4 {\n    font-size: 20px;\n    line-height: 100%;\n    font-weight: normal;\n  }\n\n  p {\n    font-size: 14px;\n    line-height: 20px;\n  }\n\n  #marketing-video #frame-video {\n    margin: 0 auto;\n  }\n\n  a#tabzilla {\n    display: inherit;\n  }\n\n  #footer a img {\n    width: 141px;\n    height: 24px;\n  }\n\n  #main-section #examples .ex-description {\n    min-height: 81px;\n  }\n\n}\n\n/* Medium devices (desktops, 992px and up) */\n@media (min-width: 992px) {\n\n  #features li.media {\n    min-height: 100px;\n  }\n\n  .howto-animation-01 p.smtextright {\n    width: 60%;\n    float: right;\n  }\n\n  .howto-animation-02 p.smtextleft {\n    width: 60%;\n    float: left;\n  }\n\n  .howto-animation-03 p.smtextright {\n    width: 60%;\n    float: right;\n  }\n\n  .large {\n    font-size: 72px;\n    line-height: 100%;\n    letter-spacing: normal;\n  }\n\n  h1 {\n    font-size: 48px;\n    line-height: 100%;\n  }\n\n  h2 {\n    font-size: 32px;\n    line-height: 100%;\n  }\n\n  h3 {\n    font-size: 28px;\n    line-height: 100%;\n  }\n\n  h4 {\n    font-size: 20px;\n    line-height: 100%;\n  }\n\n  p {\n    font-size: 14px;\n    line-height: 20px;\n  }\n\n  #video-area img {\n    margin-top: 7%;\n  }\n\n  #hero {\n    height: 436px;\n  }\n\n  #marketing-video #frame-video {\n    padding-top: 6px;\n  }\n\n  #main-section #examples .ex-description {\n    min-height: 54px;\n  }\n\n}\n\n/* Large devices (large desktops, 1200px and up) */\n@media (min-width: 1200px) {\n\n  #features li.media {\n    min-height: 100px;\n  }\n\n  #video-area img {\n    margin-top: 0%;\n  }\n\n  .large {\n    font-size: 72px;\n    line-height: 100%;\n    letter-spacing: normal;\n  }\n\n  h1 {\n    font-size: 48px;\n    line-height: 100%;\n    font-weight: 600;\n  }\n\n  h2 {\n    font-size: 32px;\n    line-height: 100%;\n  }\n\n  h3 {\n    font-size: 28px;\n    line-height: 100%;\n  }\n\n  h4 {\n    font-size: 20px;\n    line-height: 100%;\n  }\n\n  p {\n    font-size: 14px;\n    line-height: 20px;\n  }\n\n  #video-area img {\n    /*margin-top: 11px;*/\n  }\n\n  #hero {\n    height: 440px;\n  }\n\n  #marketing-video #frame-video {\n    padding-top: 8px;\n  }\n\n}\n\n\n/*making the modal size larger for the app examples*/\n@media screen and (min-width: 768px) {\n\n  .app-example .modal-dialog {\n  right: auto;\n  left: 50%;\n  width: 900px;\n  padding-top: 30px;\n  padding-bottom: 30px;\n  }\n\n}\n\n\n\n/*@media (min-width: 1200px) {\n  .navbox {\n    max-width: 1140px;\n  }\n}\n\n@media (min-width: 992px) {\n  .navbox {\n    max-width: 940px;\n  }\n}*/\n\n/*@media (min-width: 768px) {\n  .navbox {\n    max-width: 735px;\n  }\n}*/\n\n\n/* Source-specific styles */\n\n#sourcecode h1 {\n  margin-bottom: 20px;\n  border-bottom: 1px solid rgba(0,0,0,0.1);\n  padding-bottom: 17px;\n}\n\n#sourcecode h2 {\n  margin-bottom: 18px;\n}\n\n#sourcecode h3 {\n  margin-bottom: 18px;\n}\n\n#sourcecode pre {\n  margin: 10px 0 20px;\n}\n\n#sourcecode #sidenav {\n  margin-top: 40px;\n}\n\n#sourcecode #sidenav.panel .panel-heading {\n  background: #fff;\n  border-bottom: none;\n  font-weight: 700;\n}\n\n#sourcecode #sidenav .affix {\n  width: 263px;\n  position: static;\n}\n\n@media (min-width: 1200px) {\n  #sourcecode .affix, #sourcecode .affix-bottom {\n    width: 263px !important;\n    position: static !important;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 40px !important;\n  }\n}\n\n@media (min-width: 992px) {\n  #sourcecode .affix, #sourcecode .affix-bottom {\n    width: 213px;\n  }\n  #sourcecode .affix {\n    position: static !important;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 40px !important;\n  }\n}\n\n@media (min-width: 768px) {\n  #sourcecode .affix {\n    position: static;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 0px;\n  }\n}\n\n@media (min-width: 480px) {\n  #sourcecode .affix {\n    position: static;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 0px;\n  }\n}\n\n@media (max-width: 480px) {\n  #sourcecode .affix {\n    position: static;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 0px;\n  }\n}\n\n#source-content ul.sections > li > div.content {\n  background: #f5f5f5;\n}\n\n#source-content div.content {\n  padding: 13px;\n  border-radius: 6px;\n}\n\n#source-content div.annotation {\n  padding: 10px 25px 1px 0px;\n}\n\ndd {\n  padding-left: 2em;\n}\n\n\n/*MARKDOWN*/\n\n#markdownpages h1 {\n  margin-bottom: 20px;\n  border-bottom: 1px solid rgba(0,0,0,0.1);\n  padding-bottom: 17px;\n}\n\n#markdownpages h2 {\n  margin-top: 30px;\n  margin-bottom: 20px;\n  font-size: 36px;\n  line-height: 42px;\n}\n\n#markdownpages h3 {\n  font-size: 24px;\n  margin: 20px 0px;\n}\n\n#markdownpages h4 {\n  font-size: 18px;\n  margin: 20px 0px;\n}\n\n#markdownpages code {\n  white-space: pre-wrap;\n}\n\n#markdownpages pre {\n  margin: 10px 0 20px;\n}\n\n#markdownpages ul li {\n  font-size: 14px;\n  font-family: 'Open Sans',sans-serif;\n}\n\n#markdownpages #sidenav {\n  margin-top: 20px;\n}\n\n#sidenav .well .btn {\n  margin-bottom: 10px;\n}\n\n#sectionmenu {\n  border: 1px solid rgba(0,0,0,0.1);\n  margin-bottom: 20px;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n/*this doesnt match up right*/\n/*#sectionmenu li.active {\n  text-decoration: underline;\n}*/\n\n.panel {\n  border:0px;\n  box-shadow: none;\n  background: none;\n}\n\n#sidenav.panel .panel-heading {\n  background: #fff;\n  border-bottom: none;\n  font-weight: 700;\n}\n\n#sidenav .affix {\n  width: 263px;\n  position: fixed;\n}\n\n.affix-bottom {\n  top: -200px !important;\n}\n\n@media (min-width: 1200px) {\n\n  #markdownpages h1 {\n   font-weight: normal;\n  }\n\n  #sourcecode h1 {\n   font-weight: normal;\n  }\n  .affix, .affix-bottom {\n    width: 263px !important;\n    position: fixed !important;\n    bottom: 10px !important;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 40px !important;\n  }\n}\n\n@media (min-width: 992px) {\n\n  .affix, .affix-bottom {\n    width: 213px;\n  }\n  .affix {\n    position: fixed !important;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 40px !important;\n  }\n}\n\n@media (min-width: 768px) {\n\n  #sketchapp a.tjs-button {\n    float: right !important;\n    margin-bottom: 20px;\n  }\n\n  .affix {\n    position: static;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 0px;\n  }\n}\n\n@media (min-width: 480px) {\n\n  #sketchapp a.tjs-button {\n    float: right !important;\n    margin-bottom: 20px;\n  }\n\n  #sourcecode h1 {\n   font-size: 48px;\n   line-height: 52px;\n  }\n  #markdownpages h1 {\n   font-size: 48px;\n  }\n  .affix {\n    position: static;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 0px;\n  }\n}\n\n@media (max-width: 480px) {\n\n  #sketchapp a.tjs-button {\n    float: left !important;\n    margin-bottom: 20px;\n  }\n\n  #sourcecode h1 {\n   font-size: 48px;\n   line-height: 52px;\n  }\n\n  #markdownpages h1 {\n   font-size: 48px;\n   line-height: 52px;\n  }\n\n  .affix {\n    position: static;\n  }\n  .col-md-9 h1:first-child {\n    margin-top: 0px;\n  }\n}\n"
  },
  {
    "path": "site/docs/contributing.md",
    "content": "# Contributing to TogetherJS\n\n<!--\ntemplate: docs-contributing.tmpl\n\nNote: you should update the index in that template when adding\nsections to this document.\n-->\n\nHere are a variety of notes about contributing to the TogetherJS codebase.  This isn't stuff that applies if you are simply integrating TogetherJS in your site.\n\n## Code Style\n\n[Here is a style document](https://github.com/ianb/javascript).  It's a fork of the [Airbnb](https://github.com/airbnb/javascript) style guide, and maybe takes a little from the [Mozilla style guide](https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style), and then a little of our own opinions.\n\n### Code Cleanliness\n\nPlease figure out how to get your editor to delete trailing whitespace!  It's a nuisance and creates useless diffs.  Files should also end with a newline.\n\n## TogetherJS Patterns\n\n### Modules\n\nThere are [some notes in the style guide](https://github.com/ianb/javascript#modules).  TogetherJS uses [requirejs](http://requirejs.org/) for module loading, and the AMD pattern generally.  Each module should go in `app/http/togetherjs/public/` and look like:\n\n```javascript\ndefine([\"util\", \"jquery\", \"require\"], function (util, $, require) {\n  var myModule = util.Module(\"myModule\");\n  var assert = util.assert;\n  myModule.object = ... // and so on\n  return myModule;\n});\n```\n\nThe first list is the dependencies (modules) you need.  If you need to require module modules later (lazily, or later than load time due to circular dependencies) you must include `require` among your dependencies.  There *is* a global `require()` object, but you can't use it, because TogetherJS uses a [context](http://requirejs.org/docs/api.html#multiversion).\n\nYou should define an object with a name matching the name of the module (and filename).  This way an object or function will be named the same throughout the project, both when used internally and externally (e.g., `myModule.object`), and when it is being created.\n\nIf you want to load a module from the console, you do it like this:\n\n```javascript\nsession = require({context: \"togetherjs\"})(\"session\");\n```\n\n(This form of `require` only works when the module is already loaded, but from the console that's usually the case.)\n\n### Classes\n\nThere is a class factory in `util.Class`.  It supports subclassing, but we haven't used any subclasses yet, and I'm not sure we will.  Look at the implementation if you want to know more.\n\nTo define a class, do:\n\n```javascript\nvar MyClass = util.Class({\n  constructor: function (...) {...}\n});\nMyClass.classMethod = function (...) {...};\nvar instance = MyClass();\n```\n\nThe `constructor` function is called when the object is instantiated.  You don't need to use `new` when creating instances, and really you shouldn't (it'll just create an object that'll be thrown away).  MyClass.prototype is what you would expect.\n\n### this\n\nYou should understand how `this` is bound, and how that binding is lost.\n\nGenerally we prefer using `.bind(this)` to keep the references to this (as opposed to using `self = this`).  For example:\n\n```\nvar MyClass = Class({\n\n  goodExample: function () {\n    doSomething((function () {return this.foo;}).bind(this));\n  },\n\n  badExample: function () {\n    var self = this;\n    doSomething(function () {return self.foo;});\n  }\n});\n```\n\nWhy?  Mostly so that `this` is always called `this`, and you don't have to figure out whether or where there is an alias.\n\n### Templating\n\nRight now we aren't using any real templating system.  Almost everything is in `app/http/views/interface.html` – and most likely any new markup should also go there.\n\nWe try to keep most of the code that actually touches the ui in `ui.js` – though it's not done very strictly.  Moving stuff back into ui.js is appreciated though.\n\n\"Templates\" are just elements that are cloned out of `interface.html`.  They generally have an id like `togetherjs-template-foo`, and you'd clone them by doing `templating.sub(\"foo\", {vars})`.\n\nYou should avoid having text or markup in JavaScript, and instead clone templates or hide and show different elements to represent different states.  Occasionally you do need to put markup-related stuff in code (like pixel sizes or other details).  When this is the case leave a comment in both sources (HTML/CSS and JS) pointing to the other location.\n\n### Stateless controls\n\nInstead of \"toggle\" controls we prefer to show and hide controls for the alternate states.  For instances, if you have a expand/collapse control:\n\n```html\n<button id=\"togetherjs-collapse-foo\" data-toggles=\"#togetherjs-expand-foo\">-</button>\n<button id=\"togetherjs-expand-foo\" data-toggles=\"#togetherjs-collapse-foo\" style=\"display: none\">+</button>\n```\n\nThen use `ui.displayToggle(\"#togetherjs-expand-foo\")` to show the expand button, and the collapse button will be automatically hidden.  Note that the selector in `data-toggles` can be inclusive of the element itself (everything matching selector will be hidden, except the element itself).\n\nThis requires less state in the JavaScript, as the control is always an assertion to do something specific.  Also it means that we have to do a minimum of manipulation in JavaScript, and the two controls are not required to be styled identically.\n\n### Async\n\nUse [jQuery.Deferred](http://api.jquery.com/category/deferred-object/) when possible.  This is exposed as `util.Deferred`\n\n\n## Hosting the Hub Server\n\nThis has been [moved to the main docs](./#hosting-the-hub-server).\n\n## The Issue Tracker and Milestones\n\nWe do most of our planning in the [Github issue tracker](https://github.com/mozilla/togetherjs/issues), and make use of the [Milestones](https://github.com/mozilla/togetherjs/issues/milestones) (more than labels).  You are welcome to just submit issues without worrying about this, but if you are looking at a ticket and want how it relates to our plans then you might want to know our system.\n\nGenerally we have three running milestones:\n\n* \"Release X\" or \"Beta 1039\", etc: something that represents our planned work for the current iteration.  We don't generally complete everything we plan for in an iteration (i.e., we err on the side of including stuff in a milestone), so if something is important to you then you might still want to note this in a ticket.\n\n* [Next Tasks](https://github.com/mozilla/togetherjs/issues?milestone=17&state=open): this is a long-standing milestone that represents tasks we want to do soon, but not in the current milestone.  Typically when planning the next iteration we'll look through this milestone and pick out issues.  If something in this milestone is a priority for you, please note that in a comment on the ticket so we can understand your needs.\n\n* [Blue Sky](https://github.com/mozilla/togetherjs/issues?milestone=23&state=open): another long-standing milestone, this represents stuff we'd like to do but don't have any plans to do any time soon.  If you are looking to contribute this is an excellent place to look for ideas.  And if it's something you think would be helpful to you, a comment would be good -- especially one that outlines a use case.\n\n* [Issues with no milestone](https://github.com/mozilla/togetherjs/issues?milestone=none&page=1&state=open): these are issues that haven't been triaged.  We try to assign milestones every week to these issues.  If we don't then probably we are caught up in something we need to focus on over a short period, or we're just all out on vacation or something.\n"
  },
  {
    "path": "site/docs/faq.md",
    "content": "# FAQ\n\n## When I add a field dynamically it doesn't appear on the other person's page!\n\n## Will I see what the other person is seeing?\n\n## Why not synchronize everything?\n\n## Should I host my own server?\n\n## How stable is TogetherJS?\n\n## Does it work on an intranet?\n"
  },
  {
    "path": "site/docs/index.md",
    "content": "# Documentation\n\n<!--\ntemplate: docs.tmpl\n-->\n\nWould you like to use TogetherJS on your site?  Great!  If you have feedback on this or any other part of TogetherJS [we'd like to hear it](https://docs.google.com/forms/d/1lVE7JyRo_tjakN0mLG1Cd9X9vseBX9wci153z9JcNEs/viewform)!\n\n## Quick Start\n\nGet started quickly by including two things on your page.  First the JavaScript:\n\n```html\n<script>\n  // TogetherJS configuration would go here, but we'll talk about that\n  // later\n</script>\n<script src=\"https://togetherjs.com/togetherjs-min.js\"></script>\n```\n\nYou can put that wherever; e.g., right before `</body>`.\n\nThe next step is to put a button on your site that lets a user start TogetherJS:\n\n```html\n<button onclick=\"TogetherJS(this); return false;\">Start TogetherJS</button>\n```\n\nOr if you don't like `onclick`:\n\n```html\n<button id=\"start-togetherjs\">Start TogetherJS</button>\n<script>\n$(function () {\n  $(\"#start-togetherjs\").click(TogetherJS);\n});\n</script>\n```\n\nCalling `TogetherJS()` will start the tool, or stop the tool if it is already started.\n\nYou should put the `togetherjs-min.js` script on every page in your site, even if you don't include the \"Start TogetherJS\" button.  As long as the script is on a page then two people can collaborate on that page. If you forget it on a page, then if someone visits that page while in a TogetherJS session they will essentially go \"offline\" until they come back to another page that includes `togetherjs-min.js`\n\nNote that `togetherjs-min.js` *is not* the entire code for TogetherJS, it's only a fairly small file that loads the rest of TogetherJS on demand.  You can place the `<script>` anywhere on the page – generally before `</body>` is considered the best place to put scripts.\n\nIf you want to dive into code you might want to skip to [Configuring TogetherJS](#configuring-togetherjs).\n\n## Technology Overview\n\nIn this section we'll describe the general way that TogetherJS works, without diving into any code.  If you are ready to use TogetherJS and want to know how, skip to the next section; if you want to understand how it works, or if it can help you in a particular use case, then this section is for you.\n\nThe core of TogetherJS is the **hub**: this is a server that everyone in a session connects to, and it echos messages to all the participants using Web Sockets.  This server does not rewrite the messages or do much of anything besides **pass the messages between the participants**.\n\n[WebRTC](http://www.webrtc.org/) is available for **audio chat**, but is not otherwise used.  We are often asked about this, as WebRTC offers data channels that allow browsers to send data directly to other browsers without a server.  Unfortunately you still need a server to establish the connection (the connection strings to connect browsers are quite unwieldy), it only supports one-to-one connections, and that support is limited to only some browsers and browser versions.  Also establishing the connection is significantly slower than Web Sockets. But maybe someday.\n\nEverything that TogetherJS does is based on these messages being passed between browsers.  It doesn't require that everyone be on the same page, all it requires is that everyone in the session know what hub URL to connect to (the URL is essentially the session name). People *can* be on different sites, but the session URL is stored in [sessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window.sessionStorage) which is local to one domain (and because we use sessionStorage instead of localStorage, it is local to one tab).  We don't have any techniques implemented to share sessions across multiple sites, but the only barrier is this local storage of session information.\n\nFeatures are built on top of this messaging system.  For instance when you move your mouse around, a `cursor-update` message is sent giving the new mouse position.  Other clients that aren't at the same page as you see the message but ignore it.\n\n**Most features work directly with the DOM**, and so don't require any special instrumenting of your code, or integration work.  As much as possible we anchor messages things to the most specific element possible.  When using [responsive web design](http://en.wikipedia.org/wiki/Responsive_web_design) different clients at the same URL may see different things, but to the degree they see the same elements things like the mouse position will be \"correct\".  For instance, on mobile you might put a button in a different location on the page, but because the cursor message says \"the mouse is over the button named `#submit`\" the mouse will be positioned in the equivalent position.  As a result **TogetherJS is also resolution-independent**.\n\nWe support the **synchronization of form states**, and also support [operational transformation](http://en.wikipedia.org/wiki/Operational_transformation) for text fields.  Again, this is all layered on top of the message system.\n\nUnlike products like [Etherpad](http://etherpad.org/), the [Google Drive Realtime API](https://developers.google.com/drive/realtime/) we **do not have any persistence in our system**.  When two people are on the same page their text fields are synchronized, but all we've done is changed their browser states to be in sync.  We expect all persistence to still happen through your application.  You should generally write an application like you always have, and TogetherJS adds features on top of that.  **TogetherJS doesn't change your security model, your persistence model, or your authentication model**.  If one user hits \"submit\" then they are the one who saved the page, probably using a typical POST request, just as if they weren't using TogetherJS.\n\n**TogetherJS relies on the same URL returning the same page**.  When two users are at the same URL we don't force the page to be the same. For example one person might not have permission to view a page: in that case the person will still get a permission denied page, and will be unable to follow along with the first person.  Generally we try to fail gracefully, so inconsistencies will only degrade the experience, not completely break it.  In an ideal situation when two people are using TogetherJS you might allow them both to see an edit screen, but only put permission restrictions on who can actually save those edits.\n\n**TogetherJS relies on the application to synchronize its state**.  If you have a web application that has lots of dynamic client-side content, the two users won't automatically see the same things. TogetherJS isn't like screen sharing: each person is running your web application in their own normal browser environment.  We do [provide tools](#extending-togetherjs) to help you synchronize your state.\n\nYou can [host your own hub](contributing.html#hosting-the-web-server), which is the only dynamic server-side part of TogetherJS.  But you don't need to host your own server, the server we host is entirely generic and capable of serving multiple sites.  Though if your site is generating a lot of traffic we'll probably want to talk.\n\nMost of the actual code is in the client, which is **open source** and **easy to freeze**.  You can easily make your own static copy of the client, and so ensure the code won't change out from underneath you and invalidate your own testing of the product on your site.  Almost all client updates do not involve the server, so version management and stability is very easy to achieve.  Because TogetherJS does not save anything, it's easy to include in any development environment as well, and you can run it on an intranet or private site so long as everyone using it has access to that site; our servers.\n\n## Configuring TogetherJS\n\nAs mentioned there are several configuration parameters.  To see the exact list of settings and their defaults, look at `TogetherJS._defaultConfiguration` in [together.js](https://github.com/mozilla/togetherjs/blob/develop/togetherjs/togetherjs.js)\n\nThere are a couple ways of configuring TogetherJS.  The one that we prefer is to set a global variable before `togetherjs(-min).js` is included.  Each variable is named `TogetherJSConfig_*`.  This makes it fairly easy to add or remove variables.  Note however that once `togetherjs(-min).js)` is loaded that these variables might not be respected.  So do:\n\n```js\n<script>\nvar TogetherJSConfig_something = \"foo\";\n// more config...\n</script>\n<script src=\"https://togetherjs.com/togetherjs-min.js\"></script>\n```\n\nThe other way to set a variable *after* TogetherJS is loaded is `TogetherJS.config(\"variable\", value)`.  Some variables cannot be updated after TogetherJS has started, but if this is the case then you should get an error.\n\n### The Configuration\n\n`TogetherJSConfig_siteName`:\n    This is the name of your site.  It defaults to the title of the page, but often a more abbreviated title is appropriate.  This is used in some help text.\n\n`TogetherJSConfig_toolName`:\n    This is the name that you are giving this tool.  If you use this then \"TogetherJS\" won't be in the UI.  So you might want to use `TogetherJSConfig_toolName = \"Collaboration\".\n\n`TogetherJSConfig_hubBase`:\n    This is where the hub lives.  The hub is a simple server that echoes messages back and forth between clients.  It's the only real server component of TogetherJS (besides the statically hosted scripts).  It's also really boring.  If you wanted to use a hub besides ours you can override it here.  The primary reason would be for privacy; though we do not look at any traffic, by hosting the hub yourself you can be more assured that it is private.  You'll find that a hub with a valid https certificate is very useful, as mixed http/https is strictly forbidden with WebSockets.\n\n`TogetherJSConfig_dontShowClicks`:\n    This should be set to a jQuery selector or set to true. This will disable the visual click display indicating that a user has clicked on the defined element. For example: \"canvas\", \"h1\", \"p\", etc.  Setting `TogetherJSConfig_dontShowClicks = true` will globally disable all clicks.\n\n`TogetherJSConfig_cloneClicks`:\n    This should be set to a jQuery selector or set to true. Whenever someone clicks on an element matching this selector, that click will be repeated (as an actual click) on everyone else's browser.  This is useful for cases when a click typically doesn't *do* anything, but shows or hides or switches the view of the page.  Note that any control that toggles will definitely not work here!  If you have tab buttons that show different things you might use `TogetherJSConfig_cloneClicks = \".tab\"`. Setting `TogetherJSConfig_cloneClicks = true` will globally clone clicks.\n\n`TogetherJSConfig_enableShortcut`:\n    If you want to try TogetherJS out on an application, but don't want to put up a \"Start TogetherJS\" button, you can use `TogetherJSConfig_enableShortcut = true` and then an event handler will be put into place that will start TogetherJS when you hit **alt-T alt-T** (twice in a row!).  TogetherJS will still automatically start when someone opens an invitation link.\n\n`TogetherJSConfig_useMinimizedCode`:\n    Typically if you use `togetherjs.js` you'll get the unminimized and uncombined code, with each module loaded lazily.  If you use `togetherjs-min.js` you get the combined code.  But if you want to override that more dynamically, you can use this setting.\n\n`TogetherJSConfig_findRoom`:\n    To see this in action, check out the examples.  This setting assigns people to a room.  If you use a single string, this will be the name of the room; for instance: `TogetherJSConfig_findRoom = \"my_site_com_users\"`.  You can also assign people to a series of rooms with maximum occupancy (what our examples do): `TogetherJSConfig_findRoom = {prefix: \"my_site_com_users\", max: 5}` **Note:** if you change this setting, test in a *new tab* (old browser tabs carry session information that will confuse you).\n\n`TogetherJSConfig_autoStart`:\n    If true then start TogetherJS automatically.  Note TogetherJS already starts automatically when a session is continued, so if you just always call `TogetherJS()` then you might cause TogetherJS to stop.  Note you must set this as `TogetherJSConfig_autoStart = true`, not using `TogetherJS.config(\"autoStart\", true)` (it must be set when TogetherJS loads).  Anyone who autostarts a session will not be considered the session creator.\n\n`TogetherJSConfig_suppressJoinConfirmation`:\n    When a person is invited to a session, they'll be asked if they want to join in browsing with the other person.  Set this to `true` and they won't be asked to confirm joining.  Useful when combined with `findRoom`.\n\n`TogetherJSConfig_suppressInvite`:\n    When a person starts a session, usually a window will pop open with the invite link so they can send it to someone.  If this is true then that window doesn't automatically pop open (but it is still available).\n\n`TogetherJSConfig_inviteFromRoom`:\n    This adds the ability from the profile menu to invite people who are hanging out in another room (using TogetherJS).  This is kind of (but not exactly) how the \"Get Help\" button works on this site.  This is still an experimental feature.\n\n`TogetherJSConfig_includeHashInUrl`:\n    When true (default false), TogetherJS treats the entire URL, including the hash, as the identifier of the page; i.e., if you one person is on `http://example.com/#view1` and another person is at `http://example.com/#view2` then these two people are considered to be at completely different URLs.  You'd want to use this in single-page apps where being at the same base URL doesn't mean the two people are looking at the same thing.\n\n`TogetherJSConfig_disableWebRTC`:\n    Disables/removes the button to do audio chat via WebRTC.\n\n`TogetherJSConfig_youtube`:\n    If true, then YouTube videos will be synchronized (i.e., when one person plays or pauses a video, it will play for all people).  This will also load up the YouTube iframe API.\n\n`TogetherJSConfig_ignoreMessages`:\n    Contains a list of all the messages that will be ignored when console logging. Defaults to the list [\"cursor-update\", \"keydown\", \"scroll-update\"]. Will ignore all messages if set to true.\n\n`TogetherJSConfig_ignoreForms`:\n    Contains a list of all the forms that will be ignored. Each item of the list is a jQuery selector matching the form element to be ignored. Defaults to [\":password\"]. Will ignore all forms if set to true.\n\nThere are additional hooks you can configure, which are described in [Extending TogetherJS](#extending-togetherjs).\n\n## Start TogetherJS Button\n\nThe button you add to your site to start TogetherJS will typically look like this:\n\n```html\n<button id=\"start-togetherjs\" type=\"button\"\n onclick=\"TogetherJS(this); return false\"\n data-end-togetherjs-html=\"End TogetherJS\">\n  Start TogetherJS\n</button>\n```\n\n1. If you give your button the same `id` across your site, TogetherJS will know what the start/end TogetherJS button is.  It's not essential, but TogetherJS uses this to zoom the controls into and out of the button.\n\n2. `onclick=\"TogetherJS(this); return false\"` – this starts TogetherJS, and by passing `this` TogetherJS knows what button it started from.  This lets it animate out of the button.  It'll also work fine with `document.getElementById(\"start-togetherjs\").addEventListener(\"click\", TogetherJS, false)`\n\n3. `data-end-togetherjs-html` is what TogetherJS will insert into the content of the button after it is started.  You can use this to switch Start to End, or whatever language you use.  As a special case \"Start TogetherJS\" is changed to \"End TogetherJS\".\n\n4. The class `togetherjs-started` will be added to the button while TogetherJS is active.  You might want to use this to style the background color to red to show that it changes to ending the session.\n\n### Scope of the session\n\nTogetherJS sessions are connected to the domain you start them on (specifically the [origin](http://tools.ietf.org/html/rfc6454)).  So if part of your site is on another domain, people won't be able to talk across those domains.  Even a page that is on https when another is on http will cause the session to be lost.  We might make this work sometime, but if it's an issue to you please give us [feedback](https://docs.google.com/forms/d/1lVE7JyRo_tjakN0mLG1Cd9X9vseBX9wci153z9JcNEs/viewform).\n\n## About Audio Chat and WebRTC\n\nThe live audio chat is based on [WebRTC](http://www.webrtc.org/). This is a very new technology, built into some new browsers.\n\nTo enable WebRTC both you and your collaborator need a new browser. Right now, [Firefox Nightly](http://nightly.mozilla.org/) is supported, and we believe that the newest release of Chrome should work.\n\nSometime in 2013 support for this should be available in new (non-experimental) versions of Firefox, Chrome, and both Firefox and Chrome for Android.\n\nTo see a summary of outstanding issues that we know of with audio chat see [this page](https://github.com/mozilla/togetherjs/issues?labels=rtc&milestone=&page=1&state=open).\n\nNote that audio chat will not work between some networks.  These networks require a [TURN server](http://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT) which unfortunately we do not have allocated (and full support for TURN has not landed in some browsers).  Unfortunately when the network makes chat impossible, chat will simply not work – we don't receive an error, and can't tell you why chat is not working.  See [#327](https://github.com/mozilla/togetherjs/issues/327) for progress.\n\n## Extending TogetherJS\n\nWhile [configuration](#configuring-togetherjs) covers some of what you can do to customize TogetherJS, you may also need to integrate TogetherJS with your application, or sync your application data between clients.\n\n### Configuring events\n\nLike other configuration, you can configure the event handlers and hooks we describe before `togetherjs(-min).js` is loaded.  Event handlers are just a smidge different.  You'd normally add event handler like `TogetherJS.on(\"ready\", function () {...})`.  To do it as configuration:\n\n```js\nTogetherJSConfig_on = {\n  ready: function () {}\n};\n```\n\nOr if you want to set things up one-by-one you can do:\n\n```js\nTogetherJSConfig_on_ready = function () {};\n```\n\nAdditionally you may want to add event listeners to `TogetherJS.hub`; these are done like:\n\n```js\nTogetherJS_hub_on = {\n  \"my-event\": function (msg) {\n  }\n};\n```\n\n### Communication Channel\n\nIf you have a component you want to synchronize between two clients, you'll want to use the TogetherJS communication channel.  This is a broadcast channel – any message you send is sent to everyone else in the session (which can also be no one), and includes people who are on different pages.\n\nAll messages are JSON objects with a `type` property.  Custom application messages are put into their own namespace.  So imagine you want to keep an element hidden or visible on all clients, in a synchronized way, and when the element visibility changes an event is fired inside your app, `MyApp.emit(\"visibilityChange\", element, isVisible)`:\n\n```js\nTogetherJSConfig_on_ready = function () {\n  MyApp.on(\"visibilityChange\", fireTogetherJSVisibility);\n};\nTogetherJSConfig_on_close = function () {\n  MyApp.off(\"visibilityChange\", fireTogetherJSVisibility);\n};\n```\n\nNow when TogetherJS is activated we'll call `fireTogetherJSVisibility(el, isVisible)`.  Now we have to write that function:\n\n```js\nfunction fireTogetherJSVisibility(element, isVisible) {\n  TogetherJS.send({type: \"visibilityChange\", isVisible: isVisible, element: element});\n}\n```\n\nWell, that's not quite right, we have to send a JSON object, and we can't send `element`.  Instead we need to give an identifier for the element.  TogetherJS has a helpful function for that, which will require us to import the `elementFinder` module:\n\n```js\nfunction fireTogetherJSVisibility(element, isVisible) {\n  var elementFinder = TogetherJS.require(\"elementFinder\");\n  var location = elementFinder.elementLocation(element);\n  TogetherJS.send({type: \"visibilityChange\", isVisible: isVisible, element: location});\n}\n```\n\nThen we also have to listen for the message.  We can setup this listener right away (without using the ready/close TogetherJS events) because when TogetherJS isn't on then the event will just not fire:\n\n```js\nTogetherJS.hub.on(\"visibilityChange\", function (msg) {\n  var elementFinder = TogetherJS.require(\"elementFinder\");\n  // If the element can't be found this will throw an exception:\n  var element = elementFinder.findElement(msg.element);\n  MyApp.changeVisibility(element, msg.isVisible);\n});\n```\n\nThis has two major problems though: when you call `MyApp.changeVisibility` it will probably fire a `visibilityChange` event, which will cause another `fireTogetherJSVisibility` call.  The result may or may not be circular, but it's definitely not efficient. Another problem is that you can get messages from peers who are at a different URL.  We'll use a simple global variable to handle the first case, and `msg.sameUrl` to fix the second:\n\n```js\nvar visibilityChangeFromRemote = false;\n\nfunction fireTogetherJSVisibility(element, isVisible) {\n  if (visibilityChangeFromRemote) {\n    return;\n  }\n  var elementFinder = TogetherJS.require(\"elementFinder\");\n  var location = elementFinder.elementLocation(element);\n  TogetherJS.send({type: \"visibilityChange\", isVisible: isVisible, element: location});\n}\n\nTogetherJS.hub.on(\"visibilityChange\", function (msg) {\n  if (! msg.sameUrl) {\n    return;\n  }\n  var elementFinder = TogetherJS.require(\"elementFinder\");\n  // If the element can't be found this will throw an exception:\n  var element = elementFinder.findElement(msg.element);\n  visibilityChangeFromRemote = true;\n  try {\n    MyApp.changeVisibility(element, msg.isVisible);\n  } finally {\n    visibilityChangeFromRemote = false;\n  }\n});\n```\n\nNow we're getting close, except for one last problem: these events sync everything when the users are on the same page, but there may be a late comer whose page won't be in sync with everything else.  An event `togetherjs.hello` will fire when a person appears on a new page, and we can use to that send all our state.  To do this we'll imagine the `MyApp` object has a function like `MyApp.allToggleElements()` that returns a list of elements that we'd be expected to sync.\n\n```js\nTogetherJS.hub.on(\"togetherjs.hello\", function (msg) {\n  if (! msg.sameUrl) {\n    return;\n  }\n  MyApp.allToggleElements.forEach(function (el) {\n    var isVisible = $(el).is(\":visible\");\n    fireTogetherJSVisibility(el, isVisible);\n  });\n});\n```\n\nYou'll notice that multiple clients might do this reset.  This is an open question for us, and in the future we'll provide a higher-level API for this kind of initialization.\n\n#### Implementing those visibility function from jQuery\n\nLet's say your app doesn't have all these methods, and you are just using plain ol' jQuery.  Here's how you might implement them each; you'll just have to start using `$(el).syncShow()` and `$(el).syncHide()` to do your showing and hiding:\n\n```js\n$.fn.syncShow = function () {\n  this.show();\n  this.trigger(\"visibilityChange\");\n};\n\n$.fn.syncHide = function () {\n  this.hide();\n  this.trigger(\"visibilityChange\");\n};\n\n$(document).on(\"visibilityChange\", function () {\n  MyApp.emit(\"visibilityChange\", this, $(this).is(\":visible\"));\n});\n\nMyApp.changeVisibility = function (el, isVisible) {\n  if (isVisible && ! el.is(\":visible\")) {\n    el.syncShow();\n  } else if ((! isVisible) && el.is(\":visible\")) {\n    el.syncHide();\n  }\n};\n```\n\n### Setting identity information\n\nThere's a good chance your application has its own identity, and you know the name of the user, and perhaps have an avatar.  (If you don't have an avatar but do have an email, you might want to use that to make a Gravatar.)\n\nTo do this you configure TogetherJS with some functions:\n\n`TogetherJSConfig_getUserName = function () {return 'User Name';};`\n\nThis returns the user's name (or nick).  Return null if you can't determine the name.\n\n`TogetherJSConfig_getUserAvatar = function () {return avatarUrl;};`\n\nThis returns a URL to the user's avatar.  It should be 40px square. Again return null if you aren't sure.\n\n`TogetherJSConfig_getUserColor = function () {return '#ff00ff';};`\n\nThis returns the user's preferred color that represents them.  This should be a CSS color.\n\nThe names might confuse you: you are providing functions that TogetherJS will call to get the user's name, avatar, and color.  It doesn't return the name the user has set through TogetherJS (that would be `TogetherJS.require(\"peers\").Self.name`).\n\nIf any of these values are updated while in the page (like if you have a login process that doesn't cause a page reload) then call `TogetherJS.refreshUserData()` and the respective `getUser*` callbacks will all be called again.\n\nSee [#504](https://github.com/mozilla/togetherjs/issues/504) for a bug related to improving this support.\n\n### TogetherJS.reinitialize&#40;&#41;\n\nYou can run this to try to reinitialize anything TogetherJS initializes on page load.  In particular you can use it if there are new code editors or video elements that should be sync'd, but were added dynamically to the page.  E.g.:\n\n```javascript\n$(\"#content\").append('<video src=\"foo.mov\">');\nTogetherJS.reinitialize();\n```\n\n### TogetherJS events\n\nThe `TogetherJS` object is an event emitter.  It uses the style of `TogetherJS.on(\"event\", handler)`.  The available events:\n\n- `TogetherJS.on(\"ready\", function () {})`: emitted when TogetherJS is fully started up.\n- `TogetherJS.on(\"close\", function () {})`: emitted when TogetherJS is closed.  This is *not* emitted when the page simply closes or navigates elsewhere.  It is only closed when TogetherJS is specifically stopped.\n\n### Deferring Initialization\n\nTogetherJS starts up automatically as soon as it can, especially when continuing a session.  Sometimes this is problematic, like an application that bootstraps all of its UI after page load.  To defer this initialization, define a function `TogetherJSConfig_callToStart` like:\n\n```js\nTogetherJSConfig_callToStart = function (callback) {\n  MyApp.onload = callback;\n};\n```\n\nIn this example when `MyApp.onload()` is called, TogetherJS will start to initialize itself.  Note that calling `TogetherJS.reinitialize()` might be sufficient for your application's needs if it does a lot of setup after the page loads.\n\n### Invitation\n\nSometimes instead of having the user invite someone to TogetherJS you might want to handle the invitation internally in your app.  So typically when the person started TogetherJS, you'd want to find some other person they want to collaborate with and send the TogetherJS link to them.  To get at the TogetherJS link:\n\n```js\nTogetherJSConfig_on_ready = function () {\n  sendTogetherJSURLToServer(TogetherJS.shareUrl());\n};\n```\n\nIf you call `TogetherJS.shareUrl()` before TogetherJS is initialized it will return `null`.\n\n### Getting At The Innards\n\nYou can still get at TogetherJS, even if you can't rely on the internals not to change underneath you.  (You would be well recommended to deploy your own copy of the client if you do this stuff.)\n\nMost of the TogetherJS features are implemented as individual modules, so it should be possible to introduce your own module to do many of the same things.  The most important thing is the `session` module, and sending and receiving messages.\n\nTo get the session module (or any module) you can run this after TogetherJS starts:\n\n```javascript\nvar session = TogetherJS.require(\"session\");\n```\n\nThis assumes that the module has already been loaded... but that assumption would be correct once TogetherJS has started.\n\n## Getting a static copy of the client\n\nYou may also want a static copy of the client that you can host yourself.  Run `grunt build` to create a static copy of the TogetherJS library in `build/` (use `--dest` to control the output location, and `--exclude-tests` to avoid including the tests in your version).\n\nThe hub changes quite infrequently, so if you just stability then making a static copy of the client will do it for you.  This option is highly recommended for production!\n\n## Localization Support\n\n* Check [translation file](../../togetherjs/locale/en-US.json) for template example if you want to translate into your own language\n* Adding new language inside [locale](../../togetherjs/locale/) directory should be in this format: \"th-TH.json\", \"th.json\", \"pt-BR.json\" or \"pt.json\" and enable support language in [`availableTranslations`](../../togetherjs/togetherjs.js#L320) inside togetherjs.js file.  Note that your file name and language names in  your configuration should use hyphens in accord with [BCP 47](http://tools.ietf.org/html/bcp47), not underscores.\n\nTo get your language display you can enable it by:\n\n``` html\n<script>\n  var TogetherJSConfig_lang = \"pt-BR\";\n</script>\n```\n\n## Browser Support\n\nTogetherJS is intended for relatively newer browsers.  Especially as we experiment with what we're doing, supporting older browsers causes far more challenge than it is an advantage.\n\nThe bare minimum that we've identified for TogetherJS is [WebSocket support](http://caniuse.com/websockets).  That said, we generally only test on the most recent version of Firefox and Chrome, so bugs specific to older browsers are more likely (but please [submit bugs](https://github.com/mozilla/togetherjs/issues/new) from those browsers anyway – we aren't deliberately not supporting them). Our next set of browsers to target will be mobile browsers.\n\n### Supported Browsers\n\nWe recommend the most recent release of [Firefox](http://www.mozilla.org/en-US/firefox/new/) or [Chrome](https://www.google.com/intl/en/chrome/browser/).\n\nIf you want to have [WebRTC support](https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC) and are using Firefox, as of April 2013 this requires [Firefox Nightly](http://nightly.mozilla.org/) (this support will be moving towards beta and release in the coming months).\n\nWe haven't done much testing on mobile (yet!) and cannot recommend anything there.\n\n#### Internet Explorer\n\nWith IE 10 it is *possible* to support Internet Explorer (version 9 and before do not support WebSockets).  However we do not test at all regularly on Internet Explorer, and we know we have active issues but are not trying to fix them.  Pull requests to support Internet Explorer are welcome, but right now we don't plan to address bug reports for Internet Explorer that don't come with a pull request.  If Internet Explorer support is important to you we do [welcome your feedback](https://docs.google.com/a/mozilla.com/forms/d/1lVE7JyRo_tjakN0mLG1Cd9X9vseBX9wci153z9JcNEs/viewform). No decision is set in stone, but we don't want to mislead you with respect to our current priorities and intentions.\n\nWe need your help!  If you're itching to help out, it would be great if you take on one of these Internet Explorer bugs [here](https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open)!\n\n## Hosting the Hub Server\n\nWe have a server at `https://hub.togetherjs.com` which you are welcome to use for peer-to-peer communications with TogetherJS.  But you may wish to host your own.  The server is fairly small and simple, so it should be reasonable.  Note that we haven't really \"finished\" the story around self-hosting, so the details of this are likely to change.  The server itself is quite stable.\n\nThe server is located in `hub/server.js`, and is a simple Node.js application.  You can run this like `node hub/server.js` - use `node hub/server.js --help` to see the available options.  You will need to `npm install websocket optimist` to get the websocket library and option library installed.\n\nIf you want to use TogetherJS on an https site you must host the hub on https.  We don't have it set up in `server.js` for Node to do SSL directly, so we recommend a proxy. [stunnel](https://www.stunnel.org/) is an example of the kind of proxy you'd want – not all proxies support websockets.\n\nIf you want to change the port or interface the server binds to, simply run `node hub/server.js -h` and it will show the command-line options as well as environmental variables.\n\nOnce you have the hub installed you need to configure TogetherJS to use the hub, like:\n\n```javascript\nTogetherJSConfig_hubBase = \"https://myhub.com\";\n```\n\nIf you are curious about the exact version of code on the server it should be always be [server.js on master](https://github.com/mozilla/togetherjs/blob/master/hub/server.js), and you can double-check by fetching [`/server-source`](https://hub.togetherjs.com/server-source).\n\n### Deploying the hub server to Heroku\n\nYou need a Heroku account. If you don't have one, their [Node.js getting started guide](https://devcenter.heroku.com/articles/getting-started-with-nodejs) is a good place to start.\n\nWhat's about to happen: we clone the repo and create a new Heroku app within it. We need to set the HOST environment variable to get the app to bind to 0.0.0.0 instead of 127.0.0.1. It'll pick up the PORT variable automatically. We also need to enable WebSockets for the app. Then, push the code and we should be good to go!\n\n\tgit clone git@github.com:mozilla/togetherjs.git\n\tcd togetherjs\n\theroku create\n\theroku config:add HOST=0.0.0.0\n\tgit push heroku master\n\nMake note of the app name after running `heroku create` You can check that everything is running by going to http://your-app-name-here.herokuapp.com/status\n\n## Addons\n\nThere is an addon for Firefox in [addon/](https://github.com/mozilla/togetherjs/tree/develop/addon).\n\nThis isn't intended to be the \"normal\" way anyone uses TogetherJS, but it is a development tool to try TogetherJS out on a site that hasn't integrated `togetherjs-min.js` itself.  When you activate the addon (via a link in the [Add-On Toolbar](https://support.mozilla.org/en-US/kb/add-on-bar-quick-access-to-add-ons)) it simply adds `togetherjs-min.js` to every page in that tab (until you close the tab or turn it off).  Also if you open a link with `#&togetherjs=...` (the code used in the share link) it will automatically turn TogetherJS on for the tab.\n\n### Installing\n\nA simple way to install is simply to [click this link](https://togetherjs.com/togetherjs.xpi) in Firefox, and install the addon.  You can turn the addon on or off via the addon manager.  No restart is required.\n\n### Building\n\nYou can build the addon using the [Addon-SDK](https://addons.mozilla.org/en-US/developers/builder). Once you've installed the SDK, go into the `addon/` directory and run `cfx xpi` to create an XPI (packaged addon file) or `cfx run` to start up Firefox with the addon installed (for development).\n\n## Getting Help\n\n### IRC / Live Chat\n\nWe are available on the `#togetherjs` channel on `irc.mozilla.org`. Logs are on [irclog.gr](http://irclog.gr/#browse/irc.mozilla.org/togetherjs)\n\nIf you don't use IRC, you can quickly join the chat from the web [using kiwiirc](https://kiwiirc.com/client/irc.mozilla.org/togetherjs).\n\n### Issues\n\nPlease submit any issues you have via [the Github issue tracker](https://github.com/mozilla/togetherjs/issues/new).\n\nDon't be shy about opening an issue.  If you have a question or feature request that might already be possible, we can exchange comments via the issue tracker to figure it out.  We don't have a mailing list, so issues are a good way to keep a persistent record of these exchanges.\n\n### Email\n\nFeel free to email us at [togetherjs@mozilla.com](mailto:togetherjs@mozilla.com) with any questions, suggestions, or concerns.\n"
  },
  {
    "path": "site/docs-contributing.tmpl",
    "content": "{% extends \"base.tmpl\" %}\n{# set enableMarkdown true #}\n{% block body_tag %}data-spy=\"scroll\" data-target=\"#markdownpages\"{% endblock %}\n{% block body %}\n\n<div class=\"container\">\n  <section class=\"row\" id=\"markdownpages\">\n    <div class=\"col-md-3\">\n      <div class=\"panel\" role=\"complementary\" data-spy=\"affix\" data-offset-top=\"200\" id=\"sidenav\">\n        <ul id=\"sectionmenu\" class=\"nav\">\n          <li><a href=\"#code-style\" class=\"scrollnavdocs\">Code Style</a></li>\n          <li><a href=\"#togetherjs-patterns\" class=\"scrollnavdocs\">TogetherJS Patterns</a></li>\n          <li><a href=\"#hosting-the-hub-server\" class=\"scrollnavdocs\">Hosting The Hub Server</a></li>\n          <li><a href=\"#the-issue-tracker-and-milestones\" class=\"Scrollnavdocs\">The Issue Tracker and Milestones</a></li>\n        </ul>\n        <div class=\"well\">\n          <button type=\"button\" class=\"btn btn-primary btn-lg btn-block\">\n            Get help\n          </button>\n          <div class=\"small text-center\">Get support from the TogetherJS team.</div>\n        </div>\n      </div>\n    </div>\n    <div class=\"col-md-9\">\n      <h1>{{ title }}</h1>\n      {{ markdownBody }}\n    </div>\n  </section>\n\n{% endblock %}\n"
  },
  {
    "path": "site/docs.tmpl",
    "content": "{% extends \"base.tmpl\" %}\n{# set enableMarkdown true #}\n{% block body_tag %}data-spy=\"scroll\" data-target=\"#markdownpages\"{% endblock %}\n{% block body %}\n\n<script type=\"text/javascript\" charset=\"utf-8\">\n  //adding active class\n  var activeurl = window.location.pathname;\n  if(activeurl == \"/docs/\") {\n    $( \".documentationActive\" ).addClass( \"active\" );\n  }\n</script>\n\n<div class=\"container\">\n  <section class=\"row\" id=\"markdownpages\">\n    <div class=\"col-md-3\">\n      <div class=\"panel\" role=\"complementary\" data-spy=\"affix\" data-offset-top=\"200\" data-offset-bottom=\"10\" id=\"sidenav\">\n        <ul id=\"sectionmenu\" class=\"nav\">\n          <li><a href=\"#\" class=\"scrollnavdocs\"></a></li>\n          <li><a href=\"#quick-start\" class=\"scrollnavdocs\">Quick Start</a></li>\n          <li><a href=\"#technology-overview\" class=\"scrollnavdocs\">Technology Overview</a></li>\n          <li><a href=\"#configuring-togetherjs\" class=\"scrollnavdocs\">Configuring TogetherJS</a></li>\n          <li><a href=\"#start-togetherjs-button\" class=\"scrollnavdocs\">Start TogetherJS Button</a></li>\n          <li><a href=\"#about-audio-chat-and-webrtc\" class=\"scrollnavdocs\">About Audio Chat and WebRTC</a></li>\n          <li><a href=\"#extending-togetherjs\" class=\"scrollnavdocs\">Extending TogetherJS</a></li>\n          <li><a href=\"#communication-channel\" class=\"scrollnavdocs\">Communication Channel</a></li>\n          <li><a href=\"#setting-identity-information\" class=\"scrollnavdocs\">Setting Identity Information</a></li>\n          <li><a href=\"#getting-a-static-copy-of-the-client\" class=\"scrollnavdocs\">Getting a Static Copy of the Client</a></li>\n          <li><a href=\"#browser-support\" class=\"scrollnavdocs\">Browser Support</a></li>\n          <li><a href=\"#hosting-the-hub-server\" class=\"scrollnavdocs\">Hosting the Hub Server</a></li>\n          <li><a href=\"#addons\" class=\"scrollnavdocs\">Addons</a></li>\n          <li><a href=\"#getting-help\" class=\"scrollnavdocs\">Getting Help</a></li>\n        </ul>\n        <div class=\"well\">\n          <button type=\"button\" class=\"btn btn-primary btn-lg btn-block\" id=\"get-help\">\n            Get Live Help\n          </button>\n          <div class=\"small text-center\">Get support from the TogetherJS team.\n          <div style=\"display: none\" id=\"nobody-home\">Sorry, no one is available at this time.</div>\n          </div>\n        </div>\n      </div>\n    </div>\n    <div class=\"col-md-9\">\n      <h1>{{ title }}</h1>\n      {{ markdownBody }}\n    </div>\n  </section>\n\n{% endblock %}\n"
  },
  {
    "path": "site/errors/404.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block title %} Mozilla Labs : 404 error {% endblock %}\n{# set enableExample false #}\n{# set absoluteLinks true #}\n{% block body %}\n\n<div class=\"container\">\n  <section class=\"body-content\" id=\"main-section\" data-speed=\"4\" data-type=\"background\">\n    <section class=\"row\" id=\"tour\">\n      <div class=\"col-xs-12\">\n        <div id=\"error\">\n            <p class=\"text-center\"><img src=\"/images/404-image.png\" class=\"img-responsive\" style=\"margin: 0 auto;\"></p>\n            <h1 class=\"text-center\">Oops, we can't find the page you're looking for!</h1>\n            <p class=\"text-center\">404 error</p>\n        </div>\n      </div>\n    </section>\n{% endblock %}\n"
  },
  {
    "path": "site/errors/500.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block title %} Mozilla Labs : 500 error {% endblock %}\n{# set enableExample false #}\n{# set absoluteLinks true #}\n{% block body %}\n\n<div class=\"container\">\n  <section class=\"body-content\" id=\"main-section\" data-speed=\"4\" data-type=\"background\">\n    <section class=\"row\" id=\"tour\">\n      <div class=\"col-xs-12\">\n        <div id=\"error\">\n            <p class=\"text-center\"><img src=\"/images/500-image.png\" class=\"img-responsive\" style=\"margin: 0 auto;\"></p>\n            <h1 class=\"text-center\">Dang. Something went wrong.</h1>\n            <p class=\"text-center\">500 error</p>\n        </div>\n      </div>\n    </section>\n\n{% endblock %}\n"
  },
  {
    "path": "site/examples/drawing/css/main.css",
    "content": ".upper-button {\n\tborder-bottom-left-radius: 0px;\n\tborder-bottom-right-radius: 0px;\n}\n.bottom-button {\n\tborder-top-left-radius: 0px;\n\tborder-top-right-radius: 0px;\n}\n.black-pick:hover {\n\tbackground-color: #000;\n\tborder-color: #000;\n}\n.black-pick {\n\tbackground-color: #202020;\n\tborder-color: #202020;\n}\n"
  },
  {
    "path": "site/examples/drawing/index.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block title %} Mozilla Labs : TogetherJS app integration example {% endblock %}\n{# set enableExample true #}\n{% block configs %}\n  <script>\n    var TogetherJSConfig_autoStart = true;\n    var TogetherJSConfig_suppressJoinConfirmation = true;\n    var TogetherJSConfig_dontShowClicks = \":not(canvas\"\n  </script>\n{% endblock %}\n{% block body %}\n  {% block styles %}\n    <link href=\"//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css\" rel=\"stylesheet\">\n    <link href=\"css/main.css\" rel=\"stylesheet\">\n  {% endblock %}\n\n  <div class=\"container\">\n    <section class=\"body-content row\" id=\"sketchapp\" style=\"margin-left: 0px; margin-right: 0px;\">\n        <h1 style=\"margin-bottom: 20px\">Drawing Example</h1>\n        <a class=\"pull-right tjsbutton\" onclick=\"TogetherJS(this); return false;\">\n          <img src=\"https://togetherjs.com/images/start-togetherjs-blue.png\" style=\"width: 125px;\"></img>\n        </a>\n        <p class=\"pull-left\" style=\"margin-bottom: 20px\">This is a simple drawing example.  Try drawing something with a friend in the canvas below!  Check out this code on <a href=\"http://jsfiddle.net/5f8FL/1/\" target=\"_blank\">JSFiddle  here</a>.</p>\n        <div class=\"btn-group btn-group-justified\" style=\"margin-left: auto; margin-right: auto;\">\n          <a class=\"btn btn-info color-picker upper-button\">Blue</a>          \n          <a class=\"btn btn-success color-picker\">Green</a>\n          <a class=\"btn btn-warning color-picker\">Yellow</a>\n          <a class=\"btn btn-danger color-picker\">Red</a>\n          <a class=\"btn btn-success color-picker black-pick upper-button\" style=\"border-bottom-width: 0px;\">Black</a>\n        </div>\n        <div class=\"clearfix\"></div>\n        <div id=\"sketchContainer\" style=\"width: 100%; border: 1px solid rgba(0,0,0,0.2);\">\n          <canvas id=\"sketch\"></canvas>\n        </div>\n        <div class=\"btn-group btn-group-justified\" style=\"margin-left: auto; margin-right: auto;\">\n          <a class=\"btn btn-info user-color-pick bottom-button\" style=\"width: 35%;\">User Color</a>\n          <a class=\"btn btn-success plus-size\" style=\"width: 15%;\">\n            <i class=\"fa fa-plus-square\"></i>\n          </a>\n          <a class=\"btn btn-warning clear\" style=\"width: 15%;\">\n            <i class=\"fa fa-times-circle\"></i>\n          </a>\n          <a class=\"btn btn-danger minus-size\" style=\"width: 15%;\">\n            <i class=\"fa fa-minus-square\"></i>\n          </a>\n          <a class=\"btn btn-default eraser bottom-button\" style=\"width: 35%; border-top-width: 0px;\">\n            <i class=\"fa fa-eraser\"></i>\n          </a>\n       </div>\n    </section>\n  </div>\n\n  <script src=\"js/sketch.js\"></script>\n{% endblock %}\n"
  },
  {
    "path": "site/examples/drawing/js/sketch.js",
    "content": "// get the canvas element and its context\nvar canvas = document.getElementById('sketch');\nvar context = canvas.getContext('2d');\n\n// the aspect ratio is always based on 1140x400, height is calculated from width:\ncanvas.width = $('#sketchContainer').outerWidth();\ncanvas.height = (canvas.width/1140)*400;\n$('#sketchContainer').outerHeight(String(canvas.height) + \"px\", true);\n// scale function needs to know the width/height pre-resizing:\nvar oWidth = canvas.width;\nvar oHeight = canvas.height;\nvar lines = [];\n\nvar lastMouse = {\n  x: 0,\n  y: 0\n};\n\nvar ongoingTouches = [];\n\n// brush settings\ncontext.lineWidth = 2;\ncontext.lineJoin = 'round';\ncontext.lineCap = 'round';\ncontext.strokeStyle = '#000';\n\n// attach the mousedown, mouseout, mousemove, mouseup event listeners.\ncanvas.addEventListener('mousedown', function (e) {\n  lastMouse = {\n    x: e.pageX - this.offsetLeft,\n    y: e.pageY - this.offsetTop\n  };\n  canvas.addEventListener('mousemove', move, false);\n}, false);\n\ncanvas.addEventListener('mouseout', function () {\n  canvas.removeEventListener('mousemove', move, false);\n}, false);\n\ncanvas.addEventListener('mouseup', function () {\n  canvas.removeEventListener('mousemove', move, false);\n}, false);\n\n// attach the touchstart, touchend, touchcancel, touchleave,\n// and touchmove event listeners.\ncanvas.addEventListener('touchstart', touchstart, false);\ncanvas.addEventListener('touchend', touchend, false);\ncanvas.addEventListener('touchcancel', touchcancel, false);\ncanvas.addEventListener('touchleave', touchend, false);\ncanvas.addEventListener('touchmove', touchmove, false);\n\n// Sets the brush size:\nfunction setSize(size) {\n  context.lineWidth = size;\n}\n\n// Sets the brush color:\nfunction setColor(color) {\n  context.globalCompositeOperation = 'source-over';\n  context.strokeStyle = color;\n}\n\n// Sets the brush to erase-mode:\nfunction eraser() {\n  context.globalCompositeOperation = 'destination-out';\n  context.strokeStyle = 'rgba(0,0,0,1)';\n}\n\n// Clears the canvas and the lines-array:\nfunction clear(send) {\n  context.clearRect(0, 0, canvas.width, canvas.height);\n  lines = [];\n  if (send && TogetherJS.running) {\n    TogetherJS.send({\n      type: 'clear'\n    });\n  }\n}\n\n// Redraws the lines from the lines-array:\nfunction reDraw(lines){\n  for (var i in lines) {\n    draw(lines[i][0], lines[i][1], lines[i][2], lines[i][3], lines[i][4], false);\n  }\n}\n// Draws the lines, called by move and the TogetherJS event listener:\nfunction draw(start, end, color, size, compositeOperation, save) {\n  context.save();\n  context.lineJoin = 'round'; \n  context.lineCap = 'round';\n  // Since the coordinates have been translated to an 1140x400 canvas, the context needs to be scaled before it can be drawn on:\n  context.scale(canvas.width/1140,canvas.height/400);\n  context.strokeStyle = color;\n  context.globalCompositeOperation = compositeOperation;\n  context.lineWidth = size;\n  context.beginPath();\n  context.moveTo(start.x, start.y);\n  context.lineTo(end.x, end.y);\n  context.closePath();\n  context.stroke();\n  context.restore();\n  if (save) {\n    // Won't save if draw() is called from reDraw().\n    lines.push([{x: start.x, y: start.y}, {x: end.x, y: end.y}, color, size, compositeOperation]);\n  }\n}\n\n// Called whenever the mousemove event is fired, calls the draw function:\nfunction move(e) {\n  var mouse = {\n    x: e.pageX - this.offsetLeft,\n    y: e.pageY - this.offsetTop\n  };\n  // Translates the coordinates from the local canvas size to 1140x400:\n  sendMouse = {\n    x: (1140/canvas.width)*mouse.x,\n    y: (400/canvas.height)*mouse.y\n  };\n  sendLastMouse = {\n    x: (1140/canvas.width)*lastMouse.x,\n    y: (400/canvas.height)*lastMouse.y\n  };\n  draw(sendLastMouse, sendMouse, context.strokeStyle, context.lineWidth, context.globalCompositeOperation, true);\n  if (TogetherJS.running) {\n    TogetherJS.send({\n      type: 'draw',\n      start: sendLastMouse,\n      end: sendMouse,\n      color: context.strokeStyle,\n      size: context.lineWidth,\n      compositeOperation: context.globalCompositeOperation\n    });\n  }\n  lastMouse = mouse;\n}\n\n// Convenience method to convert touch position to 1140x400 position\nfunction convertTouch(touch) {\n  return {\n    x: (1140 / canvas.width) * (touch.pageX - canvas.offsetLeft),\n    y: (400 / canvas.height) * (touch.pageY - canvas.offsetTop),\n    identifier: touch.identifier\n  };\n}\n\n// Do a linear search for an ongoing touch with a particular identifier\n// Return the index into ongoingTouches, or -1 if not found\nfunction searchOngoingTouches(identifier) {\n  for (var i = 0; i < ongoingTouches.length; i++) {\n    if (ongoingTouches[i].identifier == identifier) {\n      return i;\n    }\n  }\n  return -1;\n}\n\n// Called whenever the touchstart event is fired\nfunction touchstart(e) {\n  e.preventDefault();\n  var touches = e.changedTouches;\n  for (var i = 0; i < touches.length; i++) {\n    var idx = searchOngoingTouches(touches[i].identifier);\n    ongoingTouches.push(convertTouch(touches[i]));\n  }\n}\n\n// Called whenever the touchmove event is fired, calls the draw function\nfunction touchmove(e) {\n  e.preventDefault();\n  var touches = e.changedTouches;\n  for (var i = 0; i < touches.length; i++) {\n    var idx = searchOngoingTouches(touches[i].identifier);\n    if (idx >= 0) {\n      var lastTouch = ongoingTouches[idx];\n      var touch = convertTouch(touches[i]);\n      draw(lastTouch, touch, context.strokeStyle, context.lineWidth, context.globalCompositeOperation, true);\n      if (TogetherJS.running) {\n        TogetherJS.send({\n          type: 'draw',\n          start: lastTouch,\n          end: touch,\n          color: context.strokeStyle,\n          size: context.lineWidth,\n          compositeOperation: context.globalCompositeOperation\n        });\n      }\n      ongoingTouches.splice(idx, 1, touch);\n    }\n  }\n}\n\n// Called whenever touchend or touchleave events are fired\nfunction touchend(e) {\n  e.preventDefault();\n  var touches = e.changedTouches;\n  for (var i = 0; i < touches.length; i++) {\n    var idx = searchOngoingTouches(touches[i].identifier);\n    if (idx >= 0) {\n      var lastTouch = ongoingTouches[idx];\n      var touch = convertTouch(touches[i]);\n      draw(lastTouch, touch, context.strokeStyle, context.lineWidth, context.globalCompositeOperation, true);\n      if (TogetherJS.running) {\n        TogetherJS.send({\n          type: 'draw',\n          start: lastTouch,\n          end: touch,\n          color: context.strokeStyle,\n          size: context.lineWidth,\n          compositeOperation: context.globalCompositeOperation\n        });\n      }\n      ongoingTouches.splice(idx, 1);\n    }\n  }\n}\n\n// Called whenever touchcancel event is fired\nfunction touchcancel(e) {\n  e.preventDefault();\n  var touches = e.changedTouches;\n  for (var i = 0; i < touches.length; i++) {\n    var idx = searchOngoingTouches(touches[i].identifier);\n    if (idx >= 0) {\n      ongoingTouches.splice(idx, 1);\n    }\n  }\n}\n\n// Listens for draw messages, sends info about the drawn lines:\nTogetherJS.hub.on('draw', function (msg) {\n  if (!msg.sameUrl) {\n      return;\n  }\n  draw(msg.start, msg.end, msg.color, msg.size, msg.compositeOperation, true);\n});\n\n\n// Clears the canvas whenever someone presses the clear-button\nTogetherJS.hub.on('clear', function (msg) {\n  if (!msg.sameUrl) {\n    return;\n  }\n  clear(false);\n});\n\n// Hello is sent from every newly connected user, this way they will receive what has already been drawn:\nTogetherJS.hub.on('togetherjs.hello', function () {\n  TogetherJS.send({\n    type: 'init',\n    lines: lines\n  });\n});\n\n// Draw initially received drawings:\nTogetherJS.hub.on('init', function (msg) {\n  reDraw(msg.lines);\n  lines = msg.lines;\n});\n\n// JQuery to handle buttons and resizing events, also changes the cursor to a dot resembling the brush size:\n$(document).ready(function () {\n  // changeMouse creates a temporary invisible canvas that shows the cursor, which is then set as the cursor through css:\n  function changeMouse() {\n    // Makes sure the cursorSize is scaled:\n    var cursorSize = context.lineWidth*(canvas.width/1140); \n    if (cursorSize < 10){\n        cursorSize = 10;\n    }\n    var cursorColor = context.strokeStyle;\n    var cursorGenerator = document.createElement('canvas');\n    cursorGenerator.width = cursorSize;\n    cursorGenerator.height = cursorSize;\n    var ctx = cursorGenerator.getContext('2d');\n\n    var centerX = cursorGenerator.width/2;\n    var centerY = cursorGenerator.height/2;\n\n    ctx.beginPath();\n    ctx.arc(centerX, centerY, (cursorSize/2)-4, 0, 2 * Math.PI, false);\n    ctx.lineWidth = 3;\n    ctx.strokeStyle = cursorColor;\n    ctx.stroke();\n    $('#sketch').css('cursor', 'url(' + cursorGenerator.toDataURL('image/png') + ') ' + cursorSize/2 + ' ' + cursorSize/2 + ',crosshair');\n  }\n  // Init mouse\n  changeMouse();\n\n  // Redraws the lines whenever the canvas is resized:\n  $(window).resize(function() {\n    if ($('#sketchContainer').width() != oWidth) {\n      canvas.width = $('#sketchContainer').width();\n      canvas.height = (canvas.width/1140)*400;\n      $('#sketchContainer').outerHeight(String(canvas.height)+\"px\", true);\n      var ratio = canvas.width/oWidth;\n      oWidth = canvas.width;\n      oHeight = canvas.height;\n      reDraw(lines);\n      changeMouse();\n    }\n  });\n\n  // Clears the canvas:\n  $('.clear').click(function () {\n    clear(true);\n  });\n\n  // Color-button functions:\n  $('.color-picker').click(function () {\n    var $this = $(this);\n    console.log($this);\n    setColor($this.css(\"background-color\"));\n    changeMouse();\n  });\n\n  $('.eraser').click(function () {\n    eraser();\n    changeMouse();\n  });\n  // TogetherJS user color:\n  $('.user-color-pick').click(function() {\n    setColor(TogetherJS.require('peers').Self.color);\n    changeMouse();\n  });\n\n  // Increase/decrease brush size:\n  $('.plus-size').click(function() {\n    setSize(context.lineWidth+3);\n    changeMouse();\n  });\n\n  $('.minus-size').click(function() {\n    if (context.lineWidth > 3) {\n      setSize(context.lineWidth-3);\n    }\n    changeMouse();\n  });          \n});\n"
  },
  {
    "path": "site/examples/friendlycode/.gitignore",
    "content": "js/friendlycode-built.js\ncss/friendlycode-built.css\nnode_modules/\n"
  },
  {
    "path": "site/examples/friendlycode/.gitmodules",
    "content": "[submodule \"slowparse\"]\n\tpath = slowparse\n\turl = git://github.com/mozilla/slowparse.git\n"
  },
  {
    "path": "site/examples/friendlycode/LICENSE.html",
    "content": "<!DOCTYPE html>\n<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <title>Mozilla Public License, version 2.0</title>\n  <!--[if lt IE 9]>\n    <script src=\"http://html5shim.googlecode.com/svn/trunk/html5.js\"></script>\n  <![endif]-->\n\n  <link href=\"LICENSE_files/css_002.css\" rel=\"stylesheet\" type=\"text/css\">\n  <link href=\"LICENSE_files/css_003.css\" rel=\"stylesheet\" type=\"text/css\">\n  <link href=\"LICENSE_files/css.css\" rel=\"stylesheet\" type=\"text/css\">\n\n  <style type=\"text/css\">\n\tbody { \tfont-family: 'Crimson Text', serif; \n\t\tmax-width: 30em; \n\t\tmargin-left:auto;\n\t\tmargin-right:auto;\n\t\ttext-align: justify;\n\t\t-moz-hyphens: auto;\n\t\tfont-size: 110%\n\t\t}\n\n\th1, h2, h3 { \n\t\tfont-family: 'Lora', serif;\n\t     \tfont-variant: small-caps;\n\t\t}\n\n\th1 { \n\t\ttext-align: center;\n\t\t-moz-hyphens: none;\n\t\tfont-size: 160%;\n\t\t}\n\th2 {\n\t\tfont-size: 140%;\n\t\t-moz-hyphens: none;\n\t\ttext-align: left;\n\t\t}\n\th3 {\t\n\t\tfont-size: 120%;\n\t\t-moz-hyphens: none;\n\t\ttext-align: left;\t\t\n\t\t}\n\n\tblockquote { \t\n\t\tfont-family: 'Droid Sans Mono', mono;\n\t\ttext-align: left; \n\t\t-moz-hyphens: none;\n\t\t}\n\t\n\tcode {\n\t\tfont-family: 'Droid Sans Mono', mono;\n\t\t}\n\n\tem {\n\t\tbackground: #FEFD80;\n\t\tborder: 30px solid #FEFD80;\n\t\tfloat: left;\n\t\tline-height: 1.25em;\n    \t\tmargin-left: 10px;\n\t\tmargin-right: 10px;\n\t\tmargin-bottom: 10px;\n\t\tmargin-top:-10px;\n/*\t\ttext-transform: uppercase; */\n\t\tfont-style: normal;\n\t}\n\n\tdt {\tfont-family: 'Lora', serif;\n\t\tfont-weight: bold; \n\t\tfont-size: 100%;\n\t\t}\n\n  </style>\n</head>\n<body>\n<h1 id=\"mozilla-public-license-version-2.0\">Mozilla Public License<br>Version 2.0</h1>\n<h2 id=\"definitions\">1. Definitions</h2>\n<dl>\n<dt>1.1. “Contributor”</dt>\n<dd><p>means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software.</p>\n</dd>\n<dt>1.2. “Contributor Version”</dt>\n<dd><p>means the combination of the Contributions of others (if any) \nused by a Contributor and that particular Contributor’s Contribution.</p>\n</dd>\n<dt>1.3. “Contribution”</dt>\n<dd><p>means Covered Software of a particular Contributor.</p>\n</dd>\n<dt>1.4. “Covered Software”</dt>\n<dd><p>means Source Code Form to which the initial Contributor has \nattached the notice in Exhibit A, the Executable Form of such Source \nCode Form, and Modifications of such Source Code Form, in each case \nincluding portions thereof.</p>\n</dd>\n<dt>1.5. “Incompatible With Secondary Licenses”</dt>\n<dd><p>means</p>\n<ol type=\"a\">\n<li><p>that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or</p></li>\n<li><p>that the Covered Software was made available under the terms of \nversion 1.1 or earlier of the License, but not also under the terms of a\n Secondary License.</p></li>\n</ol>\n</dd>\n<dt>1.6. “Executable Form”</dt>\n<dd><p>means any form of the work other than Source Code Form.</p>\n</dd>\n<dt>1.7. “Larger Work”</dt>\n<dd><p>means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software.</p>\n</dd>\n<dt>1.8. “License”</dt>\n<dd><p>means this document.</p>\n</dd>\n<dt>1.9. “Licensable”</dt>\n<dd><p>means having the right to grant, to the maximum extent possible, \nwhether at the time of the initial grant or subsequently, any and all of\n the rights conveyed by this License.</p>\n</dd>\n<dt>1.10. “Modifications”</dt>\n<dd><p>means any of the following:</p>\n<ol type=\"a\">\n<li><p>any file in Source Code Form that results from an addition to, \ndeletion from, or modification of the contents of Covered Software; or</p></li>\n<li><p>any new file in Source Code Form that contains any Covered Software.</p></li>\n</ol>\n</dd>\n<dt>1.11. “Patent Claims” of a Contributor</dt>\n<dd><p>means any patent claim(s), including without limitation, method, \nprocess, and apparatus claims, in any patent Licensable by such \nContributor that would be infringed, but for the grant of the License, \nby the making, using, selling, offering for sale, having made, import, \nor transfer of either its Contributions or its Contributor Version.</p>\n</dd>\n<dt>1.12. “Secondary License”</dt>\n<dd><p>means either the GNU General Public License, Version 2.0, the GNU\n Lesser General Public License, Version 2.1, the GNU Affero General \nPublic License, Version 3.0, or any later versions of those licenses.</p>\n</dd>\n<dt>1.13. “Source Code Form”</dt>\n<dd><p>means the form of the work preferred for making modifications.</p>\n</dd>\n<dt>1.14. “You” (or “Your”)</dt>\n<dd><p>means an individual or a legal entity exercising rights under \nthis License. For legal entities, “You” includes any entity that \ncontrols, is controlled by, or is under common control with You. For \npurposes of this definition, “control” means (a) the power, direct or \nindirect, to cause the direction or management of such entity, whether \nby contract or otherwise, or (b) ownership of more than fifty percent \n(50%) of the outstanding shares or beneficial ownership of such entity.</p>\n</dd>\n</dl>\n<h2 id=\"license-grants-and-conditions\">2. License Grants and Conditions</h2>\n<h3 id=\"grants\">2.1. Grants</h3>\n<p>Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license:</p>\n<ol type=\"a\">\n<li><p>under intellectual property rights (other than patent or \ntrademark) Licensable by such Contributor to use, reproduce, make \navailable, modify, display, perform, distribute, and otherwise exploit \nits Contributions, either on an unmodified basis, with Modifications, or\n as part of a Larger Work; and</p></li>\n<li><p>under Patent Claims of such Contributor to make, use, sell, offer\n for sale, have made, import, and otherwise transfer either its \nContributions or its Contributor Version.</p></li>\n</ol>\n<h3 id=\"effective-date\">2.2. Effective Date</h3>\n<p>The licenses granted in Section&nbsp;2.1 with respect to any \nContribution become effective for each Contribution on the date the \nContributor first distributes such Contribution.</p>\n<h3 id=\"limitations-on-grant-scope\">2.3. Limitations on Grant Scope</h3>\n<p>The licenses granted in this Section&nbsp;2 are the only rights \ngranted under this License. No additional rights or licenses will be \nimplied from the distribution or licensing of Covered Software under \nthis License. Notwithstanding Section&nbsp;2.1(b) above, no patent \nlicense is granted by a Contributor:</p>\n<ol type=\"a\">\n<li><p>for any code that a Contributor has removed from Covered Software; or</p></li>\n<li><p>for infringements caused by: (i) Your and any other third party’s\n modifications of Covered Software, or (ii) the combination of its \nContributions with other software (except as part of its Contributor \nVersion); or</p></li>\n<li><p>under Patent Claims infringed by Covered Software in the absence of its Contributions.</p></li>\n</ol>\n<p>This License does not grant any rights in the trademarks, service \nmarks, or logos of any Contributor (except as may be necessary to comply\n with the notice requirements in Section&nbsp;3.4).</p>\n<h3 id=\"subsequent-licenses\">2.4. Subsequent Licenses</h3>\n<p>No Contributor makes additional grants as a result of Your choice to \ndistribute the Covered Software under a subsequent version of this \nLicense (see Section&nbsp;10.2) or under the terms of a Secondary \nLicense (if permitted under the terms of Section&nbsp;3.3).</p>\n<h3 id=\"representation\">2.5. Representation</h3>\n<p>Each Contributor represents that the Contributor believes its \nContributions are its original creation(s) or it has sufficient rights \nto grant the rights to its Contributions conveyed by this License.</p>\n<h3 id=\"fair-use\">2.6. Fair Use</h3>\n<p>This License is not intended to limit any rights You have under \napplicable copyright doctrines of fair use, fair dealing, or other \nequivalents.</p>\n<h3 id=\"conditions\">2.7. Conditions</h3>\n<p>Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section&nbsp;2.1.</p>\n<h2 id=\"responsibilities\">3. Responsibilities</h2>\n<h3 id=\"distribution-of-source-form\">3.1. Distribution of Source Form</h3>\n<p>All distribution of Covered Software in Source Code Form, including \nany Modifications that You create or to which You contribute, must be \nunder the terms of this License. You must inform recipients that the \nSource Code Form of the Covered Software is governed by the terms of \nthis License, and how they can obtain a copy of this License. You may \nnot attempt to alter or restrict the recipients’ rights in the Source \nCode Form.</p>\n<h3 id=\"distribution-of-executable-form\">3.2. Distribution of Executable Form</h3>\n<p>If You distribute Covered Software in Executable Form then:</p>\n<ol type=\"a\">\n<li><p>such Covered Software must also be made available in Source Code \nForm, as described in Section&nbsp;3.1, and You must inform recipients \nof the Executable Form how they can obtain a copy of such Source Code \nForm by reasonable means in a timely manner, at a charge no more than \nthe cost of distribution to the recipient; and</p></li>\n<li><p>You may distribute such Executable Form under the terms of this \nLicense, or sublicense it under different terms, provided that the \nlicense for the Executable Form does not attempt to limit or alter the \nrecipients’ rights in the Source Code Form under this License.</p></li>\n</ol>\n<h3 id=\"distribution-of-a-larger-work\">3.3. Distribution of a Larger Work</h3>\n<p>You may create and distribute a Larger Work under terms of Your \nchoice, provided that You also comply with the requirements of this \nLicense for the Covered Software. If the Larger Work is a combination of\n Covered Software with a work governed by one or more Secondary \nLicenses, and the Covered Software is not Incompatible With Secondary \nLicenses, this License permits You to additionally distribute such \nCovered Software under the terms of such Secondary License(s), so that \nthe recipient of the Larger Work may, at their option, further \ndistribute the Covered Software under the terms of either this License \nor such Secondary License(s).</p>\n<h3 id=\"notices\">3.4. Notices</h3>\n<p>You may not remove or alter the substance of any license notices \n(including copyright notices, patent notices, disclaimers of warranty, \nor limitations of liability) contained within the Source Code Form of \nthe Covered Software, except that You may alter any license notices to \nthe extent required to remedy known factual inaccuracies.</p>\n<h3 id=\"application-of-additional-terms\">3.5. Application of Additional Terms</h3>\n<p>You may choose to offer, and to charge a fee for, warranty, support, \nindemnity or liability obligations to one or more recipients of Covered \nSoftware. However, You may do so only on Your own behalf, and not on \nbehalf of any Contributor. You must make it absolutely clear that any \nsuch warranty, support, indemnity, or liability obligation is offered by\n You alone, and You hereby agree to indemnify every Contributor for any \nliability incurred by such Contributor as a result of warranty, support,\n indemnity or liability terms You offer. You may include additional \ndisclaimers of warranty and limitations of liability specific to any \njurisdiction.</p>\n<h2 id=\"inability-to-comply-due-to-statute-or-regulation\">4. Inability to Comply Due to Statute or Regulation</h2>\n<p>If it is impossible for You to comply with any of the terms of this \nLicense with respect to some or all of the Covered Software due to \nstatute, judicial order, or regulation then You must: (a) comply with \nthe terms of this License to the maximum extent possible; and (b) \ndescribe the limitations and the code they affect. Such description must\n be placed in a text file included with all distributions of the Covered\n Software under this License. Except to the extent prohibited by statute\n or regulation, such description must be sufficiently detailed for a \nrecipient of ordinary skill to be able to understand it.</p>\n<h2 id=\"termination\">5. Termination</h2>\n<p>5.1. The rights granted under this License will terminate \nautomatically if You fail to comply with any of its terms. However, if \nYou become compliant, then the rights granted under this License from a \nparticular Contributor are reinstated (a) provisionally, unless and \nuntil such Contributor explicitly and finally terminates Your grants, \nand (b) on an ongoing basis, if such Contributor fails to notify You of \nthe non-compliance by some reasonable means prior to 60 days after You \nhave come back into compliance. Moreover, Your grants from a particular \nContributor are reinstated on an ongoing basis if such Contributor \nnotifies You of the non-compliance by some reasonable means, this is the\n first time You have received notice of non-compliance with this License\n from such Contributor, and You become compliant prior to 30 days after \nYour receipt of the notice.</p>\n<p>5.2. If You initiate litigation against any entity by asserting a \npatent infringement claim (excluding declaratory judgment actions, \ncounter-claims, and cross-claims) alleging that a Contributor Version \ndirectly or indirectly infringes any patent, then the rights granted to \nYou by any and all Contributors for the Covered Software under \nSection&nbsp;2.1 of this License shall terminate.</p>\n<p>5.3. In the event of termination under Sections&nbsp;5.1 or 5.2 \nabove, all end user license agreements (excluding distributors and \nresellers) which have been validly granted by You or Your distributors \nunder this License prior to termination shall survive termination.</p>\n<h2 id=\"disclaimer-of-warranty\">6. Disclaimer of Warranty</h2>\n<p><em>Covered Software is provided under this License on an “as is” \nbasis, without warranty of any kind, either expressed, implied, or \nstatutory, including, without limitation, warranties that the Covered \nSoftware is free of defects, merchantable, fit for a particular purpose \nor non-infringing. The entire risk as to the quality and performance of \nthe Covered Software is with You. Should any Covered Software prove \ndefective in any respect, You (not any Contributor) assume the cost of \nany necessary servicing, repair, or correction. This disclaimer of \nwarranty constitutes an essential part of this License. No use of any \nCovered Software is authorized under this License except under this \ndisclaimer.</em></p>\n<h2 id=\"limitation-of-liability\">7. Limitation of Liability</h2>\n<p><em>Under no circumstances and under no legal theory, whether tort \n(including negligence), contract, or otherwise, shall any Contributor, \nor anyone who distributes Covered Software as permitted above, be liable\n to You for any direct, indirect, special, incidental, or consequential \ndamages of any character including, without limitation, damages for lost\n profits, loss of goodwill, work stoppage, computer failure or \nmalfunction, or any and all other commercial damages or losses, even if \nsuch party shall have been informed of the possibility of such damages. \nThis limitation of liability shall not apply to liability for death or \npersonal injury resulting from such party’s negligence to the extent \napplicable law prohibits such limitation. Some jurisdictions do not \nallow the exclusion or limitation of incidental or consequential \ndamages, so this exclusion and limitation may not apply to You.</em></p>\n<h2 id=\"litigation\">8. Litigation</h2>\n<p>Any litigation relating to this License may be brought only in the \ncourts of a jurisdiction where the defendant maintains its principal \nplace of business and such litigation shall be governed by laws of that \njurisdiction, without reference to its conflict-of-law provisions. \nNothing in this Section shall prevent a party’s ability to bring \ncross-claims or counter-claims.</p>\n<h2 id=\"miscellaneous\">9. Miscellaneous</h2>\n<p>This License represents the complete agreement concerning the subject\n matter hereof. If any provision of this License is held to be \nunenforceable, such provision shall be reformed only to the extent \nnecessary to make it enforceable. Any law or regulation which provides \nthat the language of a contract shall be construed against the drafter \nshall not be used to construe this License against a Contributor.</p>\n<h2 id=\"versions-of-the-license\">10. Versions of the License</h2>\n<h3 id=\"new-versions\">10.1. New Versions</h3>\n<p>Mozilla Foundation is the license steward. Except as provided in \nSection&nbsp;10.3, no one other than the license steward has the right \nto modify or publish new versions of this License. Each version will be \ngiven a distinguishing version number.</p>\n<h3 id=\"effect-of-new-versions\">10.2. Effect of New Versions</h3>\n<p>You may distribute the Covered Software under the terms of the \nversion of the License under which You originally received the Covered \nSoftware, or under the terms of any subsequent version published by the \nlicense steward.</p>\n<h3 id=\"modified-versions\">10.3. Modified Versions</h3>\n<p>If you create software not governed by this License, and you want to \ncreate a new license for such software, you may create and use a \nmodified version of this License if you rename the license and remove \nany references to the name of the license steward (except to note that \nsuch modified license differs from this License).</p>\n<h3 id=\"distributing-source-code-form-that-is-incompatible-with-secondary-licenses\">10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses</h3>\n<p>If You choose to distribute Source Code Form that is Incompatible \nWith Secondary Licenses under the terms of this version of the License, \nthe notice described in Exhibit B of this License must be attached.</p>\n<h2 id=\"exhibit-a---source-code-form-license-notice\">Exhibit A - Source Code Form License Notice</h2>\n<blockquote>\n<p>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/.</p>\n</blockquote>\n<p>If it is not possible or desirable to put the notice in a particular \nfile, then You may include the notice in a location (such as a LICENSE \nfile in a relevant directory) where a recipient would be likely to look \nfor such a notice.</p>\n<p>You may add additional accurate notices of copyright ownership.</p>\n<h2 id=\"exhibit-b---incompatible-with-secondary-licenses-notice\">Exhibit B - “Incompatible With Secondary Licenses” Notice</h2>\n<blockquote>\n<p>This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.</p>\n</blockquote>\n\n\n</body></html>"
  },
  {
    "path": "site/examples/friendlycode/LICENSE_files/css.css",
    "content": "@font-face {\n  font-family: 'Droid Sans Mono';\n  font-style: normal;\n  font-weight: normal;\n  src: local('Droid Sans Mono'), local('DroidSansMono'), url('http://themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJaH0X__W3S3MJL29bc5CWfs.woff') format('woff');\n}\n"
  },
  {
    "path": "site/examples/friendlycode/LICENSE_files/css_002.css",
    "content": "@font-face {\n  font-family: 'Crimson Text';\n  font-style: normal;\n  font-weight: normal;\n  src: local('Crimson Text'), local('CrimsonText-Roman'), url('http://themes.googleusercontent.com/static/fonts/crimsontext/v3/3IFMwfRa07i-auYR-B-zNaRDOzjiPcYnFooOUGCOsRk.woff') format('woff');\n}\n"
  },
  {
    "path": "site/examples/friendlycode/LICENSE_files/css_003.css",
    "content": "@font-face {\n  font-family: 'Lora';\n  font-style: normal;\n  font-weight: normal;\n  src: local('Lora'), url('http://themes.googleusercontent.com/static/fonts/lora/v5/nAKwuw6_dIh5kwvpj3ShNfesZW2xOQ-xsNqO47m55DA.woff') format('woff');\n}\n"
  },
  {
    "path": "site/examples/friendlycode/README.md",
    "content": "This is a friendly HTML editor that uses [slowparse][] and [hacktionary][]\nto provide ultra-friendly real-time help to novice webmakers.\n\n## Updating CodeMirror\n\nIn the `codemirror2` directory is a mini-distribution of [CodeMirror][]\nwhich contains only the files necessary for HTML editing. It can be updated\nwith the following Python script, if it is run from the root directory\nof the repository and the value of `NEW_CODEMIRROR_PATH` is changed:\n\n```python\nimport os\n\nNEW_CODEMIRROR_PATH = \"/path/to/new/codemirror/version\"\nOUR_CODEMIRROR_PATH = os.path.abspath(\"codemirror2\")\n\nfor dirpath, dirnames, filenames in os.walk(OUR_CODEMIRROR_PATH):\n    for filename in filenames:\n        ourpath = os.path.join(dirpath, filename)\n        relpath = os.path.relpath(ourpath, OUR_CODEMIRROR_PATH)\n        newpath = os.path.join(NEW_CODEMIRROR_PATH, relpath)\n        if os.path.exists(newpath):\n            print \"copying %s\" % newpath\n            open(ourpath, \"wb\").write(open(newpath, \"rb\").read())\n```\n\n  [slowparse]: https://github.com/toolness/slowparse\n  [hacktionary]: https://github.com/toolness/hacktionary\n  [CodeMirror]: http://codemirror.net/\n"
  },
  {
    "path": "site/examples/friendlycode/build-require.js",
    "content": "/**\n * to run this script,\n *  1. install npm, `curl http://npmjs.org/install.sh | sh`\n *     https://github.com/isaacs/npm\n *  2. command `npm install` at this directory.\n *  3. command `node build-require.js` or `npm start`\n */\nvar requirejs = require('requirejs'),\n  resolve = require('path').resolve,\n  requireConfig = require('./js/require-config'),\n  baseUrl = resolve(__dirname, 'js'),\n  name = 'friendlycode',\n  out = resolve(baseUrl, 'friendlycode-built.js');\n\nfunction optimize(done) {\n  requirejs.optimize(generateConfig(), done);\n}\n\nfunction generateConfig() {\n  var config = {\n    name: name,\n    out: out,\n    // use none optimize for debugging\n    optimize: \"none\",\n    // optimize: 'uglify',\n    uglify: {\n      // beautify for debugging\n      // beautify: true,\n      mangle: true\n    },\n    // TODO  above config setting is temporary, it shuould use mainConfigFile\n    // https://github.com/toolness/friendlycode/pull/112#issuecomment-6625412\n    // mainConfigFile: \"./js/main.js\",\n  };\n  Object.keys(requireConfig).forEach(function(name) {\n    config[name] = requireConfig[name];\n  });\n  return config;\n}\n\nfunction selfTest() {\n  var assert = require('assert'),\n      config = generateConfig();\n      \n  assert('paths' in config);\n  assert('jquery' in config.shim);\n}\n\nif (!module.parent) {\n  if (process.argv[2] == 'test') {\n    selfTest();\n    console.log(\"Tests pass!\");\n    process.exit(0);\n  } else {\n    console.log(\"Generating\", out);\n\n    optimize(function (buildResponse) {\n      // buildResponse is just a text output of the modules\n      // included.\n      console.log(\"Done. About \" + buildResponse.split('\\n').length +\n                  \" modules are inside the generated JS file.\");\n      requirejs.optimize({\n        cssIn: \"css/friendlycode.css\",\n        out: \"css/friendlycode-built.css\"\n      }, function() {\n        console.log(\"Optimized CSS.\");\n        process.exit();\n      });\n    });\n  }\n}\n"
  },
  {
    "path": "site/examples/friendlycode/codemirror2/lib/codemirror.css",
    "content": ".CodeMirror {\n  line-height: 1em;\n  font-family: monospace;\n}\n\n.CodeMirror-scroll {\n  overflow: auto;\n  height: 300px;\n  /* This is needed to prevent an IE[67] bug where the scrolled content\n     is visible outside of the scrolling box. */\n  position: relative;\n  outline: none;\n}\n\n.CodeMirror-gutter {\n  position: absolute; left: 0; top: 0;\n  z-index: 10;\n  background-color: #f7f7f7;\n  border-right: 1px solid #eee;\n  min-width: 2em;\n  height: 100%;\n}\n.CodeMirror-gutter-text {\n  color: #aaa;\n  text-align: right;\n  padding: .4em .2em .4em .4em;\n  white-space: pre !important;\n}\n.CodeMirror-lines {\n  padding: .4em;\n  white-space: pre;\n}\n\n.CodeMirror pre {\n  -moz-border-radius: 0;\n  -webkit-border-radius: 0;\n  -o-border-radius: 0;\n  border-radius: 0;\n  border-width: 0; margin: 0; padding: 0; background: transparent;\n  font-family: inherit;\n  font-size: inherit;\n  padding: 0; margin: 0;\n  white-space: pre;\n  word-wrap: normal;\n  line-height: inherit;\n  color: inherit;\n}\n\n.CodeMirror-wrap pre {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n  word-break: normal;\n}\n.CodeMirror-wrap .CodeMirror-scroll {\n  overflow-x: hidden;\n}\n\n.CodeMirror textarea {\n  outline: none !important;\n}\n\n.CodeMirror pre.CodeMirror-cursor {\n  z-index: 10;\n  position: absolute;\n  visibility: hidden;\n  border-left: 1px solid black;\n  border-right: none;\n  width: 0;\n}\n.cm-keymap-fat-cursor pre.CodeMirror-cursor {\n  width: auto;\n  border: 0;\n  background: transparent;\n  background: rgba(0, 200, 0, .4);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);\n}\n/* Kludge to turn off filter in ie9+, which also accepts rgba */\n.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}\n.CodeMirror-focused pre.CodeMirror-cursor {\n  visibility: visible;\n}\n\ndiv.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; }\n\n.CodeMirror-searching {\n  background: #ffa;\n  background: rgba(255, 255, 0, .4);\n}\n\n/* Default theme */\n\n.cm-s-default span.cm-keyword {color: #708;}\n.cm-s-default span.cm-atom {color: #219;}\n.cm-s-default span.cm-number {color: #164;}\n.cm-s-default span.cm-def {color: #00f;}\n.cm-s-default span.cm-variable {color: black;}\n.cm-s-default span.cm-variable-2 {color: #05a;}\n.cm-s-default span.cm-variable-3 {color: #085;}\n.cm-s-default span.cm-property {color: black;}\n.cm-s-default span.cm-operator {color: black;}\n.cm-s-default span.cm-comment {color: #a50;}\n.cm-s-default span.cm-string {color: #a11;}\n.cm-s-default span.cm-string-2 {color: #f50;}\n.cm-s-default span.cm-meta {color: #555;}\n.cm-s-default span.cm-error {color: #f00;}\n.cm-s-default span.cm-qualifier {color: #555;}\n.cm-s-default span.cm-builtin {color: #30a;}\n.cm-s-default span.cm-bracket {color: #cc7;}\n.cm-s-default span.cm-tag {color: #170;}\n.cm-s-default span.cm-attribute {color: #00c;}\n.cm-s-default span.cm-header {color: blue;}\n.cm-s-default span.cm-quote {color: #090;}\n.cm-s-default span.cm-hr {color: #999;}\n.cm-s-default span.cm-link {color: #00c;}\n\nspan.cm-header, span.cm-strong {font-weight: bold;}\nspan.cm-em {font-style: italic;}\nspan.cm-emstrong {font-style: italic; font-weight: bold;}\nspan.cm-link {text-decoration: underline;}\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n"
  },
  {
    "path": "site/examples/friendlycode/codemirror2/lib/codemirror.js",
    "content": "// CodeMirror version 2.25\n//\n// All functions that need access to the editor's state live inside\n// the CodeMirror function. Below that, at the bottom of the file,\n// some utilities are defined.\n\n// CodeMirror is the only global var we claim\nvar CodeMirror = (function() {\n  // This is the function that produces an editor instance. Its\n  // closure is used to store the editor state.\n  function CodeMirror(place, givenOptions) {\n    // Determine effective options based on given values and defaults.\n    var options = {}, defaults = CodeMirror.defaults;\n    for (var opt in defaults)\n      if (defaults.hasOwnProperty(opt))\n        options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];\n\n    // The element in which the editor lives.\n    var wrapper = document.createElement(\"div\");\n    wrapper.className = \"CodeMirror\" + (options.lineWrapping ? \" CodeMirror-wrap\" : \"\");\n    // This mess creates the base DOM structure for the editor.\n    wrapper.innerHTML =\n      '<div style=\"overflow: hidden; position: relative; width: 3px; height: 0px;\">' + // Wraps and hides input textarea\n        '<textarea style=\"position: absolute; padding: 0; width: 1px; height: 1em\" wrap=\"off\" ' +\n          'autocorrect=\"off\" autocapitalize=\"off\"></textarea></div>' +\n      '<div class=\"CodeMirror-scroll\" tabindex=\"-1\">' +\n        '<div style=\"position: relative\">' + // Set to the height of the text, causes scrolling\n          '<div style=\"position: relative\">' + // Moved around its parent to cover visible view\n            '<div class=\"CodeMirror-gutter\"><div class=\"CodeMirror-gutter-text\"></div></div>' +\n            // Provides positioning relative to (visible) text origin\n            '<div class=\"CodeMirror-lines\"><div style=\"position: relative; z-index: 0\">' +\n              '<div style=\"position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden;\"></div>' +\n              '<pre class=\"CodeMirror-cursor\">&#160;</pre>' + // Absolutely positioned blinky cursor\n              '<div style=\"position: relative; z-index: -1\"></div><div></div>' + // DIVs containing the selection and the actual code\n            '</div></div></div></div></div>';\n    if (place.appendChild) place.appendChild(wrapper); else place(wrapper);\n    // I've never seen more elegant code in my life.\n    var inputDiv = wrapper.firstChild, input = inputDiv.firstChild,\n        scroller = wrapper.lastChild, code = scroller.firstChild,\n        mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,\n        lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,\n        cursor = measure.nextSibling, selectionDiv = cursor.nextSibling,\n        lineDiv = selectionDiv.nextSibling;\n    themeChanged(); keyMapChanged();\n    // Needed to hide big blue blinking cursor on Mobile Safari\n    if (ios) input.style.width = \"0px\";\n    if (!webkit) lineSpace.draggable = true;\n    lineSpace.style.outline = \"none\";\n    if (options.tabindex != null) input.tabIndex = options.tabindex;\n    if (options.autofocus) focusInput();\n    if (!options.gutter && !options.lineNumbers) gutter.style.display = \"none\";\n    // Needed to handle Tab key in KHTML\n    if (khtml) inputDiv.style.height = \"1px\", inputDiv.style.position = \"absolute\";\n\n    // Check for problem with IE innerHTML not working when we have a\n    // P (or similar) parent node.\n    try { stringWidth(\"x\"); }\n    catch (e) {\n      if (e.message.match(/runtime/i))\n        e = new Error(\"A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)\");\n      throw e;\n    }\n\n    // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.\n    var poll = new Delayed(), highlight = new Delayed(), blinker;\n\n    // mode holds a mode API object. doc is the tree of Line objects,\n    // work an array of lines that should be parsed, and history the\n    // undo history (instance of History constructor).\n    var mode, doc = new BranchChunk([new LeafChunk([new Line(\"\")])]), work, focused;\n    loadMode();\n    // The selection. These are always maintained to point at valid\n    // positions. Inverted is used to remember that the user is\n    // selecting bottom-to-top.\n    var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};\n    // Selection-related flags. shiftSelecting obviously tracks\n    // whether the user is holding shift.\n    var shiftSelecting, lastClick, lastDoubleClick, lastScrollPos = 0, draggingText,\n        overwrite = false, suppressEdits = false;\n    // Variables used by startOperation/endOperation to track what\n    // happened during the operation.\n    var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,\n        gutterDirty, callbacks, maxLengthChanged;\n    // Current visible range (may be bigger than the view window).\n    var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;\n    // bracketHighlighted is used to remember that a bracket has been\n    // marked.\n    var bracketHighlighted;\n    // Tracks the maximum line length so that the horizontal scrollbar\n    // can be kept static when scrolling.\n    var maxLine = \"\", maxWidth;\n    var tabCache = {};\n\n    // Initialize the content.\n    operation(function(){setValue(options.value || \"\"); updateInput = false;})();\n    var history = new History();\n\n    // Register our event handlers.\n    connect(scroller, \"mousedown\", operation(onMouseDown));\n    connect(scroller, \"dblclick\", operation(onDoubleClick));\n    connect(lineSpace, \"selectstart\", e_preventDefault);\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 (!gecko) connect(scroller, \"contextmenu\", onContextMenu);\n    connect(scroller, \"scroll\", function() {\n      lastScrollPos = scroller.scrollTop;\n      updateDisplay([]);\n      if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + \"px\";\n      if (options.onScroll) options.onScroll(instance);\n    });\n    connect(window, \"resize\", function() {updateDisplay(true);});\n    connect(input, \"keyup\", operation(onKeyUp));\n    connect(input, \"input\", fastPoll);\n    connect(input, \"keydown\", operation(onKeyDown));\n    connect(input, \"keypress\", operation(onKeyPress));\n    connect(input, \"focus\", onFocus);\n    connect(input, \"blur\", onBlur);\n\n    if (options.dragDrop) {\n      connect(lineSpace, \"dragstart\", onDragStart);\n      function drag_(e) {\n        if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;\n        e_stop(e);\n      }\n      connect(scroller, \"dragenter\", drag_);\n      connect(scroller, \"dragover\", drag_);\n      connect(scroller, \"drop\", operation(onDrop));\n    }\n    connect(scroller, \"paste\", function(){focusInput(); fastPoll();});\n    connect(input, \"paste\", fastPoll);\n    connect(input, \"cut\", operation(function(){\n      if (!options.readOnly) replaceSelection(\"\");\n    }));\n\n    // Needed to handle Tab key in KHTML\n    if (khtml) connect(code, \"mouseup\", function() {\n        if (document.activeElement == input) input.blur();\n        focusInput();\n    });\n\n    // IE throws unspecified error in certain cases, when\n    // trying to access activeElement before onload\n    var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { }\n    if (hasFocus || options.autofocus) setTimeout(onFocus, 20);\n    else onBlur();\n\n    function isLine(l) {return l >= 0 && l < doc.size;}\n    // The instance object that we'll return. Mostly calls out to\n    // local functions in the CodeMirror function. Some do some extra\n    // range checking and/or clipping. operation is used to wrap the\n    // call so that changes it makes are tracked, and the display is\n    // updated afterwards.\n    var instance = wrapper.CodeMirror = {\n      getValue: getValue,\n      setValue: operation(setValue),\n      getSelection: getSelection,\n      replaceSelection: operation(replaceSelection),\n      focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},\n      setOption: function(option, value) {\n        var oldVal = options[option];\n        options[option] = value;\n        if (option == \"mode\" || option == \"indentUnit\") loadMode();\n        else if (option == \"readOnly\" && value == \"nocursor\") {onBlur(); input.blur();}\n        else if (option == \"readOnly\" && !value) {resetInput(true);}\n        else if (option == \"theme\") themeChanged();\n        else if (option == \"lineWrapping\" && oldVal != value) operation(wrappingChanged)();\n        else if (option == \"tabSize\") updateDisplay(true);\n        else if (option == \"keyMap\") keyMapChanged();\n        if (option == \"lineNumbers\" || option == \"gutter\" || option == \"firstLineNumber\" || option == \"theme\") {\n          gutterChanged();\n          updateDisplay(true);\n        }\n      },\n      getOption: function(option) {return options[option];},\n      undo: operation(undo),\n      redo: operation(redo),\n      indentLine: operation(function(n, dir) {\n        if (typeof dir != \"string\") {\n          if (dir == null) dir = options.smartIndent ? \"smart\" : \"prev\";\n          else dir = dir ? \"add\" : \"subtract\";\n        }\n        if (isLine(n)) indentLine(n, dir);\n      }),\n      indentSelection: operation(indentSelected),\n      historySize: function() {return {undo: history.done.length, redo: history.undone.length};},\n      clearHistory: function() {history = new History();},\n      matchBrackets: operation(function(){matchBrackets(true);}),\n      getTokenAt: operation(function(pos) {\n        pos = clipPos(pos);\n        return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch);\n      }),\n      getStateAfter: function(line) {\n        line = clipLine(line == null ? doc.size - 1: line);\n        return getStateBefore(line + 1);\n      },\n      cursorCoords: function(start, mode) {\n        if (start == null) start = sel.inverted;\n        return this.charCoords(start ? sel.from : sel.to, mode);\n      },\n      charCoords: function(pos, mode) {\n        pos = clipPos(pos);\n        if (mode == \"local\") return localCoords(pos, false);\n        if (mode == \"div\") return localCoords(pos, true);\n        return pageCoords(pos);\n      },\n      coordsChar: function(coords) {\n        var off = eltOffset(lineSpace);\n        return coordsChar(coords.x - off.left, coords.y - off.top);\n      },\n      markText: operation(markText),\n      setBookmark: setBookmark,\n      findMarksAt: findMarksAt,\n      setMarker: operation(addGutterMarker),\n      clearMarker: operation(removeGutterMarker),\n      setLineClass: operation(setLineClass),\n      hideLine: operation(function(h) {return setLineHidden(h, true);}),\n      showLine: operation(function(h) {return setLineHidden(h, false);}),\n      onDeleteLine: function(line, f) {\n        if (typeof line == \"number\") {\n          if (!isLine(line)) return null;\n          line = getLine(line);\n        }\n        (line.handlers || (line.handlers = [])).push(f);\n        return line;\n      },\n      lineInfo: lineInfo,\n      addWidget: function(pos, node, scroll, vert, horiz) {\n        pos = localCoords(clipPos(pos));\n        var top = pos.yBot, left = pos.x;\n        node.style.position = \"absolute\";\n        code.appendChild(node);\n        if (vert == \"over\") top = pos.y;\n        else if (vert == \"near\") {\n          var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),\n              hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();\n          if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)\n            top = pos.y - node.offsetHeight;\n          if (left + node.offsetWidth > hspace)\n            left = hspace - node.offsetWidth;\n        }\n        node.style.top = (top + paddingTop()) + \"px\";\n        node.style.left = node.style.right = \"\";\n        if (horiz == \"right\") {\n          left = code.clientWidth - node.offsetWidth;\n          node.style.right = \"0px\";\n        } else {\n          if (horiz == \"left\") left = 0;\n          else if (horiz == \"middle\") left = (code.clientWidth - node.offsetWidth) / 2;\n          node.style.left = (left + paddingLeft()) + \"px\";\n        }\n        if (scroll)\n          scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);\n      },\n\n      lineCount: function() {return doc.size;},\n      clipPos: clipPos,\n      getCursor: function(start) {\n        if (start == null) start = sel.inverted;\n        return copyPos(start ? sel.from : sel.to);\n      },\n      somethingSelected: function() {return !posEq(sel.from, sel.to);},\n      setCursor: operation(function(line, ch, user) {\n        if (ch == null && typeof line.line == \"number\") setCursor(line.line, line.ch, user);\n        else setCursor(line, ch, user);\n      }),\n      setSelection: operation(function(from, to, user) {\n        (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from));\n      }),\n      getLine: function(line) {if (isLine(line)) return getLine(line).text;},\n      getLineHandle: function(line) {if (isLine(line)) return getLine(line);},\n      setLine: operation(function(line, text) {\n        if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length});\n      }),\n      removeLine: operation(function(line) {\n        if (isLine(line)) replaceRange(\"\", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));\n      }),\n      replaceRange: operation(replaceRange),\n      getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},\n\n      triggerOnKeyDown: operation(onKeyDown),\n      execCommand: function(cmd) {return commands[cmd](instance);},\n      // Stuff used by commands, probably not much use to outside code.\n      moveH: operation(moveH),\n      deleteH: operation(deleteH),\n      moveV: operation(moveV),\n      toggleOverwrite: function() {\n        if(overwrite){\n          overwrite = false;\n          cursor.className = cursor.className.replace(\" CodeMirror-overwrite\", \"\");\n        } else {\n          overwrite = true;\n          cursor.className += \" CodeMirror-overwrite\";\n        }\n      },\n\n      posFromIndex: function(off) {\n        var lineNo = 0, ch;\n        doc.iter(0, doc.size, 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({line: lineNo, ch: ch});\n      },\n      indexFromPos: function (coords) {\n        if (coords.line < 0 || coords.ch < 0) return 0;\n        var index = coords.ch;\n        doc.iter(0, coords.line, function (line) {\n          index += line.text.length + 1;\n        });\n        return index;\n      },\n      scrollTo: function(x, y) {\n        if (x != null) scroller.scrollLeft = x;\n        if (y != null) scroller.scrollTop = y;\n        updateDisplay([]);\n      },\n\n      operation: function(f){return operation(f)();},\n      compoundChange: function(f){return compoundChange(f);},\n      refresh: function(){\n        updateDisplay(true);\n        if (scroller.scrollHeight > lastScrollPos)\n          scroller.scrollTop = lastScrollPos;\n      },\n      getInputField: function(){return input;},\n      getWrapperElement: function(){return wrapper;},\n      getScrollerElement: function(){return scroller;},\n      getGutterElement: function(){return gutter;}\n    };\n\n    function getLine(n) { return getLineAt(doc, n); }\n    function updateLineHeight(line, height) {\n      gutterDirty = true;\n      var diff = height - line.height;\n      for (var n = line; n; n = n.parent) n.height += diff;\n    }\n\n    function setValue(code) {\n      var top = {line: 0, ch: 0};\n      updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length},\n                  splitLines(code), top, top);\n      updateInput = true;\n    }\n    function getValue() {\n      var text = [];\n      doc.iter(0, doc.size, function(line) { text.push(line.text); });\n      return text.join(\"\\n\");\n    }\n\n    function onMouseDown(e) {\n      setShift(e_prop(e, \"shiftKey\"));\n      // Check whether this is a click in a widget\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == code && n != mover) return;\n\n      // See if this is a click in the gutter\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == gutterText) {\n          if (options.onGutterClick)\n            options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e);\n          return e_preventDefault(e);\n        }\n\n      var start = posFromMouse(e);\n\n      switch (e_button(e)) {\n      case 3:\n        if (gecko && !mac) onContextMenu(e);\n        return;\n      case 2:\n        if (start) setCursor(start.line, start.ch, true);\n        setTimeout(focusInput, 20);\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) == scroller) e_preventDefault(e); return;}\n\n      if (!focused) onFocus();\n\n      var now = +new Date;\n      if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {\n        e_preventDefault(e);\n        setTimeout(focusInput, 20);\n        return selectLine(start.line);\n      } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {\n        lastDoubleClick = {time: now, pos: start};\n        e_preventDefault(e);\n        return selectWordAt(start);\n      } else { lastClick = {time: now, pos: start}; }\n\n      var last = start, going;\n      if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&\n          !posLess(start, sel.from) && !posLess(sel.to, start)) {\n        // Let the drag handler handle this.\n        if (webkit) lineSpace.draggable = true;\n        function dragEnd(e2) {\n          if (webkit) lineSpace.draggable = false;\n          draggingText = false;\n          up(); drop();\n          if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {\n            e_preventDefault(e2);\n            setCursor(start.line, start.ch, true);\n            focusInput();\n          }\n        }\n        var up = connect(document, \"mouseup\", operation(dragEnd), true);\n        var drop = connect(scroller, \"drop\", operation(dragEnd), true);\n        draggingText = true;\n        // IE's approach to draggable\n        if (lineSpace.dragDrop) lineSpace.dragDrop();\n        return;\n      }\n      e_preventDefault(e);\n      setCursor(start.line, start.ch, true);\n\n      function extend(e) {\n        var cur = posFromMouse(e, true);\n        if (cur && !posEq(cur, last)) {\n          if (!focused) onFocus();\n          last = cur;\n          setSelectionUser(start, cur);\n          updateInput = false;\n          var visible = visibleLines();\n          if (cur.line >= visible.to || cur.line < visible.from)\n            going = setTimeout(operation(function(){extend(e);}), 150);\n        }\n      }\n\n      function done(e) {\n        clearTimeout(going);\n        var cur = posFromMouse(e);\n        if (cur) setSelectionUser(start, cur);\n        e_preventDefault(e);\n        focusInput();\n        updateInput = true;\n        move(); up();\n      }\n      var move = connect(document, \"mousemove\", operation(function(e) {\n        clearTimeout(going);\n        e_preventDefault(e);\n        if (!ie && !e_button(e)) done(e);\n        else extend(e);\n      }), true);\n      var up = connect(document, \"mouseup\", operation(done), true);\n    }\n    function onDoubleClick(e) {\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == gutterText) return e_preventDefault(e);\n      var start = posFromMouse(e);\n      if (!start) return;\n      lastDoubleClick = {time: +new Date, pos: start};\n      e_preventDefault(e);\n      selectWordAt(start);\n    }\n    function onDrop(e) {\n      if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;\n      e.preventDefault();\n      var pos = posFromMouse(e, true), files = e.dataTransfer.files;\n      if (!pos || options.readOnly) return;\n      if (files && files.length && window.FileReader && window.File) {\n        function loadFile(file, i) {\n          var reader = new FileReader;\n          reader.onload = function() {\n            text[i] = reader.result;\n            if (++read == n) {\n              pos = clipPos(pos);\n              operation(function() {\n                var end = replaceRange(text.join(\"\"), pos, pos);\n                setSelectionUser(pos, end);\n              })();\n            }\n          };\n          reader.readAsText(file);\n        }\n        var n = files.length, text = Array(n), read = 0;\n        for (var i = 0; i < n; ++i) loadFile(files[i], i);\n      }\n      else {\n        try {\n          var text = e.dataTransfer.getData(\"Text\");\n          if (text) {\n            compoundChange(function() {\n              var curFrom = sel.from, curTo = sel.to;\n              setSelectionUser(pos, pos);\n              if (draggingText) replaceRange(\"\", curFrom, curTo);\n              replaceSelection(text);\n              focusInput();\n            });\n          }\n        }\n        catch(e){}\n      }\n    }\n    function onDragStart(e) {\n      var txt = getSelection();\n      e.dataTransfer.setData(\"Text\", txt);\n      \n      // Use dummy image instead of default browsers image.\n      if (gecko || chrome) {\n        var img = document.createElement('img');\n        img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image\n        e.dataTransfer.setDragImage(img, 0, 0);\n      }\n    }\n\n    function doHandleBinding(bound, dropShift) {\n      if (typeof bound == \"string\") {\n        bound = commands[bound];\n        if (!bound) return false;\n      }\n      var prevShift = shiftSelecting;\n      try {\n        if (options.readOnly) suppressEdits = true;\n        if (dropShift) shiftSelecting = null;\n        bound(instance);\n      } catch(e) {\n        if (e != Pass) throw e;\n        return false;\n      } finally {\n        shiftSelecting = prevShift;\n        suppressEdits = false;\n      }\n      return true;\n    }\n    function handleKeyBinding(e) {\n      // Handle auto keymap transitions\n      var startMap = getKeyMap(options.keyMap), next = startMap.auto;\n      clearTimeout(maybeTransition);\n      if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {\n        if (getKeyMap(options.keyMap) == startMap) {\n          options.keyMap = (next.call ? next.call(null, instance) : next);\n        }\n      }, 50);\n\n      var name = keyNames[e_prop(e, \"keyCode\")], handled = false;\n      if (name == null || e.altGraphKey) return false;\n      if (e_prop(e, \"altKey\")) name = \"Alt-\" + name;\n      if (e_prop(e, \"ctrlKey\")) name = \"Ctrl-\" + name;\n      if (e_prop(e, \"metaKey\")) name = \"Cmd-\" + name;\n\n      var stopped = false;\n      function stop() { stopped = true; }\n\n      if (e_prop(e, \"shiftKey\")) {\n        handled = lookupKey(\"Shift-\" + name, options.extraKeys, options.keyMap,\n                            function(b) {return doHandleBinding(b, true);}, stop)\n               || lookupKey(name, options.extraKeys, options.keyMap, function(b) {\n                 if (typeof b == \"string\" && /^go[A-Z]/.test(b)) return doHandleBinding(b);\n               }, stop);\n      } else {\n        handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop);\n      }\n      if (stopped) handled = false;\n      if (handled) {\n        e_preventDefault(e);\n        restartBlink();\n        if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }\n      }\n      return handled;\n    }\n    function handleCharBinding(e, ch) {\n      var handled = lookupKey(\"'\" + ch + \"'\", options.extraKeys,\n                              options.keyMap, function(b) { return doHandleBinding(b, true); });\n      if (handled) {\n        e_preventDefault(e);\n        restartBlink();\n      }\n      return handled;\n    }\n\n    var lastStoppedKey = null, maybeTransition;\n    function onKeyDown(e) {\n      if (!focused) onFocus();\n      if (ie && e.keyCode == 27) { e.returnValue = false; }\n      if (pollingFast) { if (readInput()) pollingFast = false; }\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n      var code = e_prop(e, \"keyCode\");\n      // IE does strange things with escape.\n      setShift(code == 16 || e_prop(e, \"shiftKey\"));\n      // First give onKeyEvent option a chance to handle this.\n      var handled = handleKeyBinding(e);\n      if (window.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 && e_prop(e, mac ? \"metaKey\" : \"ctrlKey\"))\n          replaceSelection(\"\");\n      }\n    }\n    function onKeyPress(e) {\n      if (pollingFast) readInput();\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n      var keyCode = e_prop(e, \"keyCode\"), charCode = e_prop(e, \"charCode\");\n      if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}\n      if (((window.opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;\n      var ch = String.fromCharCode(charCode == null ? keyCode : charCode);\n      if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {\n        if (mode.electricChars.indexOf(ch) > -1)\n          setTimeout(operation(function() {indentLine(sel.to.line, \"smart\");}), 75);\n      }\n      if (handleCharBinding(e, ch)) return;\n      fastPoll();\n    }\n    function onKeyUp(e) {\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n      if (e_prop(e, \"keyCode\") == 16) shiftSelecting = null;\n    }\n\n    function onFocus() {\n      if (options.readOnly == \"nocursor\") return;\n      if (!focused) {\n        if (options.onFocus) options.onFocus(instance);\n        focused = true;\n        if (wrapper.className.search(/\\bCodeMirror-focused\\b/) == -1)\n          wrapper.className += \" CodeMirror-focused\";\n        if (!leaveInputAlone) resetInput(true);\n      }\n      slowPoll();\n      restartBlink();\n    }\n    function onBlur() {\n      if (focused) {\n        if (options.onBlur) options.onBlur(instance);\n        focused = false;\n        if (bracketHighlighted)\n          operation(function(){\n            if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }\n          })();\n        wrapper.className = wrapper.className.replace(\" CodeMirror-focused\", \"\");\n      }\n      clearInterval(blinker);\n      setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);\n    }\n\n    // Replace the range from from to to by the strings in newText.\n    // Afterwards, set the selection to selFrom, selTo.\n    function updateLines(from, to, newText, selFrom, selTo) {\n      if (suppressEdits) return;\n      if (history) {\n        var old = [];\n        doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); });\n        history.addChange(from.line, newText.length, old);\n        while (history.done.length > options.undoDepth) history.done.shift();\n      }\n      updateLinesNoUndo(from, to, newText, selFrom, selTo);\n    }\n    function unredoHelper(from, to) {\n      if (!from.length) return;\n      var set = from.pop(), out = [];\n      for (var i = set.length - 1; i >= 0; i -= 1) {\n        var change = set[i];\n        var replaced = [], end = change.start + change.added;\n        doc.iter(change.start, end, function(line) { replaced.push(line.text); });\n        out.push({start: change.start, added: change.old.length, old: replaced});\n        var pos = clipPos({line: change.start + change.old.length - 1,\n                           ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});\n        updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);\n      }\n      updateInput = true;\n      to.push(out);\n    }\n    function undo() {unredoHelper(history.done, history.undone);}\n    function redo() {unredoHelper(history.undone, history.done);}\n\n    function updateLinesNoUndo(from, to, newText, selFrom, selTo) {\n      if (suppressEdits) return;\n      var recomputeMaxLength = false, maxLineLength = maxLine.length;\n      if (!options.lineWrapping)\n        doc.iter(from.line, to.line + 1, function(line) {\n          if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}\n        });\n      if (from.line != to.line || newText.length > 1) gutterDirty = true;\n\n      var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line);\n      // First adjust the line structure, taking some care to leave highlighting intact.\n      if (from.ch == 0 && to.ch == 0 && newText[newText.length - 1] == \"\") {\n        // This is a whole-line replace. Treated specially to make\n        // sure line objects move the way they are supposed to.\n        var added = [], prevLine = null;\n        if (from.line) {\n          prevLine = getLine(from.line - 1);\n          prevLine.fixMarkEnds(lastLine);\n        } else lastLine.fixMarkStarts();\n        for (var i = 0, e = newText.length - 1; i < e; ++i)\n          added.push(Line.inheritMarks(newText[i], prevLine));\n        if (nlines) doc.remove(from.line, nlines, callbacks);\n        if (added.length) doc.insert(from.line, added);\n      } else if (firstLine == lastLine) {\n        if (newText.length == 1)\n          firstLine.replace(from.ch, to.ch, newText[0]);\n        else {\n          lastLine = firstLine.split(to.ch, newText[newText.length-1]);\n          firstLine.replace(from.ch, null, newText[0]);\n          firstLine.fixMarkEnds(lastLine);\n          var added = [];\n          for (var i = 1, e = newText.length - 1; i < e; ++i)\n            added.push(Line.inheritMarks(newText[i], firstLine));\n          added.push(lastLine);\n          doc.insert(from.line + 1, added);\n        }\n      } else if (newText.length == 1) {\n        firstLine.replace(from.ch, null, newText[0]);\n        lastLine.replace(null, to.ch, \"\");\n        firstLine.append(lastLine);\n        doc.remove(from.line + 1, nlines, callbacks);\n      } else {\n        var added = [];\n        firstLine.replace(from.ch, null, newText[0]);\n        lastLine.replace(null, to.ch, newText[newText.length-1]);\n        firstLine.fixMarkEnds(lastLine);\n        for (var i = 1, e = newText.length - 1; i < e; ++i)\n          added.push(Line.inheritMarks(newText[i], firstLine));\n        if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks);\n        doc.insert(from.line + 1, added);\n      }\n      if (options.lineWrapping) {\n        var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);\n        doc.iter(from.line, from.line + newText.length, function(line) {\n          if (line.hidden) return;\n          var guess = Math.ceil(line.text.length / perLine) || 1;\n          if (guess != line.height) updateLineHeight(line, guess);\n        });\n      } else {\n        doc.iter(from.line, from.line + newText.length, function(line) {\n          var l = line.text;\n          if (!line.hidden && l.length > maxLineLength) {\n            maxLine = l; maxLineLength = l.length; maxWidth = null;\n            recomputeMaxLength = false;\n          }\n        });\n        if (recomputeMaxLength) maxLengthChanged = true;\n      }\n\n      // Add these lines to the work array, so that they will be\n      // highlighted. Adjust work lines if lines were added/removed.\n      var newWork = [], lendiff = newText.length - nlines - 1;\n      for (var i = 0, l = work.length; i < l; ++i) {\n        var task = work[i];\n        if (task < from.line) newWork.push(task);\n        else if (task > to.line) newWork.push(task + lendiff);\n      }\n      var hlEnd = from.line + Math.min(newText.length, 500);\n      highlightLines(from.line, hlEnd);\n      newWork.push(hlEnd);\n      work = newWork;\n      startWorker(100);\n      // Remember that these lines changed, for updating the display\n      changes.push({from: from.line, to: to.line + 1, diff: lendiff});\n      var changeObj = {from: from, to: to, text: newText};\n      if (textChanged) {\n        for (var cur = textChanged; cur.next; cur = cur.next) {}\n        cur.next = changeObj;\n      } else textChanged = changeObj;\n\n      // Update the selection\n      function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}\n      setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line));\n\n      // Make sure the scroll-size div has the correct height.\n      if (scroller.clientHeight)\n        code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + \"px\";\n    }\n    \n    function computeMaxLength() {\n      var maxLineLength = 0; \n      maxLine = \"\"; maxWidth = null;\n      doc.iter(0, doc.size, function(line) {\n        var l = line.text;\n        if (!line.hidden && l.length > maxLineLength) {\n          maxLineLength = l.length; maxLine = l;\n        }\n      });\n      maxLengthChanged = false;\n    }\n\n    function replaceRange(code, from, to) {\n      from = clipPos(from);\n      if (!to) to = from; else to = clipPos(to);\n      code = splitLines(code);\n      function adjustPos(pos) {\n        if (posLess(pos, from)) return pos;\n        if (!posLess(to, pos)) return end;\n        var line = pos.line + code.length - (to.line - from.line) - 1;\n        var ch = pos.ch;\n        if (pos.line == to.line)\n          ch += code[code.length-1].length - (to.ch - (to.line == from.line ? from.ch : 0));\n        return {line: line, ch: ch};\n      }\n      var end;\n      replaceRange1(code, from, to, function(end1) {\n        end = end1;\n        return {from: adjustPos(sel.from), to: adjustPos(sel.to)};\n      });\n      return end;\n    }\n    function replaceSelection(code, collapse) {\n      replaceRange1(splitLines(code), sel.from, sel.to, function(end) {\n        if (collapse == \"end\") return {from: end, to: end};\n        else if (collapse == \"start\") return {from: sel.from, to: sel.from};\n        else return {from: sel.from, to: end};\n      });\n    }\n    function replaceRange1(code, from, to, computeSel) {\n      var endch = code.length == 1 ? code[0].length + from.ch : code[code.length-1].length;\n      var newSel = computeSel({line: from.line + code.length - 1, ch: endch});\n      updateLines(from, to, code, newSel.from, newSel.to);\n    }\n\n    function getRange(from, to) {\n      var l1 = from.line, l2 = to.line;\n      if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);\n      var code = [getLine(l1).text.slice(from.ch)];\n      doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });\n      code.push(getLine(l2).text.slice(0, to.ch));\n      return code.join(\"\\n\");\n    }\n    function getSelection() {\n      return getRange(sel.from, sel.to);\n    }\n\n    var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll\n    function slowPoll() {\n      if (pollingFast) return;\n      poll.set(options.pollInterval, function() {\n        startOperation();\n        readInput();\n        if (focused) slowPoll();\n        endOperation();\n      });\n    }\n    function fastPoll() {\n      var missed = false;\n      pollingFast = true;\n      function p() {\n        startOperation();\n        var changed = readInput();\n        if (!changed && !missed) {missed = true; poll.set(60, p);}\n        else {pollingFast = false; slowPoll();}\n        endOperation();\n      }\n      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    var prevInput = \"\";\n    function readInput() {\n      if (leaveInputAlone || !focused || hasSelection(input) || options.readOnly) return false;\n      var text = input.value;\n      if (text == prevInput) return false;\n      shiftSelecting = null;\n      var same = 0, l = Math.min(prevInput.length, text.length);\n      while (same < l && prevInput[same] == text[same]) ++same;\n      if (same < prevInput.length)\n        sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)};\n      else if (overwrite && posEq(sel.from, sel.to))\n        sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};\n      replaceSelection(text.slice(same), \"end\");\n      if (text.length > 1000) { input.value = prevInput = \"\"; }\n      else prevInput = text;\n      return true;\n    }\n    function resetInput(user) {\n      if (!posEq(sel.from, sel.to)) {\n        prevInput = \"\";\n        input.value = getSelection();\n        selectInput(input);\n      } else if (user) prevInput = input.value = \"\";\n    }\n\n    function focusInput() {\n      if (options.readOnly != \"nocursor\") input.focus();\n    }\n\n    function scrollEditorIntoView() {\n      if (!cursor.getBoundingClientRect) return;\n      var rect = cursor.getBoundingClientRect();\n      // IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden\n      if (ie && rect.top == rect.bottom) return;\n      var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);\n      if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView();\n    }\n    function scrollCursorIntoView() {\n      var cursor = localCoords(sel.inverted ? sel.from : sel.to);\n      var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;\n      return scrollIntoView(x, cursor.y, x, cursor.yBot);\n    }\n    function scrollIntoView(x1, y1, x2, y2) {\n      var pl = paddingLeft(), pt = paddingTop();\n      y1 += pt; y2 += pt; x1 += pl; x2 += pl;\n      var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true;\n      if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1); scrolled = true;}\n      else if (y2 > screentop + screen) {scroller.scrollTop = y2 - screen; scrolled = true;}\n\n      var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;\n      var gutterw = options.fixedGutter ? gutter.clientWidth : 0;\n      var atLeft = x1 < gutterw + pl + 10;\n      if (x1 < screenleft + gutterw || atLeft) {\n        if (atLeft) x1 = 0;\n        scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);\n        scrolled = true;\n      }\n      else if (x2 > screenw + screenleft - 3) {\n        scroller.scrollLeft = x2 + 10 - screenw;\n        scrolled = true;\n        if (x2 > code.clientWidth) result = false;\n      }\n      if (scrolled && options.onScroll) options.onScroll(instance);\n      return result;\n    }\n\n    function visibleLines() {\n      var lh = textHeight(), top = scroller.scrollTop - paddingTop();\n      var fromHeight = Math.max(0, Math.floor(top / lh));\n      var toHeight = Math.ceil((top + scroller.clientHeight) / lh);\n      return {from: lineAtHeight(doc, fromHeight),\n              to: lineAtHeight(doc, toHeight)};\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 updateDisplay(changes, suppressCallback) {\n      if (!scroller.clientWidth) {\n        showingFrom = showingTo = displayOffset = 0;\n        return;\n      }\n      // Compute the new visible window\n      var visible = visibleLines();\n      // Bail out if the visible area is already rendered and nothing changed.\n      if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) return;\n      var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);\n      if (showingFrom < from && from - showingFrom < 20) from = showingFrom;\n      if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);\n\n      // Create a range of theoretically intact lines, and punch holes\n      // in that using the change info.\n      var intact = changes === true ? [] :\n        computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes);\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.domStart += (from - range.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 (intactLines == to - from && from == showingFrom && to == showingTo) return;\n      intact.sort(function(a, b) {return a.domStart - b.domStart;});\n\n      var th = textHeight(), gutterDisplay = gutter.style.display;\n      lineDiv.style.display = \"none\";\n      patchDisplay(from, to, intact);\n      lineDiv.style.display = gutter.style.display = \"\";\n\n      // Position the mover div to align with the lines it's supposed\n      // to be showing (which will cover the visible display)\n      var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;\n      // This is just a bogus formula that detects when the editor is\n      // resized or the font size changes.\n      if (different) lastSizeC = scroller.clientHeight + th;\n      showingFrom = from; showingTo = to;\n      displayOffset = heightAtLine(doc, from);\n      mover.style.top = (displayOffset * th) + \"px\";\n      if (scroller.clientHeight)\n        code.style.height = (doc.height * th + 2 * paddingTop()) + \"px\";\n\n      // Since this is all rather error prone, it is honoured with the\n      // only assertion in the whole file.\n      if (lineDiv.childNodes.length != showingTo - showingFrom)\n        throw new Error(\"BAD PATCH! \" + JSON.stringify(intact) + \" size=\" + (showingTo - showingFrom) +\n                        \" nodes=\" + lineDiv.childNodes.length);\n\n      function checkHeights() {\n        maxWidth = scroller.clientWidth;\n        var curNode = lineDiv.firstChild, heightChanged = false;\n        doc.iter(showingFrom, showingTo, function(line) {\n          if (!line.hidden) {\n            var height = Math.round(curNode.offsetHeight / th) || 1;\n            if (line.height != height) {\n              updateLineHeight(line, height);\n              gutterDirty = heightChanged = true;\n            }\n          }\n          curNode = curNode.nextSibling;\n        });\n        if (heightChanged)\n          code.style.height = (doc.height * th + 2 * paddingTop()) + \"px\";\n        return heightChanged;\n      }\n\n      if (options.lineWrapping) {\n        checkHeights();\n      } else {\n        if (maxWidth == null) maxWidth = stringWidth(maxLine);\n        if (maxWidth > scroller.clientWidth) {\n          lineSpace.style.width = maxWidth + \"px\";\n          // Needed to prevent odd wrapping/hiding of widgets placed in here.\n          code.style.width = \"\";\n          code.style.width = scroller.scrollWidth + \"px\";\n        } else {\n          lineSpace.style.width = code.style.width = \"\";\n        }\n      }\n\n      gutter.style.display = gutterDisplay;\n      if (different || gutterDirty) {\n        // If the gutter grew in size, re-check heights. If those changed, re-draw gutter.\n        updateGutter() && options.lineWrapping && checkHeights() && updateGutter();\n      }\n      updateSelection();\n      if (!suppressCallback && options.onUpdate) options.onUpdate(instance);\n      return true;\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                          domStart: range.domStart});\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, domStart: range.domStart});\n            if (change.to < range.to)\n              intact2.push({from: change.to + diff, to: range.to + diff,\n                            domStart: range.domStart + (change.to - range.from)});\n          }\n        }\n        intact = intact2;\n      }\n      return intact;\n    }\n\n    function patchDisplay(from, to, intact) {\n      // The first pass removes the DOM nodes that aren't intact.\n      if (!intact.length) lineDiv.innerHTML = \"\";\n      else {\n        function killNode(node) {\n          var tmp = node.nextSibling;\n          node.parentNode.removeChild(node);\n          return tmp;\n        }\n        var domPos = 0, curNode = lineDiv.firstChild, n;\n        for (var i = 0; i < intact.length; ++i) {\n          var cur = intact[i];\n          while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;}\n          for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;}\n        }\n        while (curNode) curNode = killNode(curNode);\n      }\n      // This pass fills in the lines that actually changed.\n      var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;\n      var scratch = document.createElement(\"div\");\n      doc.iter(from, to, function(line) {\n        if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();\n        if (!nextIntact || nextIntact.from > j) {\n          if (line.hidden) var html = scratch.innerHTML = \"<pre></pre>\";\n          else {\n            var html = '<pre' + (line.className ? ' class=\"' + line.className + '\"' : '') + '>'\n              + line.getHTML(makeTab) + '</pre>';\n            // Kludge to make sure the styled element lies behind the selection (by z-index)\n            if (line.bgClassName)\n              html = '<div style=\"position: relative\"><pre class=\"' + line.bgClassName +\n              '\" style=\"position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2\">&#160;</pre>' + html + \"</div>\";\n          }\n          scratch.innerHTML = html;\n          lineDiv.insertBefore(scratch.firstChild, curNode);\n        } else {\n          curNode = curNode.nextSibling;\n        }\n        ++j;\n      });\n    }\n\n    function updateGutter() {\n      if (!options.gutter && !options.lineNumbers) return;\n      var hText = mover.offsetHeight, hEditor = scroller.clientHeight;\n      gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + \"px\";\n      var html = [], i = showingFrom, normalNode;\n      doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {\n        if (line.hidden) {\n          html.push(\"<pre></pre>\");\n        } else {\n          var marker = line.gutterMarker;\n          var text = options.lineNumbers ? i + options.firstLineNumber : null;\n          if (marker && marker.text)\n            text = marker.text.replace(\"%N%\", text != null ? text : \"\");\n          else if (text == null)\n            text = \"\\u00a0\";\n          html.push((marker && marker.style ? '<pre class=\"' + marker.style + '\">' : \"<pre>\"), text);\n          for (var j = 1; j < line.height; ++j) html.push(\"<br/>&#160;\");\n          html.push(\"</pre>\");\n          if (!marker) normalNode = i;\n        }\n        ++i;\n      });\n      gutter.style.display = \"none\";\n      gutterText.innerHTML = html.join(\"\");\n      // Make sure scrolling doesn't cause number gutter size to pop\n      if (normalNode != null) {\n        var node = gutterText.childNodes[normalNode - showingFrom];\n        var minwidth = String(doc.size).length, val = eltText(node), pad = \"\";\n        while (val.length + pad.length < minwidth) pad += \"\\u00a0\";\n        if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild);\n      }\n      gutter.style.display = \"\";\n      var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2;\n      lineSpace.style.marginLeft = gutter.offsetWidth + \"px\";\n      gutterDirty = false;\n      return resized;\n    }\n    function updateSelection() {\n      var collapsed = posEq(sel.from, sel.to);\n      var fromPos = localCoords(sel.from, true);\n      var toPos = collapsed ? fromPos : localCoords(sel.to, true);\n      var headPos = sel.inverted ? fromPos : toPos, th = textHeight();\n      var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv);\n      inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + \"px\";\n      inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + \"px\";\n      if (collapsed) {\n        cursor.style.top = headPos.y + \"px\";\n        cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + \"px\";\n        cursor.style.display = \"\";\n        selectionDiv.style.display = \"none\";\n      } else {\n        var sameLine = fromPos.y == toPos.y, html = \"\";\n        var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;\n        var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;\n        function add(left, top, right, height) {\n          var rstyle = quirksMode ? \"width: \" + (!right ? clientWidth : clientWidth - right - left) + \"px\"\n                                  : \"right: \" + right + \"px\";\n          html += '<div class=\"CodeMirror-selected\" style=\"position: absolute; left: ' + left +\n            'px; top: ' + top + 'px; ' + rstyle + '; height: ' + height + 'px\"></div>';\n        }\n        if (sel.from.ch && fromPos.y >= 0) {\n          var right = sameLine ? clientWidth - toPos.x : 0;\n          add(fromPos.x, fromPos.y, right, th);\n        }\n        var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));\n        var middleHeight = Math.min(toPos.y, clientHeight) - middleStart;\n        if (middleHeight > 0.2 * th)\n          add(0, middleStart, 0, middleHeight);\n        if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th)\n          add(0, toPos.y, clientWidth - toPos.x, th);\n        selectionDiv.innerHTML = html;\n        cursor.style.display = \"none\";\n        selectionDiv.style.display = \"\";\n      }\n    }\n\n    function setShift(val) {\n      if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);\n      else shiftSelecting = null;\n    }\n    function setSelectionUser(from, to) {\n      var sh = shiftSelecting && clipPos(shiftSelecting);\n      if (sh) {\n        if (posLess(sh, from)) from = sh;\n        else if (posLess(to, sh)) to = sh;\n      }\n      setSelection(from, to);\n      userSelChange = true;\n    }\n    // Update the selection. Last two args are only used by\n    // updateLines, since they have to be expressed in the line\n    // numbers before the update.\n    function setSelection(from, to, oldFrom, oldTo) {\n      goalColumn = null;\n      if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;}\n      if (posEq(sel.from, from) && posEq(sel.to, to)) return;\n      if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}\n\n      // Skip over hidden lines.\n      if (from.line != oldFrom) {\n        var from1 = skipHidden(from, oldFrom, sel.from.ch);\n        // If there is no non-hidden line left, force visibility on current line\n        if (!from1) setLineHidden(from.line, false);\n        else from = from1;\n      }\n      if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);\n\n      if (posEq(from, to)) sel.inverted = false;\n      else if (posEq(from, sel.to)) sel.inverted = false;\n      else if (posEq(to, sel.from)) sel.inverted = true;\n\n      if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) {\n        var head = sel.inverted ? from : to;\n        if (head.line != sel.from.line && sel.from.line < doc.size) {\n          var oldLine = getLine(sel.from.line);\n          if (/^\\s+$/.test(oldLine.text))\n            setTimeout(operation(function() {\n              if (oldLine.parent && /^\\s+$/.test(oldLine.text)) {\n                var no = lineNo(oldLine);\n                replaceRange(\"\", {line: no, ch: 0}, {line: no, ch: oldLine.text.length});\n              }\n            }, 10));\n        }\n      }\n\n      sel.from = from; sel.to = to;\n      selectionChanged = true;\n    }\n    function skipHidden(pos, oldLine, oldCh) {\n      function getNonHidden(dir) {\n        var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1;\n        while (lNo != end) {\n          var line = getLine(lNo);\n          if (!line.hidden) {\n            var ch = pos.ch;\n            if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length;\n            return {line: lNo, ch: ch};\n          }\n          lNo += dir;\n        }\n      }\n      var line = getLine(pos.line);\n      var toEnd = pos.ch == line.text.length && pos.ch != oldCh;\n      if (!line.hidden) return pos;\n      if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);\n      else return getNonHidden(-1) || getNonHidden(1);\n    }\n    function setCursor(line, ch, user) {\n      var pos = clipPos({line: line, ch: ch || 0});\n      (user ? setSelectionUser : setSelection)(pos, pos);\n    }\n\n    function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));}\n    function clipPos(pos) {\n      if (pos.line < 0) return {line: 0, ch: 0};\n      if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length};\n      var ch = pos.ch, linelen = getLine(pos.line).text.length;\n      if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};\n      else if (ch < 0) return {line: pos.line, ch: 0};\n      else return pos;\n    }\n\n    function findPosH(dir, unit) {\n      var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch;\n      var lineObj = getLine(line);\n      function findNextLine() {\n        for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) {\n          var lo = getLine(l);\n          if (!lo.hidden) { line = l; lineObj = lo; return true; }\n        }\n      }\n      function moveOnce(boundToLine) {\n        if (ch == (dir < 0 ? 0 : lineObj.text.length)) {\n          if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0;\n          else return false;\n        } else ch += dir;\n        return true;\n      }\n      if (unit == \"char\") moveOnce();\n      else if (unit == \"column\") moveOnce(true);\n      else if (unit == \"word\") {\n        var sawWord = false;\n        for (;;) {\n          if (dir < 0) if (!moveOnce()) break;\n          if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;\n          else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}\n          if (dir > 0) if (!moveOnce()) break;\n        }\n      }\n      return {line: line, ch: ch};\n    }\n    function moveH(dir, unit) {\n      var pos = dir < 0 ? sel.from : sel.to;\n      if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit);\n      setCursor(pos.line, pos.ch, true);\n    }\n    function deleteH(dir, unit) {\n      if (!posEq(sel.from, sel.to)) replaceRange(\"\", sel.from, sel.to);\n      else if (dir < 0) replaceRange(\"\", findPosH(dir, unit), sel.to);\n      else replaceRange(\"\", sel.from, findPosH(dir, unit));\n      userSelChange = true;\n    }\n    var goalColumn = null;\n    function moveV(dir, unit) {\n      var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true);\n      if (goalColumn != null) pos.x = goalColumn;\n      if (unit == \"page\") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);\n      else if (unit == \"line\") dist = textHeight();\n      var target = coordsChar(pos.x, pos.y + dist * dir + 2);\n      if (unit == \"page\") scroller.scrollTop += localCoords(target, true).y - pos.y;\n      setCursor(target.line, target.ch, true);\n      goalColumn = pos.x;\n    }\n\n    function selectWordAt(pos) {\n      var line = getLine(pos.line).text;\n      var start = pos.ch, end = pos.ch;\n      while (start > 0 && isWordChar(line.charAt(start - 1))) --start;\n      while (end < line.length && isWordChar(line.charAt(end))) ++end;\n      setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});\n    }\n    function selectLine(line) {\n      setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0}));\n    }\n    function indentSelected(mode) {\n      if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);\n      var e = sel.to.line - (sel.to.ch ? 0 : 1);\n      for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);\n    }\n\n    function indentLine(n, how) {\n      if (!how) how = \"add\";\n      if (how == \"smart\") {\n        if (!mode.indent) how = \"prev\";\n        else var state = getStateBefore(n);\n      }\n\n      var line = getLine(n), curSpace = line.indentation(options.tabSize),\n          curSpaceString = line.text.match(/^\\s*/)[0], indentation;\n      if (how == \"prev\") {\n        if (n) indentation = getLine(n-1).indentation(options.tabSize);\n        else indentation = 0;\n      }\n      else if (how == \"smart\") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);\n      else if (how == \"add\") indentation = curSpace + options.indentUnit;\n      else if (how == \"subtract\") indentation = curSpace - options.indentUnit;\n      indentation = Math.max(0, indentation);\n      var diff = indentation - curSpace;\n\n      if (!diff) {\n        if (sel.from.line != n && sel.to.line != n) return;\n        var indentString = curSpaceString;\n      }\n      else {\n        var indentString = \"\", pos = 0;\n        if (options.indentWithTabs)\n          for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += \"\\t\";}\n        while (pos < indentation) {++pos; indentString += \" \";}\n      }\n\n      replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});\n    }\n\n    function loadMode() {\n      mode = CodeMirror.getMode(options, options.mode);\n      doc.iter(0, doc.size, function(line) { line.stateAfter = null; });\n      work = [0];\n      startWorker();\n    }\n    function gutterChanged() {\n      var visible = options.gutter || options.lineNumbers;\n      gutter.style.display = visible ? \"\" : \"none\";\n      if (visible) gutterDirty = true;\n      else lineDiv.parentNode.style.marginLeft = 0;\n    }\n    function wrappingChanged(from, to) {\n      if (options.lineWrapping) {\n        wrapper.className += \" CodeMirror-wrap\";\n        var perLine = scroller.clientWidth / charWidth() - 3;\n        doc.iter(0, doc.size, function(line) {\n          if (line.hidden) return;\n          var guess = Math.ceil(line.text.length / perLine) || 1;\n          if (guess != 1) updateLineHeight(line, guess);\n        });\n        lineSpace.style.width = code.style.width = \"\";\n      } else {\n        wrapper.className = wrapper.className.replace(\" CodeMirror-wrap\", \"\");\n        maxWidth = null; maxLine = \"\";\n        doc.iter(0, doc.size, function(line) {\n          if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);\n          if (line.text.length > maxLine.length) maxLine = line.text;\n        });\n      }\n      changes.push({from: 0, to: doc.size});\n    }\n    function makeTab(col) {\n      var w = options.tabSize - col % options.tabSize, cached = tabCache[w];\n      if (cached) return cached;\n      for (var str = '<span class=\"cm-tab\">', i = 0; i < w; ++i) str += \" \";\n      return (tabCache[w] = {html: str + \"</span>\", width: w});\n    }\n    function themeChanged() {\n      scroller.className = scroller.className.replace(/\\s*cm-s-\\S+/g, \"\") +\n        options.theme.replace(/(^|\\s)\\s*/g, \" cm-s-\");\n    }\n    function keyMapChanged() {\n      var style = keyMap[options.keyMap].style;\n      wrapper.className = wrapper.className.replace(/\\s*cm-keymap-\\S+/g, \"\") +\n        (style ? \" cm-keymap-\" + style : \"\");\n    }\n\n    function TextMarker() { this.set = []; }\n    TextMarker.prototype.clear = operation(function() {\n      var min = Infinity, max = -Infinity;\n      for (var i = 0, e = this.set.length; i < e; ++i) {\n        var line = this.set[i], mk = line.marked;\n        if (!mk || !line.parent) continue;\n        var lineN = lineNo(line);\n        min = Math.min(min, lineN); max = Math.max(max, lineN);\n        for (var j = 0; j < mk.length; ++j)\n          if (mk[j].marker == this) mk.splice(j--, 1);\n      }\n      if (min != Infinity)\n        changes.push({from: min, to: max + 1});\n    });\n    TextMarker.prototype.find = function() {\n      var from, to;\n      for (var i = 0, e = this.set.length; i < e; ++i) {\n        var line = this.set[i], mk = line.marked;\n        for (var j = 0; j < mk.length; ++j) {\n          var mark = mk[j];\n          if (mark.marker == this) {\n            if (mark.from != null || mark.to != null) {\n              var found = lineNo(line);\n              if (found != null) {\n                if (mark.from != null) from = {line: found, ch: mark.from};\n                if (mark.to != null) to = {line: found, ch: mark.to};\n              }\n            }\n          }\n        }\n      }\n      return {from: from, to: to};\n    };\n\n    function markText(from, to, className) {\n      from = clipPos(from); to = clipPos(to);\n      var tm = new TextMarker();\n      if (!posLess(from, to)) return tm;\n      function add(line, from, to, className) {\n        getLine(line).addMark(new MarkedText(from, to, className, tm));\n      }\n      if (from.line == to.line) add(from.line, from.ch, to.ch, className);\n      else {\n        add(from.line, from.ch, null, className);\n        for (var i = from.line + 1, e = to.line; i < e; ++i)\n          add(i, null, null, className);\n        add(to.line, null, to.ch, className);\n      }\n      changes.push({from: from.line, to: to.line + 1});\n      return tm;\n    }\n\n    function setBookmark(pos) {\n      pos = clipPos(pos);\n      var bm = new Bookmark(pos.ch);\n      getLine(pos.line).addMark(bm);\n      return bm;\n    }\n\n    function findMarksAt(pos) {\n      pos = clipPos(pos);\n      var markers = [], marked = getLine(pos.line).marked;\n      if (!marked) return markers;\n      for (var i = 0, e = marked.length; i < e; ++i) {\n        var m = marked[i];\n        if ((m.from == null || m.from <= pos.ch) &&\n            (m.to == null || m.to >= pos.ch))\n          markers.push(m.marker || m);\n      }\n      return markers;\n    }\n\n    function addGutterMarker(line, text, className) {\n      if (typeof line == \"number\") line = getLine(clipLine(line));\n      line.gutterMarker = {text: text, style: className};\n      gutterDirty = true;\n      return line;\n    }\n    function removeGutterMarker(line) {\n      if (typeof line == \"number\") line = getLine(clipLine(line));\n      line.gutterMarker = null;\n      gutterDirty = true;\n    }\n\n    function changeLine(handle, op) {\n      var no = handle, line = handle;\n      if (typeof handle == \"number\") line = getLine(clipLine(handle));\n      else no = lineNo(handle);\n      if (no == null) return null;\n      if (op(line, no)) changes.push({from: no, to: no + 1});\n      else return null;\n      return line;\n    }\n    function setLineClass(handle, className, bgClassName) {\n      return changeLine(handle, function(line) {\n        if (line.className != className || line.bgClassName != bgClassName) {\n          line.className = className;\n          line.bgClassName = bgClassName;\n          return true;\n        }\n      });\n    }\n    function setLineHidden(handle, hidden) {\n      return changeLine(handle, function(line, no) {\n        if (line.hidden != hidden) {\n          line.hidden = hidden;\n          if (!options.lineWrapping) {\n            var l = line.text;\n            if (hidden && l.length == maxLine.length) {\n              maxLengthChanged = true;\n            }\n            else if (!hidden && l.length > maxLine.length) {\n              maxLine = l; maxWidth = null;\n              maxLengthChanged = false;\n            }\n          }\n          updateLineHeight(line, hidden ? 0 : 1);\n          var fline = sel.from.line, tline = sel.to.line;\n          if (hidden && (fline == no || tline == no)) {\n            var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;\n            var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;\n            // Can't hide the last visible line, we'd have no place to put the cursor\n            if (!to) return;\n            setSelection(from, to);\n          }\n          return (gutterDirty = true);\n        }\n      });\n    }\n\n    function lineInfo(line) {\n      if (typeof line == \"number\") {\n        if (!isLine(line)) return null;\n        var n = line;\n        line = getLine(line);\n        if (!line) return null;\n      }\n      else {\n        var n = lineNo(line);\n        if (n == null) return null;\n      }\n      var marker = line.gutterMarker;\n      return {line: n, handle: line, text: line.text, markerText: marker && marker.text,\n              markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};\n    }\n\n    function stringWidth(str) {\n      measure.innerHTML = \"<pre><span>x</span></pre>\";\n      measure.firstChild.firstChild.firstChild.nodeValue = str;\n      return measure.firstChild.firstChild.offsetWidth || 10;\n    }\n    // These are used to go from pixel positions to character\n    // positions, taking varying character widths into account.\n    function charFromX(line, x) {\n      if (x <= 0) return 0;\n      var lineObj = getLine(line), text = lineObj.text;\n      function getX(len) {\n        return measureLine(lineObj, len).left;\n      }\n      var from = 0, fromX = 0, to = text.length, toX;\n      // Guess a suitable upper bound for our search.\n      var estimated = Math.min(to, Math.ceil(x / charWidth()));\n      for (;;) {\n        var estX = getX(estimated);\n        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));\n        else {toX = estX; to = estimated; break;}\n      }\n      if (x > toX) return to;\n      // Try to guess a suitable lower bound as well.\n      estimated = Math.floor(to * 0.8); estX = getX(estimated);\n      if (estX < x) {from = estimated; fromX = estX;}\n      // Do a binary search between these bounds.\n      for (;;) {\n        if (to - from <= 1) return (toX - x > x - fromX) ? from : to;\n        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);\n        if (middleX > x) {to = middle; toX = middleX;}\n        else {from = middle; fromX = middleX;}\n      }\n    }\n\n    var tempId = \"CodeMirror-temp-\" + Math.floor(Math.random() * 0xffffff).toString(16);\n    function measureLine(line, ch) {\n      if (ch == 0) return {top: 0, left: 0};\n      var wbr = options.lineWrapping && ch < line.text.length &&\n                spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));\n      measure.innerHTML = \"<pre>\" + line.getHTML(makeTab, ch, tempId, wbr) + \"</pre>\";\n      var elt = document.getElementById(tempId);\n      if (!elt) {\n        // Temporary workaround for:\n        // https://github.com/mozilla/webpagemaker/issues/394\n        if (window.console) {\n          if (window.console.warn)\n            window.console.warn(\"elt is null for ch \" + ch + \" of line \" +\n                                JSON.stringify(line.text));\n          if (window.console.trace)\n            window.console.trace();\n        }\n        return {top: 0, left: 0};\n      }\n      var top = elt.offsetTop, left = elt.offsetLeft;\n      // Older IEs report zero offsets for spans directly after a wrap\n      if (ie && top == 0 && left == 0) {\n        var backup = document.createElement(\"span\");\n        backup.innerHTML = \"x\";\n        elt.parentNode.insertBefore(backup, elt.nextSibling);\n        top = backup.offsetTop;\n      }\n      return {top: top, left: left};\n    }\n    function localCoords(pos, inLineWrap) {\n      var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0));\n      if (pos.ch == 0) x = 0;\n      else {\n        var sp = measureLine(getLine(pos.line), pos.ch);\n        x = sp.left;\n        if (options.lineWrapping) y += Math.max(0, sp.top);\n      }\n      return {x: x, y: y, yBot: y + lh};\n    }\n    // Coords must be lineSpace-local\n    function coordsChar(x, y) {\n      if (y < 0) y = 0;\n      var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th);\n      var lineNo = lineAtHeight(doc, heightPos);\n      if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length};\n      var lineObj = getLine(lineNo), text = lineObj.text;\n      var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0;\n      if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0};\n      function getX(len) {\n        var sp = measureLine(lineObj, len);\n        if (tw) {\n          var off = Math.round(sp.top / th);\n          return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth);\n        }\n        return sp.left;\n      }\n      var from = 0, fromX = 0, to = text.length, toX;\n      // Guess a suitable upper bound for our search.\n      var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw));\n      for (;;) {\n        var estX = getX(estimated);\n        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));\n        else {toX = estX; to = estimated; break;}\n      }\n      if (x > toX) return {line: lineNo, ch: to};\n      // Try to guess a suitable lower bound as well.\n      estimated = Math.floor(to * 0.8); estX = getX(estimated);\n      if (estX < x) {from = estimated; fromX = estX;}\n      // Do a binary search between these bounds.\n      for (;;) {\n        if (to - from <= 1) return {line: lineNo, ch: (toX - x > x - fromX) ? from : to};\n        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);\n        if (middleX > x) {to = middle; toX = middleX;}\n        else {from = middle; fromX = middleX;}\n      }\n    }\n    function pageCoords(pos) {\n      var local = localCoords(pos, true), off = eltOffset(lineSpace);\n      return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};\n    }\n\n    var cachedHeight, cachedHeightFor, measureText;\n    function textHeight() {\n      if (measureText == null) {\n        measureText = \"<pre>\";\n        for (var i = 0; i < 49; ++i) measureText += \"x<br/>\";\n        measureText += \"x</pre>\";\n      }\n      var offsetHeight = lineDiv.clientHeight;\n      if (offsetHeight == cachedHeightFor) return cachedHeight;\n      cachedHeightFor = offsetHeight;\n      measure.innerHTML = measureText;\n      cachedHeight = measure.firstChild.offsetHeight / 50 || 1;\n      measure.innerHTML = \"\";\n      return cachedHeight;\n    }\n    var cachedWidth, cachedWidthFor = 0;\n    function charWidth() {\n      if (scroller.clientWidth == cachedWidthFor) return cachedWidth;\n      cachedWidthFor = scroller.clientWidth;\n      return (cachedWidth = stringWidth(\"x\"));\n    }\n    function paddingTop() {return lineSpace.offsetTop;}\n    function paddingLeft() {return lineSpace.offsetLeft;}\n\n    function posFromMouse(e, liberal) {\n      var offW = eltOffset(scroller, true), x, y;\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      // This is a mess of a heuristic to try and determine whether a\n      // scroll-bar was clicked or not, and to return null if one was\n      // (and !liberal).\n      if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight))\n        return null;\n      var offL = eltOffset(lineSpace, true);\n      return coordsChar(x - offL.left, y - offL.top);\n    }\n    function onContextMenu(e) {\n      var pos = posFromMouse(e), scrollPos = scroller.scrollTop;\n      if (!pos || window.opera) return; // Opera is difficult.\n      if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))\n        operation(setCursor)(pos.line, pos.ch);\n\n      var oldCSS = input.style.cssText;\n      inputDiv.style.position = \"absolute\";\n      input.style.cssText = \"position: fixed; width: 30px; height: 30px; top: \" + (e.clientY - 5) +\n        \"px; left: \" + (e.clientX - 5) + \"px; z-index: 1000; background: white; \" +\n        \"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);\";\n      leaveInputAlone = true;\n      var val = input.value = getSelection();\n      focusInput();\n      selectInput(input);\n      function rehide() {\n        var newVal = splitLines(input.value).join(\"\\n\");\n        if (newVal != val) operation(replaceSelection)(newVal, \"end\");\n        inputDiv.style.position = \"relative\";\n        input.style.cssText = oldCSS;\n        if (ie_lt9) scroller.scrollTop = scrollPos;\n        leaveInputAlone = false;\n        resetInput(true);\n        slowPoll();\n      }\n\n      if (gecko) {\n        e_stop(e);\n        var mouseup = connect(window, \"mouseup\", function() {\n          mouseup();\n          setTimeout(rehide, 20);\n        }, true);\n      } else {\n        setTimeout(rehide, 50);\n      }\n    }\n\n    // Cursor-blinking\n    function restartBlink() {\n      clearInterval(blinker);\n      var on = true;\n      cursor.style.visibility = \"\";\n      blinker = setInterval(function() {\n        cursor.style.visibility = (on = !on) ? \"\" : \"hidden\";\n      }, 650);\n    }\n\n    var matching = {\"(\": \")>\", \")\": \"(<\", \"[\": \"]>\", \"]\": \"[<\", \"{\": \"}>\", \"}\": \"{<\"};\n    function matchBrackets(autoclear) {\n      var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1;\n      var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];\n      if (!match) return;\n      var ch = match.charAt(0), forward = match.charAt(1) == \">\", d = forward ? 1 : -1, st = line.styles;\n      for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2)\n        if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;}\n\n      var stack = [line.text.charAt(pos)], re = /[(){}[\\]]/;\n      function scan(line, from, to) {\n        if (!line.text) return;\n        var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;\n        for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {\n          var text = st[i];\n          if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;}\n          for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {\n            if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {\n              var match = matching[cur];\n              if (match.charAt(1) == \">\" == forward) stack.push(cur);\n              else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};\n              else if (!stack.length) return {pos: pos, match: true};\n            }\n          }\n        }\n      }\n      for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) {\n        var line = getLine(i), first = i == head.line;\n        var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);\n        if (found) break;\n      }\n      if (!found) found = {pos: null, match: false};\n      var style = found.match ? \"CodeMirror-matchingbracket\" : \"CodeMirror-nonmatchingbracket\";\n      var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),\n          two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);\n      var clear = operation(function(){one.clear(); two && two.clear();});\n      if (autoclear) setTimeout(clear, 800);\n      else bracketHighlighted = clear;\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(n) {\n      var minindent, minline;\n      for (var search = n, lim = n - 40; search > lim; --search) {\n        if (search == 0) return 0;\n        var line = getLine(search-1);\n        if (line.stateAfter) return search;\n        var indented = line.indentation(options.tabSize);\n        if (minline == null || minindent > indented) {\n          minline = search - 1;\n          minindent = indented;\n        }\n      }\n      return minline;\n    }\n    function getStateBefore(n) {\n      var start = findStartLine(n), state = start && getLine(start-1).stateAfter;\n      if (!state) state = startState(mode);\n      else state = copyState(mode, state);\n      doc.iter(start, n, function(line) {\n        line.highlight(mode, state, options.tabSize);\n        line.stateAfter = copyState(mode, state);\n      });\n      if (start < n) changes.push({from: start, to: n});\n      if (n < doc.size && !getLine(n).stateAfter) work.push(n);\n      return state;\n    }\n    function highlightLines(start, end) {\n      var state = getStateBefore(start);\n      doc.iter(start, end, function(line) {\n        line.highlight(mode, state, options.tabSize);\n        line.stateAfter = copyState(mode, state);\n      });\n    }\n    function highlightWorker() {\n      var end = +new Date + options.workTime;\n      var foundWork = work.length;\n      while (work.length) {\n        if (!getLine(showingFrom).stateAfter) var task = showingFrom;\n        else var task = work.pop();\n        if (task >= doc.size) continue;\n        var start = findStartLine(task), state = start && getLine(start-1).stateAfter;\n        if (state) state = copyState(mode, state);\n        else state = startState(mode);\n\n        var unchanged = 0, compare = mode.compareStates, realChange = false,\n            i = start, bail = false;\n        doc.iter(i, doc.size, function(line) {\n          var hadState = line.stateAfter;\n          if (+new Date > end) {\n            work.push(i);\n            startWorker(options.workDelay);\n            if (realChange) changes.push({from: task, to: i + 1});\n            return (bail = true);\n          }\n          var changed = line.highlight(mode, state, options.tabSize);\n          if (changed) realChange = true;\n          line.stateAfter = copyState(mode, state);\n          var done = null;\n          if (compare) {\n            var same = hadState && compare(hadState, state);\n            if (same != Pass) done = !!same;\n          }\n          if (done == null) {\n            if (changed !== false || !hadState) unchanged = 0;\n            else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, \"\") == mode.indent(state, \"\")))\n              done = true;\n          }\n          if (done) return true;\n          ++i;\n        });\n        if (bail) return;\n        if (realChange) changes.push({from: task, to: i + 1});\n      }\n      if (foundWork && options.onHighlightComplete)\n        options.onHighlightComplete(instance);\n    }\n    function startWorker(time) {\n      if (!work.length) return;\n      highlight.set(time, operation(highlightWorker));\n    }\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    function startOperation() {\n      updateInput = userSelChange = textChanged = null;\n      changes = []; selectionChanged = false; callbacks = [];\n    }\n    function endOperation() {\n      var reScroll = false, updated;\n      if (maxLengthChanged) computeMaxLength();\n      if (selectionChanged) reScroll = !scrollCursorIntoView();\n      if (changes.length) updated = updateDisplay(changes, true);\n      else {\n        if (selectionChanged) updateSelection();\n        if (gutterDirty) updateGutter();\n      }\n      if (reScroll) scrollCursorIntoView();\n      if (selectionChanged) {scrollEditorIntoView(); restartBlink();}\n\n      if (focused && !leaveInputAlone &&\n          (updateInput === true || (updateInput !== false && selectionChanged)))\n        resetInput(userSelChange);\n\n      if (selectionChanged && options.matchBrackets)\n        setTimeout(operation(function() {\n          if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}\n          if (posEq(sel.from, sel.to)) matchBrackets(false);\n        }), 20);\n      var tc = textChanged, cbs = callbacks; // these can be reset by callbacks\n      if (selectionChanged && options.onCursorActivity)\n        options.onCursorActivity(instance);\n      if (tc && options.onChange && instance)\n        options.onChange(instance, tc);\n      for (var i = 0; i < cbs.length; ++i) cbs[i](instance);\n      if (updated && options.onUpdate) options.onUpdate(instance);\n    }\n    var nestedOperation = 0;\n    function operation(f) {\n      return function() {\n        if (!nestedOperation++) startOperation();\n        try {var result = f.apply(this, arguments);}\n        finally {if (!--nestedOperation) endOperation();}\n        return result;\n      };\n    }\n\n    function compoundChange(f) {\n      history.startCompound();\n      try { return f(); } finally { history.endCompound(); }\n    }\n\n    for (var ext in extensions)\n      if (extensions.propertyIsEnumerable(ext) &&\n          !instance.propertyIsEnumerable(ext))\n        instance[ext] = extensions[ext];\n    return instance;\n  } // (end of function CodeMirror)\n\n  // The default configuration options.\n  CodeMirror.defaults = {\n    value: \"\",\n    mode: null,\n    theme: \"default\",\n    indentUnit: 2,\n    indentWithTabs: false,\n    smartIndent: true,\n    tabSize: 4,\n    keyMap: \"default\",\n    extraKeys: null,\n    electricChars: true,\n    autoClearEmptyLines: false,\n    onKeyEvent: null,\n    onDragEvent: null,\n    lineWrapping: false,\n    lineNumbers: false,\n    gutter: false,\n    fixedGutter: false,\n    firstLineNumber: 1,\n    readOnly: false,\n    dragDrop: true,\n    onChange: null,\n    onCursorActivity: null,\n    onGutterClick: null,\n    onHighlightComplete: null,\n    onUpdate: null,\n    onFocus: null, onBlur: null, onScroll: null,\n    matchBrackets: false,\n    workTime: 100,\n    workDelay: 200,\n    pollInterval: 100,\n    undoDepth: 40,\n    tabindex: null,\n    autofocus: null\n  };\n\n  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\\/\\w+/.test(navigator.userAgent);\n  var mac = ios || /Mac/.test(navigator.platform);\n  var win = /Win/.test(navigator.platform);\n\n  // Known modes, by name and by MIME\n  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};\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  CodeMirror.defineMIME = function(mime, spec) {\n    mimeModes[mime] = spec;\n  };\n  CodeMirror.resolveMode = function(spec) {\n    if (typeof spec == \"string\" && mimeModes.hasOwnProperty(spec))\n      spec = mimeModes[spec];\n    else if (typeof spec == \"string\" && /^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(spec))\n      return CodeMirror.resolveMode(\"application/xml\");\n    if (typeof spec == \"string\") return {name: spec};\n    else return spec || {name: \"null\"};\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    return mfactory(options, spec);\n  };\n  CodeMirror.listModes = function() {\n    var list = [];\n    for (var m in modes)\n      if (modes.propertyIsEnumerable(m)) list.push(m);\n    return list;\n  };\n  CodeMirror.listMIMEs = function() {\n    var list = [];\n    for (var m in mimeModes)\n      if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]});\n    return list;\n  };\n\n  var extensions = CodeMirror.extensions = {};\n  CodeMirror.defineExtension = function(name, func) {\n    extensions[name] = func;\n  };\n\n  var commands = CodeMirror.commands = {\n    selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},\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) cm.replaceRange(\"\", from, {line: from.line + 1, ch: 0});\n      else cm.replaceRange(\"\", from, sel ? to : {line: from.line});\n    },\n    deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange(\"\", {line: l, ch: 0}, {line: l});},\n    undo: function(cm) {cm.undo();},\n    redo: function(cm) {cm.redo();},\n    goDocStart: function(cm) {cm.setCursor(0, 0, true);},\n    goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);},\n    goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);},\n    goLineStartSmart: function(cm) {\n      var cur = cm.getCursor();\n      var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\\S/));\n      cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true);\n    },\n    goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);},\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    goWordRight: function(cm) {cm.moveH(1, \"word\");},\n    delCharLeft: function(cm) {cm.deleteH(-1, \"char\");},\n    delCharRight: function(cm) {cm.deleteH(1, \"char\");},\n    delWordLeft: function(cm) {cm.deleteH(-1, \"word\");},\n    delWordRight: function(cm) {cm.deleteH(1, \"word\");},\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) {cm.replaceSelection(\"\\t\", \"end\");},\n    defaultTab: function(cm) {\n      if (cm.somethingSelected()) cm.indentSelection(\"add\");\n      else cm.replaceSelection(\"\\t\", \"end\");\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                        {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1});\n    },\n    newlineAndIndent: function(cm) {\n      cm.replaceSelection(\"\\n\", \"end\");\n      cm.indentLine(cm.getCursor().line);\n    },\n    toggleOverwrite: function(cm) {cm.toggleOverwrite();}\n  };\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\": \"delCharRight\", \"Backspace\": \"delCharLeft\", \"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\", \"Alt-Up\": \"goDocStart\", \"Ctrl-End\": \"goDocEnd\", \"Ctrl-Down\": \"goDocEnd\",\n    \"Ctrl-Left\": \"goWordLeft\", \"Ctrl-Right\": \"goWordRight\", \"Alt-Left\": \"goLineStart\", \"Alt-Right\": \"goLineEnd\",\n    \"Ctrl-Backspace\": \"delWordLeft\", \"Ctrl-Delete\": \"delWordRight\", \"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\": \"goWordLeft\",\n    \"Alt-Right\": \"goWordRight\", \"Cmd-Left\": \"goLineStart\", \"Cmd-Right\": \"goLineEnd\", \"Alt-Backspace\": \"delWordLeft\",\n    \"Ctrl-Alt-Backspace\": \"delWordRight\", \"Alt-Delete\": \"delWordRight\", \"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\",\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\": \"goPageUp\", \"Shift-Ctrl-V\": \"goPageDown\", \"Ctrl-D\": \"delCharRight\", \"Ctrl-H\": \"delCharLeft\",\n    \"Alt-D\": \"delWordRight\", \"Alt-Backspace\": \"delWordLeft\", \"Ctrl-K\": \"killLine\", \"Ctrl-T\": \"transposeChars\"\n  };\n\n  function getKeyMap(val) {\n    if (typeof val == \"string\") return keyMap[val];\n    else return val;\n  }\n  function lookupKey(name, extraMap, map, handle, stop) {\n    function lookup(map) {\n      map = getKeyMap(map);\n      var found = map[name];\n      if (found != null && handle(found)) return true;\n      if (map.nofallthrough) {\n        if (stop) stop();\n        return true;\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        if (lookup(fallthrough[i])) return true;\n      }\n      return false;\n    }\n    if (extraMap && lookup(extraMap)) return true;\n    return lookup(map);\n  }\n  function isModifierKey(event) {\n    var name = keyNames[e_prop(event, \"keyCode\")];\n    return name == \"Ctrl\" || name == \"Alt\" || name == \"Shift\" || name == \"Mod\";\n  }\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.autofocus == null && textarea.getAttribute(\"autofocus\") != null)\n      options.autofocus = true;\n\n    function save() {textarea.value = instance.getValue();}\n    if (textarea.form) {\n      // Deplorable hack to make the submit method do the right thing.\n      var rmSubmit = connect(textarea.form, \"submit\", save, true);\n      if (typeof textarea.form.submit == \"function\") {\n        var realSubmit = textarea.form.submit;\n        function wrappedSubmit() {\n          save();\n          textarea.form.submit = realSubmit;\n          textarea.form.submit();\n          textarea.form.submit = wrappedSubmit;\n        }\n        textarea.form.submit = wrappedSubmit;\n      }\n    }\n\n    textarea.style.display = \"none\";\n    var instance = CodeMirror(function(node) {\n      textarea.parentNode.insertBefore(node, textarea.nextSibling);\n    }, options);\n    instance.save = save;\n    instance.getTextArea = function() { return textarea; };\n    instance.toTextArea = function() {\n      save();\n      textarea.parentNode.removeChild(instance.getWrapperElement());\n      textarea.style.display = \"\";\n      if (textarea.form) {\n        rmSubmit();\n        if (typeof textarea.form.submit == \"function\")\n          textarea.form.submit = realSubmit;\n      }\n    };\n    return instance;\n  };\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  function startState(mode, a1, a2) {\n    return mode.startState ? mode.startState(a1, a2) : true;\n  }\n  CodeMirror.startState = startState;\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  }\n  StringStream.prototype = {\n    eol: function() {return this.pos >= this.string.length;},\n    sol: function() {return this.pos == 0;},\n    peek: function() {return this.string.charAt(this.pos);},\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() {return countColumn(this.string, this.start, this.tabSize);},\n    indentation: function() {return countColumn(this.string, null, this.tabSize);},\n    match: function(pattern, consume, caseInsensitive) {\n      if (typeof pattern == \"string\") {\n        function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}\n        if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {\n          if (consume !== false) this.pos += pattern.length;\n          return true;\n        }\n      }\n      else {\n        var match = this.string.slice(this.pos).match(pattern);\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  };\n  CodeMirror.StringStream = StringStream;\n\n  function MarkedText(from, to, className, marker) {\n    this.from = from; this.to = to; this.style = className; this.marker = marker;\n  }\n  MarkedText.prototype = {\n    attach: function(line) { this.marker.set.push(line); },\n    detach: function(line) {\n      var ix = indexOf(this.marker.set, line);\n      if (ix > -1) this.marker.set.splice(ix, 1);\n    },\n    split: function(pos, lenBefore) {\n      if (this.to <= pos && this.to != null) return null;\n      var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;\n      var to = this.to == null ? null : this.to - pos + lenBefore;\n      return new MarkedText(from, to, this.style, this.marker);\n    },\n    dup: function() { return new MarkedText(null, null, this.style, this.marker); },\n    clipTo: function(fromOpen, from, toOpen, to, diff) {\n      if (fromOpen && to > this.from && (to < this.to || this.to == null))\n        this.from = null;\n      else if (this.from != null && this.from >= from)\n        this.from = Math.max(to, this.from) + diff;\n      if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))\n        this.to = null;\n      else if (this.to != null && this.to > from)\n        this.to = to < this.to ? this.to + diff : from;\n    },\n    isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },\n    sameSet: function(x) { return this.marker == x.marker; }\n  };\n\n  function Bookmark(pos) {\n    this.from = pos; this.to = pos; this.line = null;\n  }\n  Bookmark.prototype = {\n    attach: function(line) { this.line = line; },\n    detach: function(line) { if (this.line == line) this.line = null; },\n    split: function(pos, lenBefore) {\n      if (pos < this.from) {\n        this.from = this.to = (this.from - pos) + lenBefore;\n        return this;\n      }\n    },\n    isDead: function() { return this.from > this.to; },\n    clipTo: function(fromOpen, from, toOpen, to, diff) {\n      if ((fromOpen || from < this.from) && (toOpen || to > this.to)) {\n        this.from = 0; this.to = -1;\n      } else if (this.from > from) {\n        this.from = this.to = Math.max(to, this.from) + diff;\n      }\n    },\n    sameSet: function(x) { return false; },\n    find: function() {\n      if (!this.line || !this.line.parent) return null;\n      return {line: lineNo(this.line), ch: this.from};\n    },\n    clear: function() {\n      if (this.line) {\n        var found = indexOf(this.line.marked, this);\n        if (found != -1) this.line.marked.splice(found, 1);\n        this.line = null;\n      }\n    }\n  };\n\n  // Line objects. These hold state related to a line, including\n  // highlighting info (the styles array).\n  function Line(text, styles) {\n    this.styles = styles || [text, null];\n    this.text = text;\n    this.height = 1;\n    this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null;\n    this.stateAfter = this.parent = this.hidden = null;\n  }\n  Line.inheritMarks = function(text, orig) {\n    var ln = new Line(text), mk = orig && orig.marked;\n    if (mk) {\n      for (var i = 0; i < mk.length; ++i) {\n        if (mk[i].to == null && mk[i].style) {\n          var newmk = ln.marked || (ln.marked = []), mark = mk[i];\n          var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln);\n        }\n      }\n    }\n    return ln;\n  }\n  Line.prototype = {\n    // Replace a piece of a line, keeping the styles around it intact.\n    replace: function(from, to_, text) {\n      var st = [], mk = this.marked, to = to_ == null ? this.text.length : to_;\n      copyStyles(0, from, this.styles, st);\n      if (text) st.push(text, null);\n      copyStyles(to, this.text.length, this.styles, st);\n      this.styles = st;\n      this.text = this.text.slice(0, from) + text + this.text.slice(to);\n      this.stateAfter = null;\n      if (mk) {\n        var diff = text.length - (to - from);\n        for (var i = 0; i < mk.length; ++i) {\n          var mark = mk[i];\n          mark.clipTo(from == null, from || 0, to_ == null, to, diff);\n          if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);}\n        }\n      }\n    },\n    // Split a part off a line, keeping styles and markers intact.\n    split: function(pos, textBefore) {\n      var st = [textBefore, null], mk = this.marked;\n      copyStyles(pos, this.text.length, this.styles, st);\n      var taken = new Line(textBefore + this.text.slice(pos), st);\n      if (mk) {\n        for (var i = 0; i < mk.length; ++i) {\n          var mark = mk[i];\n          var newmark = mark.split(pos, textBefore.length);\n          if (newmark) {\n            if (!taken.marked) taken.marked = [];\n            taken.marked.push(newmark); newmark.attach(taken);\n            if (newmark == mark) mk.splice(i--, 1);\n          }\n        }\n      }\n      return taken;\n    },\n    append: function(line) {\n      var mylen = this.text.length, mk = line.marked, mymk = this.marked;\n      this.text += line.text;\n      copyStyles(0, line.text.length, line.styles, this.styles);\n      if (mymk) {\n        for (var i = 0; i < mymk.length; ++i)\n          if (mymk[i].to == null) mymk[i].to = mylen;\n      }\n      if (mk && mk.length) {\n        if (!mymk) this.marked = mymk = [];\n        outer: for (var i = 0; i < mk.length; ++i) {\n          var mark = mk[i];\n          if (!mark.from) {\n            for (var j = 0; j < mymk.length; ++j) {\n              var mymark = mymk[j];\n              if (mymark.to == mylen && mymark.sameSet(mark)) {\n                mymark.to = mark.to == null ? null : mark.to + mylen;\n                if (mymark.isDead()) {\n                  mymark.detach(this);\n                  mk.splice(i--, 1);\n                }\n                continue outer;\n              }\n            }\n          }\n          mymk.push(mark);\n          mark.attach(this);\n          mark.from += mylen;\n          if (mark.to != null) mark.to += mylen;\n        }\n      }\n    },\n    fixMarkEnds: function(other) {\n      var mk = this.marked, omk = other.marked;\n      if (!mk) return;\n      for (var i = 0; i < mk.length; ++i) {\n        var mark = mk[i], close = mark.to == null;\n        if (close && omk) {\n          for (var j = 0; j < omk.length; ++j)\n            if (omk[j].sameSet(mark)) {close = false; break;}\n        }\n        if (close) mark.to = this.text.length;\n      }\n    },\n    fixMarkStarts: function() {\n      var mk = this.marked;\n      if (!mk) return;\n      for (var i = 0; i < mk.length; ++i)\n        if (mk[i].from == null) mk[i].from = 0;\n    },\n    addMark: function(mark) {\n      mark.attach(this);\n      if (this.marked == null) this.marked = [];\n      this.marked.push(mark);\n      this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);});\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    highlight: function(mode, state, tabSize) {\n      var stream = new StringStream(this.text, tabSize), st = this.styles, pos = 0;\n      var changed = false, curWord = st[0], prevWord;\n      if (this.text == \"\" && mode.blankLine) mode.blankLine(state);\n      while (!stream.eol()) {\n        var style = mode.token(stream, state);\n        var substr = this.text.slice(stream.start, stream.pos);\n        stream.start = stream.pos;\n        if (pos && st[pos-1] == style)\n          st[pos-2] += substr;\n        else if (substr) {\n          if (!changed && (st[pos+1] != style || (pos && st[pos-2] != prevWord))) changed = true;\n          st[pos++] = substr; st[pos++] = style;\n          prevWord = curWord; curWord = st[pos];\n        }\n        // Give up when line is ridiculously long\n        if (stream.pos > 5000) {\n          st[pos++] = this.text.slice(stream.pos); st[pos++] = null;\n          break;\n        }\n      }\n      if (st.length != pos) {st.length = pos; changed = true;}\n      if (pos && st[pos-2] != prevWord) changed = true;\n      // Short lines with simple highlights return null, and are\n      // counted as changed by the driver because they are likely to\n      // highlight the same way in various contexts.\n      return changed || (st.length < 5 && this.text.length < 10 ? null : false);\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(mode, state, ch) {\n      var txt = this.text, stream = new StringStream(txt);\n      while (stream.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,\n              state: state};\n    },\n    indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},\n    // Produces an HTML fragment for the line, taking selection,\n    // marking, and highlighting into account.\n    getHTML: function(makeTab, wrapAt, wrapId, wrapWBR) {\n      var html = [], first = true, col = 0;\n      function span_(text, style) {\n        if (!text) return;\n        // Work around a bug where, in some compat modes, IE ignores leading spaces\n        if (first && ie && text.charAt(0) == \" \") text = \"\\u00a0\" + text.slice(1);\n        first = false;\n        if (text.indexOf(\"\\t\") == -1) {\n          col += text.length;\n          var escaped = htmlEscape(text);\n        } else {\n          var escaped = \"\";\n          for (var pos = 0;;) {\n            var idx = text.indexOf(\"\\t\", pos);\n            if (idx == -1) {\n              escaped += htmlEscape(text.slice(pos));\n              col += text.length - pos;\n              break;\n            } else {\n              col += idx - pos;\n              var tab = makeTab(col);\n              escaped += htmlEscape(text.slice(pos, idx)) + tab.html;\n              col += tab.width;\n              pos = idx + 1;\n            }\n          }\n        }\n        if (style) html.push('<span class=\"', style, '\">', escaped, \"</span>\");\n        else html.push(escaped);\n      }\n      var span = span_;\n      if (wrapAt != null) {\n        var outPos = 0, open = \"<span id=\\\"\" + wrapId + \"\\\">\";\n        span = function(text, style) {\n          var l = text.length;\n          if (wrapAt >= outPos && wrapAt < outPos + l) {\n            if (wrapAt > outPos) {\n              span_(text.slice(0, wrapAt - outPos), style);\n              // See comment at the definition of spanAffectsWrapping\n              if (wrapWBR) html.push(\"<wbr>\");\n            }\n            html.push(open);\n            var cut = wrapAt - outPos;\n            span_(window.opera ? text.slice(cut, cut + 1) : text.slice(cut), style);\n            html.push(\"</span>\");\n            if (window.opera) span_(text.slice(cut + 1), style);\n            wrapAt--;\n            outPos += l;\n          } else {\n            outPos += l;\n            span_(text, style);\n            // Output empty wrapper when at end of line\n            if (outPos == wrapAt && outPos == len) html.push(open + \" </span>\");\n            // Stop outputting HTML when gone sufficiently far beyond measure\n            else if (outPos > wrapAt + 10 && /\\s/.test(text)) span = function(){};\n          }\n        }\n      }\n\n      var st = this.styles, allText = this.text, marked = this.marked;\n      var len = allText.length;\n      function styleToClass(style) {\n        if (!style) return null;\n        return \"cm-\" + style.replace(/ +/g, \" cm-\");\n      }\n\n      if (!allText && wrapAt == null) {\n        span(\" \");\n      } else if (!marked || !marked.length) {\n        for (var i = 0, ch = 0; ch < len; i+=2) {\n          var str = st[i], style = st[i+1], l = str.length;\n          if (ch + l > len) str = str.slice(0, len - ch);\n          ch += l;\n          span(str, styleToClass(style));\n        }\n      } else {\n        var pos = 0, i = 0, text = \"\", style, sg = 0;\n        var nextChange = marked[0].from || 0, marks = [], markpos = 0;\n        function advanceMarks() {\n          var m;\n          while (markpos < marked.length &&\n                 ((m = marked[markpos]).from == pos || m.from == null)) {\n            if (m.style != null) marks.push(m);\n            ++markpos;\n          }\n          nextChange = markpos < marked.length ? marked[markpos].from : Infinity;\n          for (var i = 0; i < marks.length; ++i) {\n            var to = marks[i].to || Infinity;\n            if (to == pos) marks.splice(i--, 1);\n            else nextChange = Math.min(to, nextChange);\n          }\n        }\n        var m = 0;\n        while (pos < len) {\n          if (nextChange == pos) advanceMarks();\n          var upto = Math.min(len, nextChange);\n          while (true) {\n            if (text) {\n              var end = pos + text.length;\n              var appliedStyle = style;\n              for (var j = 0; j < marks.length; ++j)\n                appliedStyle = (appliedStyle ? appliedStyle + \" \" : \"\") + marks[j].style;\n              span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);\n              if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}\n              pos = end;\n            }\n            text = st[i++]; style = styleToClass(st[i++]);\n          }\n        }\n      }\n      return html.join(\"\");\n    },\n    cleanUp: function() {\n      this.parent = null;\n      if (this.marked)\n        for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this);\n    }\n  };\n  // Utility used by replace and split above\n  function copyStyles(from, to, source, dest) {\n    for (var i = 0, pos = 0, state = 0; pos < to; i+=2) {\n      var part = source[i], end = pos + part.length;\n      if (state == 0) {\n        if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);\n        if (end >= from) state = 1;\n      }\n      else if (state == 1) {\n        if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);\n        else dest.push(part, source[i+1]);\n      }\n      pos = end;\n    }\n  }\n\n  // Data structure that holds the sequence of lines.\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  LeafChunk.prototype = {\n    chunkSize: function() { return this.lines.length; },\n    remove: function(at, n, callbacks) {\n      for (var i = at, e = at + n; i < e; ++i) {\n        var line = this.lines[i];\n        this.height -= line.height;\n        line.cleanUp();\n        if (line.handlers)\n          for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]);\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    insertHeight: 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  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  BranchChunk.prototype = {\n    chunkSize: function() { return this.size; },\n    remove: function(at, n, callbacks) {\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.remove(at, rm, callbacks);\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    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.insertHeight(at, lines, height);\n    },\n    insertHeight: 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.insertHeight(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    iter: function(from, to, op) { this.iterN(from, to - from, op); },\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  function getLineAt(chunk, n) {\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  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, e = chunk.children.length; ; ++i) {\n        if (chunk.children[i] == cur) break;\n        no += chunk.children[i].chunkSize();\n      }\n    }\n    return no;\n  }\n  function lineAtHeight(chunk, h) {\n    var n = 0;\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  function heightAtLine(chunk, n) {\n    var h = 0;\n    outer: do {\n      for (var i = 0, e = chunk.children.length; i < e; ++i) {\n        var child = chunk.children[i], sz = child.chunkSize();\n        if (n < sz) { chunk = child; continue outer; }\n        n -= sz;\n        h += child.height;\n      }\n      return h;\n    } while (!chunk.lines);\n    for (var i = 0; i < n; ++i) h += chunk.lines[i].height;\n    return h;\n  }\n\n  // The history object 'chunks' changes that are made close together\n  // and at almost the same time into bigger undoable units.\n  function History() {\n    this.time = 0;\n    this.done = []; this.undone = [];\n    this.compound = 0;\n    this.closed = false;\n  }\n  History.prototype = {\n    addChange: function(start, added, old) {\n      this.undone.length = 0;\n      var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];\n      var dtime = time - this.time;\n\n      if (this.compound && cur && !this.closed) {\n        cur.push({start: start, added: added, old: old});\n      } else if (dtime > 400 || !last || this.closed ||\n                 last.start > start + old.length || last.start + last.added < start) {\n        this.done.push([{start: start, added: added, old: old}]);\n        this.closed = false;\n      } else {\n        var startBefore = Math.max(0, last.start - start),\n            endAfter = Math.max(0, (start + old.length) - (last.start + last.added));\n        for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);\n        for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);\n        if (startBefore) last.start = start;\n        last.added += added - (old.length - startBefore - endAfter);\n      }\n      this.time = time;\n    },\n    startCompound: function() {\n      if (!this.compound++) this.closed = true;\n    },\n    endCompound: function() {\n      if (!--this.compound) this.closed = true;\n    }\n  };\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_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    if (e.which) return e.which;\n    else if (e.button & 1) return 1;\n    else if (e.button & 2) return 3;\n    else if (e.button & 4) return 2;\n  }\n\n  // Allow 3rd-party code to override event properties by adding an override\n  // object to an event object.\n  function e_prop(e, prop) {\n    var overridden = e.override && e.override.hasOwnProperty(prop);\n    return overridden ? e.override[prop] : e[prop];\n  }\n\n  // Event handler registration. If disconnect is true, it'll return a\n  // function that unregisters the handler.\n  function connect(node, type, handler, disconnect) {\n    if (typeof node.addEventListener == \"function\") {\n      node.addEventListener(type, handler, false);\n      if (disconnect) return function() {node.removeEventListener(type, handler, false);};\n    }\n    else {\n      var wrapHandler = function(event) {handler(event || window.event);};\n      node.attachEvent(\"on\" + type, wrapHandler);\n      if (disconnect) return function() {node.detachEvent(\"on\" + type, wrapHandler);};\n    }\n  }\n  CodeMirror.connect = connect;\n\n  function Delayed() {this.id = null;}\n  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};\n\n  var Pass = CodeMirror.Pass = {toString: function(){return \"CodeMirror.Pass\";}};\n\n  var gecko = /gecko\\/\\d{7}/i.test(navigator.userAgent);\n  var ie = /MSIE \\d/.test(navigator.userAgent);\n  var ie_lt9 = /MSIE [1-8]\\b/.test(navigator.userAgent);\n  var quirksMode = ie && document.documentMode == 5;\n  var webkit = /WebKit\\//.test(navigator.userAgent);\n  var chrome = /Chrome\\//.test(navigator.userAgent);\n  var safari = /Apple Computer/.test(navigator.vendor);\n  var khtml = /KHTML\\//.test(navigator.userAgent);\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 = document.createElement('div');\n    return \"draggable\" in div || \"dragDrop\" in div;\n  }();\n\n  // Feature-detect whether newlines in textareas are converted to \\r\\n\n  var lineSep = function () {\n    var te = document.createElement(\"textarea\");\n    te.value = \"foo\\nbar\";\n    if (te.value.indexOf(\"\\r\") > -1) return \"\\r\\n\";\n    return \"\\n\";\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 regexps matches the\n  // character combinations that suffer from this phenomenon on the\n  // various browsers.\n  var spanAffectsWrapping = /^$/; // Won't match any two-character string\n  if (gecko) spanAffectsWrapping = /$'/;\n  else if (safari) spanAffectsWrapping = /\\-[^ \\-?]|\\?[^ !'\\\"\\),.\\-\\/:;\\?\\]\\}]/;\n  else if (chrome) spanAffectsWrapping = /\\-[^ \\-\\.?]|\\?[^ \\-\\.?\\]\\}:;!'\\\"\\),\\/]|[\\.!\\\"#&%\\)*+,:;=>\\]|\\}~][\\(\\{\\[<]|\\$'/;\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) {\n    if (end == null) {\n      end = string.search(/[^\\s\\u00a0]/);\n      if (end == -1) end = string.length;\n    }\n    for (var i = 0, n = 0; i < end; ++i) {\n      if (string.charAt(i) == \"\\t\") n += tabSize - (n % tabSize);\n      else ++n;\n    }\n    return n;\n  }\n\n  function computedStyle(elt) {\n    if (elt.currentStyle) return elt.currentStyle;\n    return window.getComputedStyle(elt, null);\n  }\n\n  // Find the position of an element by following the offsetParent chain.\n  // If screen==true, it returns screen (rather than page) coordinates.\n  function eltOffset(node, screen) {\n    var bod = node.ownerDocument.body;\n    var x = 0, y = 0, skipBody = false;\n    for (var n = node; n; n = n.offsetParent) {\n      var ol = n.offsetLeft, ot = n.offsetTop;\n      // Firefox reports weird inverted offsets when the body has a border.\n      if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); }\n      else { x += ol, y += ot; }\n      if (screen && computedStyle(n).position == \"fixed\")\n        skipBody = true;\n    }\n    var e = screen && !skipBody ? null : bod;\n    for (var n = node.parentNode; n != e; n = n.parentNode)\n      if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;}\n    return {left: x, top: y};\n  }\n  // Use the faster and saner getBoundingClientRect method when possible.\n  if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) {\n    // Take the parts of bounding client rect that we are interested in so we are able to edit if need be,\n    // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)\n    try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }\n    catch(e) { box = {top: 0, left: 0}; }\n    if (!screen) {\n      // Get the toplevel scroll, working around browser differences.\n      if (window.pageYOffset == null) {\n        var t = document.documentElement || document.body.parentNode;\n        if (t.scrollTop == null) t = document.body;\n        box.top += t.scrollTop; box.left += t.scrollLeft;\n      } else {\n        box.top += window.pageYOffset; box.left += window.pageXOffset;\n      }\n    }\n    return box;\n  };\n\n  // Get a node's text content.\n  function eltText(node) {\n    return node.textContent || node.innerText || node.nodeValue || \"\";\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 node.select();\n  }\n\n  // Operations on {line, ch} objects.\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 copyPos(x) {return {line: x.line, ch: x.ch};}\n\n  var escapeElement = document.createElement(\"pre\");\n  function htmlEscape(str) {\n    escapeElement.textContent = str;\n    return escapeElement.innerHTML;\n  }\n  // Recent (late 2011) Opera betas insert bogus newlines at the start\n  // of the textContent, so we strip those.\n  if (htmlEscape(\"a\") == \"\\na\")\n    htmlEscape = function(str) {\n      escapeElement.textContent = str;\n      return escapeElement.innerHTML.slice(1);\n    };\n  // Some IEs don't preserve tabs through innerHTML\n  else if (htmlEscape(\"\\t\") != \"\\t\")\n    htmlEscape = function(str) {\n      escapeElement.innerHTML = \"\";\n      escapeElement.appendChild(document.createTextNode(str));\n      return escapeElement.innerHTML;\n    };\n  CodeMirror.htmlEscape = htmlEscape;\n\n  // Used to position the cursor after an undo/redo by finding the\n  // last edited character.\n  function editEnd(from, to) {\n    if (!to) return 0;\n    if (!from) return to.length;\n    for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)\n      if (from.charAt(i) != to.charAt(j)) break;\n    return j + 1;\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  function isWordChar(ch) {\n    return /\\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase();\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, nl, result = [];\n    while ((nl = string.indexOf(\"\\n\", pos)) > -1) {\n      result.push(string.slice(pos, string.charAt(nl-1) == \"\\r\" ? nl - 1 : nl));\n      pos = nl + 1;\n    }\n    result.push(string.slice(pos));\n    return result;\n  } : function(string){return string.split(/\\r?\\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  CodeMirror.defineMode(\"null\", function() {\n    return {token: function(stream) {stream.skipToEnd();}};\n  });\n  CodeMirror.defineMIME(\"text/plain\", \"null\");\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: \";\", 91: \"Mod\", 92: \"Mod\", 93: \"Mod\", 127: \"Delete\", 186: \";\", 187: \"=\", 188: \",\",\n                  189: \"-\", 190: \".\", 191: \"/\", 192: \"`\", 219: \"[\", 220: \"\\\\\", 221: \"]\", 222: \"'\", 63276: \"PageUp\",\n                  63277: \"PageDown\", 63275: \"End\", 63273: \"Home\", 63234: \"Left\", 63232: \"Up\", 63235: \"Right\",\n                  63233: \"Down\", 63302: \"Insert\", 63272: \"Delete\"};\n  CodeMirror.keyNames = keyNames;\n  (function() {\n    // Number keys\n    for (var i = 0; i < 10; i++) keyNames[i + 48] = 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  return CodeMirror;\n})();\n"
  },
  {
    "path": "site/examples/friendlycode/codemirror2/mode/css/css.js",
    "content": "CodeMirror.defineMode(\"css\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == \"@\") {stream.eatWhile(/[\\w\\\\\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"#\") {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"atom\", \"hash\");\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,.+>*\\/]/.test(ch)) {\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]]/.test(ch)) {\n      return ret(null, ch);\n    }\n    else {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"variable\", \"variable\");\n    }\n  }\n\n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context != \"rule\") style = \"string-2\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = \"number\";\n        else if (!context || context == \"@media{\") style = \"tag\";\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/css\", \"css\");\n"
  },
  {
    "path": "site/examples/friendlycode/codemirror2/mode/htmlmixed/htmlmixed.js",
    "content": "CodeMirror.defineMode(\"htmlmixed\", function(config, parserConfig) {\n  var htmlMode = CodeMirror.getMode(config, {name: \"xml\", htmlMode: true});\n  var jsMode = CodeMirror.getMode(config, \"javascript\");\n  var cssMode = CodeMirror.getMode(config, \"css\");\n\n  function html(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if (style == \"tag\" && stream.current() == \">\" && state.htmlState.context) {\n      if (/^script$/i.test(state.htmlState.context.tagName)) {\n        state.token = javascript;\n        state.localState = jsMode.startState(htmlMode.indent(state.htmlState, \"\"));\n        state.mode = \"javascript\";\n      }\n      else if (/^style$/i.test(state.htmlState.context.tagName)) {\n        state.token = css;\n        state.localState = cssMode.startState(htmlMode.indent(state.htmlState, \"\"));\n        state.mode = \"css\";\n      }\n    }\n    return style;\n  }\n  function maybeBackup(stream, pat, style) {\n    var cur = stream.current();\n    var close = cur.search(pat);\n    if (close > -1) stream.backUp(cur.length - close);\n    return style;\n  }\n  function javascript(stream, state) {\n    if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n                       jsMode.token(stream, state.localState));\n  }\n  function css(stream, state) {\n    if (stream.match(/^<\\/\\s*style\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*style\\s*>/,\n                       cssMode.token(stream, state.localState));\n  }\n\n  return {\n    startState: function() {\n      var state = htmlMode.startState();\n      return {token: html, localState: null, mode: \"html\", htmlState: state};\n    },\n\n    copyState: function(state) {\n      if (state.localState)\n        var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);\n      return {token: state.token, localState: local, mode: state.mode,\n              htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.token == html || /^\\s*<\\//.test(textAfter))\n        return htmlMode.indent(state.htmlState, textAfter);\n      else if (state.token == javascript)\n        return jsMode.indent(state.localState, textAfter);\n      else\n        return cssMode.indent(state.localState, textAfter);\n    },\n\n    compareStates: function(a, b) {\n      if (a.mode != b.mode) return false;\n      if (a.localState) return CodeMirror.Pass;\n      return htmlMode.compareStates(a.htmlState, b.htmlState);\n    },\n\n    electricChars: \"/{}:\"\n  }\n}, \"xml\", \"javascript\", \"css\");\n\nCodeMirror.defineMIME(\"text/html\", \"htmlmixed\");\n"
  },
  {
    "path": "site/examples/friendlycode/codemirror2/mode/javascript/javascript.js",
    "content": "CodeMirror.defineMode(\"javascript\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var jsonMode = parserConfig.json;\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    return {\n      \"if\": A, \"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,\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    };\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|]/;\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  function nextUntilUnescaped(stream, end) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (next == end && !escaped)\n        return false;\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return escaped;\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\n  function jsTokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, jsTokenString(ch));\n    else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch))\n      return ret(ch);\n    else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    }      \n    else if (/\\d/.test(ch) || ch == \"-\" && stream.eat(/\\d/)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    }\n    else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, jsTokenComment);\n      }\n      else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      }\n      else if (state.reAllowed) {\n        nextUntilUnescaped(stream, \"/\");\n        stream.eatWhile(/[gimy]/); // 'y' is \"sticky\" option in Mozilla\n        return ret(\"regexp\", \"string-2\");\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", null, stream.current());\n      }\n    }\n    else if (ch == \"#\") {\n        stream.skipToEnd();\n        return ret(\"error\", \"error\");\n    }\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", null, stream.current());\n    }\n    else {\n      stream.eatWhile(/[\\w\\$_]/);\n      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n      return (known && state.kwAllowed) ? ret(known.type, known.style, word) :\n                     ret(\"variable\", \"variable\", word);\n    }\n  }\n\n  function jsTokenString(quote) {\n    return function(stream, state) {\n      if (!nextUntilUnescaped(stream, quote))\n        state.tokenize = jsTokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function jsTokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": 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  }\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    var state = cx.state;\n    if (state.context) {\n      cx.marked = \"def\";\n      for (var v = state.localVars; v; v = v.next)\n        if (v.name == varname) return;\n      state.localVars = {name: varname, next: state.localVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: {name: \"arguments\"}};\n  function pushcontext() {\n    if (!cx.state.context) cx.state.localVars = defaultVars;\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\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;\n      state.lexical = new JSLexical(state.indented, 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 expecting(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) {\n    if (type == \"var\") return cont(pushlex(\"vardef\"), vardef1, 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 == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), expect(\"(\"), pushlex(\")\"), forspec1, expect(\")\"),\n                                      poplex, 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    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"keyword c\") return cont(maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, expect(\")\"), poplex, maybeoperator);\n    if (type == \"operator\") return cont(expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), commasep(expression, \"]\"), poplex, maybeoperator);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(objprop, \"}\"), poplex, maybeoperator);\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n    \n  function maybeoperator(type, value) {\n    if (type == \"operator\" && /\\+\\+|--/.test(value)) return cont(maybeoperator);\n    if (type == \"operator\" || type == \":\") return cont(expression);\n    if (type == \";\") return;\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(expression, \")\"), poplex, maybeoperator);\n    if (type == \".\") return cont(property, maybeoperator);\n    if (type == \"[\") return cont(pushlex(\"]\"), expression, expect(\"]\"), poplex, maybeoperator);\n  }\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperator, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type) {\n    if (type == \"variable\") cx.marked = \"property\";\n    if (atomicTypes.hasOwnProperty(type)) return cont(expect(\":\"), expression);\n  }\n  function commasep(what, end) {\n    function proceed(type) {\n      if (type == \",\") return cont(what, proceed);\n      if (type == end) return cont();\n      return cont(expect(end));\n    }\n    return function commaSeparated(type) {\n      if (type == end) return cont();\n      else return pass(what, proceed);\n    };\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function vardef1(type, value) {\n    if (type == \"variable\"){register(value); return cont(vardef2);}\n    return cont();\n  }\n  function vardef2(type, value) {\n    if (value == \"=\") return cont(expression, vardef2);\n    if (type == \",\") return cont(vardef1);\n  }\n  function forspec1(type) {\n    if (type == \"var\") return cont(vardef1, forspec2);\n    if (type == \";\") return pass(forspec2);\n    if (type == \"variable\") return cont(formaybein);\n    return pass(forspec2);\n  }\n  function formaybein(type, value) {\n    if (value == \"in\") return cont(expression);\n    return cont(maybeoperator, forspec2);\n  }\n  function forspec2(type, value) {\n    if (type == \";\") return cont(forspec3);\n    if (value == \"in\") return cont(expression);\n    return cont(expression, expect(\";\"), forspec3);\n  }\n  function forspec3(type) {\n    if (type != \")\") cont(expression);\n  }\n  function functiondef(type, value) {\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (type == \"(\") return cont(pushlex(\")\"), pushcontext, commasep(funarg, \")\"), poplex, statement, popcontext);\n  }\n  function funarg(type, value) {\n    if (type == \"variable\") {register(value); return cont();}\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: jsTokenBase,\n        reAllowed: true,\n        kwAllowed: true,\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    },\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      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.reAllowed = !!(type == \"operator\" || type == \"keyword c\" || type.match(/^[\\[{}\\(,;:]$/));\n      state.kwAllowed = type != '.';\n      return parseJS(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != jsTokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;\n      if (lexical.type == \"stat\" && firstChar == \"}\") lexical = lexical.prev;\n      var type = lexical.type, closing = firstChar == type;\n      if (type == \"vardef\") return lexical.indented + 4;\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"stat\" || type == \"form\") return lexical.indented + indentUnit;\n      else if (lexical.info == \"switch\" && !closing)\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  };\n});\n\nCodeMirror.defineMIME(\"text/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/json\", {name: \"javascript\", json: true});\n"
  },
  {
    "path": "site/examples/friendlycode/codemirror2/mode/xml/xml.js",
    "content": "CodeMirror.defineMode(\"xml\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var Kludges = parserConfig.htmlMode ? {\n    autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,\n                      'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,\n                      'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,\n                      'track': true, 'wbr': true},\n    implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,\n                       'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,\n                       'th': true, 'tr': true},\n    contextGrabbers: {\n      'dd': {'dd': true, 'dt': true},\n      'dt': {'dd': true, 'dt': true},\n      'li': {'li': true},\n      'option': {'option': true, 'optgroup': true},\n      'optgroup': {'optgroup': true},\n      'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,\n            'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,\n            'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,\n            'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,\n            'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},\n      'rp': {'rp': true, 'rt': true},\n      'rt': {'rp': true, 'rt': true},\n      'tbody': {'tbody': true, 'tfoot': true},\n      'td': {'td': true, 'th': true},\n      'tfoot': {'tbody': true},\n      'th': {'td': true, 'th': true},\n      'thead': {'tbody': true, 'tfoot': true},\n      'tr': {'tr': true}\n    },\n    doNotIndent: {\"pre\": true},\n    allowUnquoted: true,\n    allowMissing: false\n  } : {\n    autoSelfClosers: {},\n    implicitlyClosed: {},\n    contextGrabbers: {},\n    doNotIndent: {},\n    allowUnquoted: false,\n    allowMissing: false\n  };\n  var alignCDATA = parserConfig.alignCDATA;\n\n  // Return variables for tokenizers\n  var tagName, type;\n\n  function inText(stream, state) {\n    function chain(parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n\n    var ch = stream.next();\n    if (ch == \"<\") {\n      if (stream.eat(\"!\")) {\n        if (stream.eat(\"[\")) {\n          if (stream.match(\"CDATA[\")) return chain(inBlock(\"atom\", \"]]>\"));\n          else return null;\n        }\n        else if (stream.match(\"--\")) return chain(inBlock(\"comment\", \"-->\"));\n        else if (stream.match(\"DOCTYPE\", true, true)) {\n          stream.eatWhile(/[\\w\\._\\-]/);\n          return chain(doctype(1));\n        }\n        else return null;\n      }\n      else if (stream.eat(\"?\")) {\n        stream.eatWhile(/[\\w\\._\\-]/);\n        state.tokenize = inBlock(\"meta\", \"?>\");\n        return \"meta\";\n      }\n      else {\n        type = stream.eat(\"/\") ? \"closeTag\" : \"openTag\";\n        stream.eatSpace();\n        tagName = \"\";\n        var c;\n        while ((c = stream.eat(/[^\\s\\u00a0=<>\\\"\\'\\/?]/))) tagName += c;\n        state.tokenize = inTag;\n        return \"tag\";\n      }\n    }\n    else if (ch == \"&\") {\n      var ok;\n      if (stream.eat(\"#\")) {\n        if (stream.eat(\"x\")) {\n          ok = stream.eatWhile(/[a-fA-F\\d]/) && stream.eat(\";\");          \n        } else {\n          ok = stream.eatWhile(/[\\d]/) && stream.eat(\";\");\n        }\n      } else {\n        ok = stream.eatWhile(/[\\w\\.\\-:]/) && stream.eat(\";\");\n      }\n      return ok ? \"atom\" : \"error\";\n    }\n    else {\n      stream.eatWhile(/[^&<]/);\n      return null;\n    }\n  }\n\n  function inTag(stream, state) {\n    var ch = stream.next();\n    if (ch == \">\" || (ch == \"/\" && stream.eat(\">\"))) {\n      state.tokenize = inText;\n      type = ch == \">\" ? \"endTag\" : \"selfcloseTag\";\n      return \"tag\";\n    }\n    else if (ch == \"=\") {\n      type = \"equals\";\n      return null;\n    }\n    else if (/[\\'\\\"]/.test(ch)) {\n      state.tokenize = inAttribute(ch);\n      return state.tokenize(stream, state);\n    }\n    else {\n      stream.eatWhile(/[^\\s\\u00a0=<>\\\"\\'\\/?]/);\n      return \"word\";\n    }\n  }\n\n  function inAttribute(quote) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.next() == quote) {\n          state.tokenize = inTag;\n          break;\n        }\n      }\n      return \"string\";\n    };\n  }\n\n  function inBlock(style, terminator) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = inText;\n          break;\n        }\n        stream.next();\n      }\n      return style;\n    };\n  }\n  function doctype(depth) {\n    return function(stream, state) {\n      var ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == \"<\") {\n          state.tokenize = doctype(depth + 1);\n          return state.tokenize(stream, state);\n        } else if (ch == \">\") {\n          if (depth == 1) {\n            state.tokenize = inText;\n            break;\n          } else {\n            state.tokenize = doctype(depth - 1);\n            return state.tokenize(stream, state);\n          }\n        }\n      }\n      return \"meta\";\n    };\n  }\n\n  var curState, setStyle;\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n\n  function pushContext(tagName, startOfLine) {\n    var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);\n    curState.context = {\n      prev: curState.context,\n      tagName: tagName,\n      indent: curState.indented,\n      startOfLine: startOfLine,\n      noIndent: noIndent\n    };\n  }\n  function popContext() {\n    if (curState.context) curState.context = curState.context.prev;\n  }\n\n  function element(type) {\n    if (type == \"openTag\") {\n      curState.tagName = tagName;\n      return cont(attributes, endtag(curState.startOfLine));\n    } else if (type == \"closeTag\") {\n      var err = false;\n      if (curState.context) {\n        if (curState.context.tagName != tagName) {\n          if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {\n            popContext();\n          }\n          err = !curState.context || curState.context.tagName != tagName;\n        }\n      } else {\n        err = true;\n      }\n      if (err) setStyle = \"error\";\n      return cont(endclosetag(err));\n    }\n    return cont();\n  }\n  function endtag(startOfLine) {\n    return function(type) {\n      if (type == \"selfcloseTag\" ||\n          (type == \"endTag\" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) {\n        maybePopContext(curState.tagName.toLowerCase());\n        return cont();\n      }\n      if (type == \"endTag\") {\n        maybePopContext(curState.tagName.toLowerCase());\n        pushContext(curState.tagName, startOfLine);\n        return cont();\n      }\n      return cont();\n    };\n  }\n  function endclosetag(err) {\n    return function(type) {\n      if (err) setStyle = \"error\";\n      if (type == \"endTag\") { popContext(); return cont(); }\n      setStyle = \"error\";\n      return cont(arguments.callee);\n    }\n  }\n  function maybePopContext(nextTagName) {\n    var parentTagName;\n    while (true) {\n      if (!curState.context) {\n        return;\n      }\n      parentTagName = curState.context.tagName.toLowerCase();\n      if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||\n          !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {\n        return;\n      }\n      popContext();\n    }\n  }\n\n  function attributes(type) {\n    if (type == \"word\") {setStyle = \"attribute\"; return cont(attribute, attributes);}\n    if (type == \"endTag\" || type == \"selfcloseTag\") return pass();\n    setStyle = \"error\";\n    return cont(attributes);\n  }\n  function attribute(type) {\n    if (type == \"equals\") return cont(attvalue, attributes);\n    if (!Kludges.allowMissing) setStyle = \"error\";\n    return (type == \"endTag\" || type == \"selfcloseTag\") ? pass() : cont();\n  }\n  function attvalue(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    if (type == \"word\" && Kludges.allowUnquoted) {setStyle = \"string\"; return cont();}\n    setStyle = \"error\";\n    return (type == \"endTag\" || type == \"selfCloseTag\") ? pass() : cont();\n  }\n  function attvaluemaybe(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    else return pass();\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        state.startOfLine = true;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n\n      setStyle = type = tagName = null;\n      var style = state.tokenize(stream, state);\n      state.type = type;\n      if ((style || type) && style != \"comment\") {\n        curState = state;\n        while (true) {\n          var comb = state.cc.pop() || element;\n          if (comb(type || style)) break;\n        }\n      }\n      state.startOfLine = false;\n      return setStyle || style;\n    },\n\n    indent: function(state, textAfter, fullLine) {\n      var context = state.context;\n      if ((state.tokenize != inTag && state.tokenize != inText) ||\n          context && context.noIndent)\n        return fullLine ? fullLine.match(/^(\\s*)/)[0].length : 0;\n      if (alignCDATA && /<!\\[CDATA\\[/.test(textAfter)) return 0;\n      if (context && /^<\\//.test(textAfter))\n        context = context.prev;\n      while (context && !context.startOfLine)\n        context = context.prev;\n      if (context) return context.indent + indentUnit;\n      else return 0;\n    },\n\n    compareStates: function(a, b) {\n      if (a.indented != b.indented || a.tokenize != b.tokenize) return false;\n      for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {\n        if (!ca || !cb) return ca == cb;\n        if (ca.tagName != cb.tagName) return false;\n      }\n    },\n\n    electricChars: \"/\"\n  };\n});\n\nCodeMirror.defineMIME(\"application/xml\", \"xml\");\nif (!CodeMirror.mimeModes.hasOwnProperty(\"text/html\"))\n  CodeMirror.defineMIME(\"text/html\", {name: \"xml\", htmlMode: true});\n"
  },
  {
    "path": "site/examples/friendlycode/css/buttons.css",
    "content": ".wm-button {\n  display: inline-block;\n  padding: 0 12px;\n  white-space: nowrap;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  -ms-box-sizing: border-box;\n  box-sizing: border-box;\n  height: 36px;\n  line-height: 34px;\n  border-radius: 2px;\n  font-size: 12px;\n  cursor: pointer;\n  background: #d6d8d7;\n  color: #777;\n  border: 1px solid #959a97;\n  box-shadow: 0 5px 3px -4px rgba(0, 0, 0, 0.3), inset 0 0 0 1px rgba(255, 255, 255, 0.1);\n}\n.wm-button:hover {\n  background: #F5F5F5;\n  box-shadow: 0 4px 6px -4px rgba(0, 0, 0, 0.4), inset 0 0 0 1px #959a97;\n}\n.wm-button.wm-button-blue {\n  filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr='#68a2f1', endColorstr='#3985ed', GradientType=0);\n  background: -webkit-gradient(linear, top, bottom, color-stop(0%, #68a2f1), color-stop(100%, #3985ed));\n  background: -webkit-linear-gradient(top, #68a2f1 0%, #3985ed 100%);\n  background: -moz-linear-gradient(top, #68a2f1 0%, #3985ed 100%);\n  background: -ms-linear-gradient(top, #68a2f1 0%, #3985ed 100%);\n  background: -o-linear-gradient(top, #68a2f1 0%, #3985ed 100%);\n  background: linear-gradient(top, #68a2f1);\n  border-color: #2679eb;\n  color: #FFF;\n}\n.wm-button.wm-button-blue:hover {\n  filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr='#7fb0f3', endColorstr='#5093ef', GradientType=0);\n  background: -webkit-gradient(linear, top, bottom, color-stop(0%, #7fb0f3), color-stop(100%, #5093ef));\n  background: -webkit-linear-gradient(top, #7fb0f3 0%, #5093ef 100%);\n  background: -moz-linear-gradient(top, #7fb0f3 0%, #5093ef 100%);\n  background: -ms-linear-gradient(top, #7fb0f3 0%, #5093ef 100%);\n  background: -o-linear-gradient(top, #7fb0f3 0%, #5093ef 100%);\n  background: linear-gradient(top, #7fb0f3);\n  border-color: #2277eb;\n  box-shadow: 0 4px 7px -4px rgba(0, 0, 0, 0.6);\n}\n\n.wm-button.short {\n  height: 28px;\n  line-height: 26px;\n}"
  },
  {
    "path": "site/examples/friendlycode/css/editor.css",
    "content": ".friendlycode-base {\n  font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  overflow: hidden;\n  background-color: #F5F5F5;\n  color: #414244;\n}\n\n.friendlycode-base img {\n  border: 0 none;\n}\n\n.friendlycode-loading > * {\n  visibility: hidden;\n}\n\n.friendlycode-loading {\n  position: absolute;\n  top: 0;\n  width: 100%;\n  left: 0;\n  right: 0;\n  height: 41px;\n  background: white;\n  color: lightgray;\n  border-bottom: 1px solid #D6D6D6;\n  font-family: sans-serif;\n  font-size: 12px;\n  padding: 14px 0 0 42px;\n  background-image: url(../img/throbber.gif);\n  background-position: 20px 12px;\n  background-repeat: no-repeat;\n  -webkit-box-shadow: 0 5px 5px 0 rgba(233,233,233,0.5);\n  box-shadow: 0 5px 5px 0 rgba(233,233,233,0.5);\n  \n  -moz-box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n  \n  -moz-animation-duration: 4s;\n  -moz-animation-name: friendlycode-loading-fadein;\n  -webkit-animation-duration: 4s;\n  -webkit-animation-name: friendlycode-loading-fadein;\n}\n\n@-moz-keyframes friendlycode-loading-fadein {\n  /* Slowly fade-in the loading message, so that users on really slow\n   * connections will see it, but users on fast connections won't\n   * see the distracting flicker of a loading message that only shows\n   * itself for a split-second. */\n  \n  from {\n    color: white;\n  }\n  \n  to {\n    color: lightgray;\n  }\n}\n\n@-webkit-keyframes friendlycode-loading-fadein {\n  from {\n    color: white;\n  }\n  \n  to {\n    color: lightgray;\n  }\n}\n\n.friendlycode-loading:before {\n  content: 'Loading...';\n}\n\n.friendlycode-toolbar {\n  position: absolute;\n  z-index: 2;\n  top: 0;\n\n  height: 40px;    /* corresponds with .friendlycode-panes.top */\n  width: 100%;\n  margin: 0;\n  padding: 0;\n\n  border-bottom: 1px solid #D6D6D6;\n  \n  background: white;\n  \n  -webkit-box-shadow: 0 5px 5px 0 rgba(233,233,233,0.5);\n  box-shadow: 0 5px 5px 0 rgba(233,233,233,0.5);\n}\n\n.nav-options {\n  font-size: 12px;\n\n  position: absolute;\n  display: block;\n  top: 0;\n  width: 100%;\n  height: 0;\n}\n\n.editor-pane-nav-options {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 50%;\n  height: 100%;\n  border-right: 1px solid #D6D6D6;\n  z-index: 2;\n  height: 41px;\n}\n\n.preview-pane-nav-options {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  width: 50%;\n  height: 100%;\n  z-index: 1;\n}\n\n.nav-options .nav-item {\n  display: table-cell;\n  height: 41px;\n  text-align: center;\n  vertical-align: middle;\n  color: gray;\n  padding: 0 5px;\n  padding-right: 2em;\n  white-space: nowrap;\n  cursor: default;\n  font-size: 14px;\n  opacity: 0.33;\n  -moz-transition: opacity 0.5s;\n  -webkit-transition: opacity 0.5s;\n  -o-transition: opacity 0.5s;\n  \n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -khtml-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.nav-options .nav-item.enabled {\n  cursor: pointer;\n  opacity: 1.0;\n}\n\n.nav-options .nav-item.enabled:hover {\n  color: #3D59FE;\n}\n\n@media screen and (max-width: 980px) {\n  .nav-options .responsive,\n  .nav-options .responsive:hover,\n  .nav-options .nav-item.responsive.enabled {\n    max-width: 30px;\n    overflow: hidden;\n    background-position: center center;\n    color: transparent !important;\n  }\n  .nav-options .nav-item ul,\n  .nav-options .nav-item ul li {\n    max-width: 999px !important;\n    width: auto !important;\n    padding-right: 1em;\n    color: black;\n  }\n  .nav-options .nav-item {\n    border: none;\n  }\n}\n\n@media screen and (max-width: 785px) {\n  .editor-pane-nav-options {\n    border: none;\n  }\n  .preview-pane-nav-options {\n   left: 65%;\n  }\n  .preview-nav-item .icon {\n    margin-right: 0 !important;\n  }\n  .preview-nav-item {\n    border-left: 1px solid #D6D6D6 !important;\n    border-right: 1px solid #D6D6D6 !important;\n    padding-right: 10px !important;\n  }\n  .nav-options .nav-item.buttons {\n    right: 30% !important;\n  }\n  .hints-nav-item {\n    margin-left: 0 !important;\n    left: 310px !important;\n  }\n}\n\n@media screen and (max-width: 620px) {\n  .editor-nav-item.nav-item,\n  .preview-nav-item.nav-item {\n    display: none !important;\n  }\n  .hints-nav-item {\n    left: 180px !important;\n  }\n}\n\n@media screen and (max-width: 420px) {\n  .preview-pane-nav-options > div.nav-item.buttons {\n    left: 0 !important;\n    right: auto !important;\n  }\n}\n\n.nav-options .nav-item ul li {\n  color: #666;\n}\n\n.nav-options .nav-item ul li:hover {\n  color: #666;\n}\n\n.preview-pane-nav-options > div.nav-item.buttons {\n  cursor: default;\n  opacity: 1.0;\n}\n\n.nav-options .nav-item.buttons {\n  position: absolute;\n  top: 5px;\n  right: 0;\n  width: 7em;\n}\n\n/* ------ nav button stylings ------ */\n\n.nav-options .editor-nav-item,\n.nav-options .preview-nav-item {\n  font-weight: bold;\n  font-size: 16px;\n  opacity: 1.0;\n  color: #3887F3;\n}\n\n.editor-nav-item .icon,\n.preview-nav-item .icon {\n  display: inline-block;\n  width: 30px;\n  background-repeat: no-repeat;\n  background-position: center center;\n  margin-right: 1em;\n}\n\n.editor-nav-item .icon {\n  background-image: url(\"../img/editor-icon.png\");\n}\n\n.preview-nav-item .icon {\n  background-image: url(\"../img/preview-icon.png\");\n}\n\n.preview-nav-item .preview-title {\n  font-weight: bold;\n  display: none;\n}\n\n.preview-nav-item .preview-title:before {\n  content: ' for ';\n  font-weight: normal;\n}\n\n.editor-nav-item .pane-indicator,\n.preview-nav-item .pane-indicator {\n  position: absolute;\n  background-image: url(\"../img/indicator-arrow.png\");\n  background-repeat: no-repeat;\n  top: 38px;\n  left: 18px;\n  width: 25px;\n  height: 25px;\n}\n\n.undo-nav-item .icon {\n  display: inline-block;\n  width: 30px;\n\n  background-image: url(\"../img/undo-grey.png\");\n  background-repeat: no-repeat;\n  background-position: center center;\n}\n\n.undo-nav-item.enabled:hover .icon {\n  background-image: url(\"../img/undo-blue.png\");\n}\n\n.redo-nav-item .icon {\n  display: inline-block;\n  width: 30px;\n\n  background-image: url(\"../img/redo-grey.png\");\n  background-repeat: no-repeat;\n  background-position: center center;\n}\n\n.redo-nav-item.enabled:hover .icon {\n  background-image: url(\"../img/redo-blue.png\");\n}\n\n.text-nav-item .icon {\n  display: inline-block;\n  width: 40px;\n\n  background-image: url(\"../img/text-size.png\");\n  background-repeat: no-repeat;\n  background-position: center center;\n}\n\n.text-nav-item.enabled:hover .icon {\n  background-image: url(\"../img/text-size-blue.png\");\n}\n\n.text-size-options {\n  position: absolute;\n  display: none;\n  list-style: none;\n  text-align: left;\n  padding-top: 14px;\n}\n\n.text-nav-item ul {\n  margin: 0;\n  padding: 0;\n  padding-top: 35px;\n}\n\n.text-nav-item li {\n  background-color: white;\n  border: 1px solid C0C0C0;\n  border-top: none;\n  padding: 10px;\n\n  background-repeat: no-repeat;\n  background-position: 0 center;\n  padding-left: 40px;\n  width: 60px;\n\n  border: 1px solid #D6D6D6;\n  margin-top: -1px;\n}\n\n.text-size-options li.selected {\n  background-color: #F4F4F4;\n}\n\n.text-size-options li:hover {\n  background-color: rgb(200,235,255);\n}\n\n.text-size-options li[data-size=small] {\n  background-image: url(\"../img/text-size-small.png\");\n  font-size: 12px;\n}\n.text-size-options li[data-size=normal] {\n  background-image: url(\"../img/text-size-normal.png\");\n  font-size: 14px;\n}\n.text-size-options li[data-size=large] {\n  background-image: url(\"../img/text-size-large.png\");\n  font-size: 18px;\n}\n\n.hints-nav-item {\n  left: 100%;\n  margin-left: -100px;\n  position: absolute;\n  top: 11px;\n}\n\n.hints-nav-item .checkbox {\n  display: inline-block;\n  border: 1px solid grey;\n  border-radius: 2px;\n  background-color: white;\n  background-image: url(\"../img/checkbox-gradient.png\");\n  background-repeat: repeat-x;\n  background-position: left center;\n  color: black;\n  width: 10px;\n  height: 10px;\n  line-height: 10px;\n\n  font-family: OpenSymbolCropped;\n  font-size: 21px;\n  line-height: 9px;\n  vertical-align: middle;\n}\n\n.hints-nav-item .checkbox-label {\n  display: inline-block;\n  vertical-align: middle;\n}\n\n.hints-nav-item .checkbox.off {\n  color: transparent;\n}\n\n\n/* ------ CONTENT AREA ------ */\n\n.friendlycode-panes {\n  position: absolute;\n  top: 30px;       /* corresponds to .friendlycode-toolbar.height */\n  left: 0;\n  right: 0;\n  bottom: 0;    /* corresponds to 20 + footer.height */\n}\n\ndiv.editor-actions {\n  visibility: visible;\n  position: absolute;\n  right: 20px;\n  top: 20px;\n}\n\n.source-code {\n  background-color: #F9F9F9;\n  z-index: 1;\n}\n\n.source-code, .preview-holder {\n  width: 50%;\n  -moz-box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n  position: absolute;\n  bottom: 0;\n  top: 10px;\n}\n\n.preview-holder {\n  right: 0;\n  border-left: 1px solid #D6D6D6;\n  background: white;\n  background-color: #F9F9F9;\n  padding: 10px;\n}\n\n.preview-holder iframe {\n  border: 1px solid #D6D6D6;\n  width: 100%;\n  height: 100%;\n  background-color: white;\n}\n\n.source-code .CodeMirror, .source-code .CodeMirror-scroll {\n  height: 100%;\n  overflow: auto;\n}\n\n.tipsy.friendlycode-base {\n  /* Make tipsy tooltips slightly larger than the default. */\n  font-size: 12px;\n}\n\n.friendlycode-base .breadcrumbs {\n  position: relative;\n  display: inline-block;\n  width: 1px;\n  height: 100%;\n  margin: 0;\n  border-right: 1px solid #848484;\n}\n.friendlycode-base .breadcrumbs:after,\n.friendlycode-base .breadcrumbs:before {\n  left: 100%;\n  border: solid transparent;\n  content: \" \";\n  height: 0;\n  width: 0;\n  position: absolute;\n  pointer-events: none;\n}\n.friendlycode-base .breadcrumbs:after {\n  border-left-color: #fff; \n  border-width: 5px;\n  top: 50%;\n  margin-top: -5px;\n}\n.friendlycode-base .breadcrumbs:before {\n  border-left-color: #848484;\n  border-width: 7px;\n  top: 50%;\n  margin-top: -7px;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/css/errorhelp.css",
    "content": "/* ------ ERRORS AND HELP MESSAGE STYLING ------ */\r\n\r\nhtml .flipped {\r\n  margin-top: -180px;\r\n}\r\n\r\nhtml .help:not(.flipped) .up-arrow,\r\nhtml .error:not(.flipped) .up-arrow {\r\n  display: block;\r\n}\r\n\r\nhtml .flipped .down-arrow {\r\n  display: block;\r\n}\r\n\r\n.error,\r\n.help {\r\n  display: block;\r\n  position: absolute;\r\n  font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\r\n\r\n  /* Force the left side of the message to be on the left side of the\r\n   * editing area. CodeMirror.addWidget() will set the left side on the\r\n   * style attribute of the widget to be where the relevant character is,\r\n   * and we want to override that. */\r\n  left: 0 !important;\r\n\r\n  width: 97%;\r\n  height: 140px;\r\n  background-color: #FDFDFD;\r\n  margin: 10px;\r\n  margin-top: 20px;\r\n  padding: 4px;\r\n  white-space: normal;\r\n\r\n  border: 1px solid rgb(193,193,193);\r\n  -webkit-box-shadow: 0 0 5px 1px #C1C1C1;\r\n  box-shadow: 0 0 5px 1px #C1C1C1;\r\n\r\n  z-index: 1000;\r\n\r\n  -moz-box-sizing: border-box;\r\n  -webkit-box-sizing: border-box;\r\n  box-sizing: border-box;\r\n}\r\n\r\n.error p {\r\n  display: inline;\r\n}\r\n\r\n.error .icon,\r\n.help .icon {\r\n  display: inline-block;\r\n  width: 20%;\r\n  height: 100%;\r\n  border-right: 1px solid #C0C0C0;\r\n  text-align: center;\r\n  vertical-align: middle;\r\n\r\n  background-position: center center;\r\n  background-repeat: no-repeat;\r\n  -moz-box-sizing: border-box;\r\n  -webkit-box-sizing: border-box;\r\n  box-sizing: border-box;\r\n}\r\n\r\n.error .content,\r\n.help .content {\r\n  display: inline-block;\r\n  width: 78%;\r\n  height: 90%;\r\n  vertical-align: top;\r\n  overflow: auto;\r\n  padding: 5px;\r\n  -moz-box-sizing: border-box;\r\n  -webkit-box-sizing: border-box;\r\n  box-sizing: border-box;\r\n}\r\n\r\n.error .icon {\r\n  background-image: url(\"../img/error.png\");\r\n}\r\n.help .icon {\r\n  background-image: url(\"../img/help.png\");\r\n}\r\n\r\n.CodeMirror-gutter-text .gutter-highlight-error {\r\n  color: white;\r\n  background: #FF2A04;\r\n}\r\n\r\n.error a,\r\n.error strong,\r\n.error code,\r\n.error em[data-highlight] {\r\n  color: #FF2A04;\r\n}\r\n\r\n.CodeMirror-gutter-text .gutter-highlight-help {\r\n  color: white;\r\n  background: #FF9933;\r\n}\r\n\r\n.help a,\r\n.help strong,\r\n.help code,\r\n.help em[data-highlight] {\r\n  color: #FF9933;\r\n}\r\n\r\n.error a,\r\n.help a  {\r\n  font-weight: bold;\r\n}\r\n\r\n.error strong,\r\n.help strong {\r\n  font-weight: bold;\r\n  font-size: 110%;\r\n}\r\n\r\n.error code,\r\n.help code {\r\n  font-weight: bold;\r\n  font-size: 110%;\r\n}\r\n\r\n.error em.highlight-1 {\r\n  font-style: normal;\r\n  text-decoration: underline;\r\n  cursor: pointer;\r\n}\r\n\r\n.CodeMirror span.highlight-1,\r\n.CodeMirror span.highlight-2 {\r\n  background: rgba(255, 0, 0, 0.05) !important;\r\n}\r\n\r\n.CodeMirror span.cursor-help-highlight,\r\n.cursor-help-highlight {\r\n  background-color: rgba(255, 160, 0, 0.2);\r\n}\r\n\r\n.error em.highlight-2 {\r\n  text-decoration: underline;\r\n  cursor: pointer;\r\n  font-style: normal;\r\n}\r\n\r\n.CodeMirror .cursor-pointer {\r\n  display: absolute;\r\n  font-size: 40px;\r\n  padding-top: 0px;\r\n  font-weight: bold;\r\n  z-index: 2000;\r\n  color: #FF2A04;\r\n  text-shadow:\r\n    -2px -2px 0 white,\r\n    2px -2px 0 white,\r\n    -2px 2px 0 white,\r\n    2px 2px 0 white;\r\n}\r\n\r\n.cursor-pointer:before {\r\n  content: '▲';\r\n}\r\n\r\n.error .down-arrow,\r\n.help .down-arrow,\r\n.error .up-arrow,\r\n.help .up-arrow {\r\n  position: absolute;\r\n  display: none;\r\n  width: 40px;\r\n  height: 23px;\r\n  background-repeat: no-repeat;\r\n  background-position: center center;\r\n  padding-left: 20px;\r\n}\r\n\r\n.error .down-arrow,\r\n.help .down-arrow {\r\n  top: 138px;\r\n  background-image: url(\"../img/hint-down-arrow.png\");\r\n}\r\n\r\n.error .up-arrow,\r\n.help .up-arrow {\r\n  top: -22px;\r\n  background-image: url(\"../img/hint-up-arrow.png\");\r\n}\r\n\r\n.hint-marker-positioning {\r\n  left: auto !important; /* CodeMirror will set this value, but we don't want it set! */\r\n  right: 1em;\r\n  background-color: transparent;\r\n\r\n  margin: 0px;\r\n  padding: 0px;\r\n  cursor: pointer;\r\n\r\n  width: 1.4em;\r\n  height: 1.4em;\r\n  margin-top: -1.3em;\r\n\r\n  background-size: 100% 100%;\r\n}\r\n\r\n.hint-marker-help {\r\n  background-image: url(\"../img/questionmark.png\");\r\n}\r\n\r\n.hint-marker-error {\r\n  background-image: url(\"../img/explanationpt.png\");\r\n}\r\n\r\nsvg.gutter-pointer {\r\n  z-index: 100;\r\n}\r\n\r\nsvg.gutter-pointer.gutter-highlight-error polygon {\r\n  fill: #FF2A04;\r\n}\r\n\r\nsvg.gutter-pointer.gutter-highlight-help polygon {\r\n  fill: #FF9933;\r\n}\r\n"
  },
  {
    "path": "site/examples/friendlycode/css/friendlycode.css",
    "content": "/* \n * This stylesheet is only intended for development purposes,\n * due to the inefficiency of @import [1]. For production use, this\n * file should be a raw concatenation of all the @import rules below.\n *\n * [1] http://www.stevesouders.com/blog/2009/04/09/dont-use-import/\n */\n\n@import url(../codemirror2/lib/codemirror.css);\n\n@import url(jsbin-codemirror-theme.css);\n@import url(tipsy.css);\n@import url(ubuntumono/stylesheet.css);\n@import url(opensymbolcropped/stylesheet.css);\n@import url(opensans/stylesheet.css);\n@import url(editor.css);\n@import url(errorhelp.css);\n@import url(modals.css);\n@import url(buttons.css);\n\n"
  },
  {
    "path": "site/examples/friendlycode/css/jsbin-codemirror-theme.css",
    "content": "/* jsbin - based on web inspector */\n.cm-s-jsbin span.cm-keyword {color: #AA0D91;}\n.cm-s-jsbin span.cm-atom {color: #219;}\n.cm-s-jsbin span.cm-number {color: #164;}\n.cm-s-jsbin span.cm-def {color: #00f;}\n.cm-s-jsbin span.cm-variable {color: black;}\n.cm-s-jsbin span.cm-variable-2 {color: #05a;}\n.cm-s-jsbin span.cm-variable-3 {color: #0a5;}\n.cm-s-jsbin span.cm-property {color: black;}\n.cm-s-jsbin span.cm-operator {color: black;}\n.cm-s-jsbin span.cm-comment {color: #236E25;}\n.cm-s-jsbin span.cm-string {color: #C41A16;}\n.cm-s-jsbin span.cm-meta {color: #555;}\n.cm-s-jsbin span.cm-error {color: #f00;}\n.cm-s-jsbin span.cm-qualifier {color: #555;}\n.cm-s-jsbin span.cm-builtin {color: #30a;}\n.cm-s-jsbin span.cm-bracket {color: #cc7;}\n.cm-s-jsbin span.cm-tag {color: #881280;}\n.cm-s-jsbin span.cm-attribute {color: #994500;}\n\n.CodeMirror {\n  font-family: 'Ubuntu Mono', monospace;\n  font-weight: 200;\n  font-size: 14px;\n}\n\n.CodeMirror .CodeMirror-lines {\n  color: #333;\n  font-size: 14px;\n  line-height: 15.75px;\n}\n\n.CodeMirror textarea {\n  font-family: 'Ubuntu Mono', monospace;\n  font-size: 14px;\n  line-height: 15.75px;\n}\n\n.CodeMirror-gutter {\n  background-color: #EEEEEE !important;\n}\n\n.CodeMirror-gutter-text {\n  color: #A9A9A9;\n  font-size: 12px;\n  line-height: 15.75px;\n  padding-left: 0;\n}\n\n.cm-s-jsbin span.cm-meta {\n  color: #999999;\n}\n\n.cm-s-jsbin span.cm-comment {\n  color: #333;\n  font-style: italic;\n  font-weight: bold;\n  \n  /* This needs to be a little less than the standard line-height to align on\n     multi-line wrapped content. */\n  line-height: 15.75px;\n}\n\n.CodeMirror-wrap .CodeMirror-scroll {\n  overflow: hidden;\n}\n\n.CodeMirror-scroll.cm-s-jsbin {\n  height: 100%;\n}\n\n.cm-tag {\n  color: #3A85FF !important;\n}\n\n.CodeMirror-lines .CodeMirror-line-highlight {\n  background-color: #EEEEEE;\n  margin-left: -3em;\n  padding-left: 3em;\n}\n\n.CodeMirror-gutter {\n  opacity: 1 !important;\n}\n.CodeMirror span.preview-to-editor-highlight {\n  background-color: rgba(50,100,255,0.3);\n}\n\n/* Text size: small */\n\n.CodeMirror[data-size=\"small\"] div,\n.CodeMirror[data-size=\"small\"] pre {\n  font-size: 12px;\n  line-height: 13.5px;\n}\n\n.CodeMirror[data-size=\"small\"] .cm-s-jsbin span.cm-comment {\n  font-size: 12px;\n  line-height: 12.5px;\n}\n\n/* Text size: normal */\n\n.CodeMirror[data-size=\"normal\"] div,\n.CodeMirror[data-size=\"normal\"] pre {\n  font-size: 14px;\n  line-height: 15.75px;\n}\n\n.CodeMirror[data-size=\"normal\"] .cm-s-jsbin span.cm-comment {\n  font-size: 14px;\n  line-height: 14.75px;\n}\n\n/* Text size: large */\n\n.CodeMirror[data-size=\"large\"] div,\n.CodeMirror[data-size=\"large\"] pre {\n  font-size: 18px;\n  line-height: 20.25px;\n}\n\n.CodeMirror[data-size=\"large\"] .cm-s-jsbin span.cm-comment {\n  font-size: 18px;\n  line-height: 19.25px;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/css/modals.css",
    "content": "/**\n * Styling for webpagemaker editor modal dialogs\n */\n\n.modal-overlay {\n  z-index: 10000;\n  display: block;\n  position: absolute;\n  top: 0;\n  left: 0;\n  background-color: rgba(0,0,0,0.2); \n  height: 100%; \n  width: 100%;\n}\n\n.thimble-error {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  width: 400px;\n  height: 200px;\n  margin-top: -125px;\n  margin-left: -200px;\n  background-color: white;\n}\n\n.thimble-error .thimble-title {\n  position: relative;\n  top: 0px;\n  left: 0px;\n  padding-top: 0.5em;\n  height: 1.5em;\n  border: 1px solid #C0C0C0;\n}\n\n.thimble-modal-menu {\n  position: absolute;\n  margin-top: 22px;\n  margin-left: 18px;\n  width: 425px;\n  height: 145px;\n  border: 1px solid #C0C0C0;\n}\n\n.thimble-question-bar {\n  background-color: #505050;\n}\n\n.thimble-question-bar .thimble-title {\n  color: white;\n  background: inherit;\n  font-size: 18px;\n  text-align: center;\n}\n\n.thimble-grey-bar {\n  background-color: #F7F7F7;\n}\n\n.thimble-branding {\n  position: relative;\n  display: block;\n  width: 30px;\n  height: 30px;\n  top: -15px;\n  left: 365px;\n  background-color: inherit;\n\n  -moz-transform: rotate(45deg);\n  -webkit-transform: rotate(45deg);\n  -o-transform: rotate(45deg);\n  -ms-transform: rotate(45deg);\n  transform: rotate(45deg); \n  \n  border: 1px solid #C0C0C0;\n  border-width: 1px 0 0 1px;\n  margin-bottom: 1.5em;\n}\n\n/* make the top padding 'disappear' for greybar content */\n.thimble-grey-bar .thimble-branding {\n  position: absolute;\n}\n\n.modal-close-button {\n  background-image: url(\"../img/modal-close-button.png\");\n  background-position: center center;\n  background-repeat: no-repeat;\n  cursor: pointer;\n  height: 40px;\n  position: absolute;\n  right: 25px;\n  top: 5px;\n  width: 40px;\n  z-index: 3;\n}\n\n.thimble-grey-bar .modal-close-button {\n  top: 0;\n}\n\n.thimble-menu-content {\n  background-color: white;\n  width: 100%;\n}\n\n.thimble-title {\n  position: relative;\n  top: -2em;\n  text-align: left;\n  padding-left: 5px;\n\n  font-weight: bold;\n  font-size: 14px;\n\n  background-color: #3A84FC;\n  \n  color: white;\n}\n\n.thimble-grey-bar .thimble-title {\n  top: 0;\n  text-align: left;\n  padding: 1em 1em 0.5em 0;\n  padding-left: 0;\n}\n\n\n.thimble-grey-bar .thimble-title:before {\n  content: \"▾ \";\n  padding-left: 1em;\n}\n\n.confirm-dialog .thimble-title:before {\n  content: \"\" !important;\n}\n\n.collapsed .thimble-title {\n  color: white;\n  background-color: gray;\n  vertical-align: middle;\n  cursor: pointer;\n}\n\n.collapsed .thimble-title:hover {\n  background-color: #505050;\n}\n\n.thimble-url-box {\n  background-color: #FFFFFF;\n  color: blue;\n  height: 25px;\n  margin: 10px auto 1em;\n  padding-left: 1em;\n  padding-top: 5px;\n  width: 370px;\n  overflow: hidden;\n}\n\n.thimble-url-box a {\n  color: #50A5F8;\n}\n\n.thimble-url-box a:hover {\n  color: blue;\n}\n\n.thimble-additionals {\n  color: #222;\n  text-align: left;\n  position: relative;\n  padding: 2px 10px;\n  font-size: 14px;\n}\n\n.thimble-additionals ul {\n  list-style: none;\n  text-align: center;\n  margin: 1em 0;\n  padding: 0;\n}\n\n.thimble-additionals ul li {\n  display: table-cell;\n  vertical-align: middle;\n  padding: 0 5px;\n}\n\n.collapsed .thimble-title:before {\n  content: \"▸ \";\n}\n\n.accordion-content {\n  overflow: hidden;\n  -moz-transition: height 0.5s;\n  -webkit-transition: height 0.5s;\n  -o-transition: height 0.5s;\n}\n\n.collapsed .accordion-content {\n  height: 0;\n}\n\ndiv.accordion:not(.collapsed) .accordion-content {\n  height: 50px;\n}\n\n.thimble-grey-bar .thimble-additionals {\n  padding: 0 1em;\n}\n\n.thimble-additionals a {\n  text-decoration: none;\n  color: #3F9A31;\n}\n\n.thimble-additionals a:hover {\n  color: #236819;\n}\n\n.confirm-dialog .public-warning {\n  text-align: center;\n  padding-bottom: 1em;\n}\n\n.confirm-dialog .error-warning,\n.confirm-dialog .development-note {\n  display: none;\n}\n\nhtml.deployment-type-development .confirm-dialog .development-note {\n  display: block;\n  padding-bottom: 1em;\n  color: gray;\n  font-style: italic;\n}\n\n.confirm-dialog.has-errors .error-warning {\n  display: block;\n  padding-bottom: 1em;\n  color: red;\n}\n\n.confirmation-buttons {\n  text-align: center;\n  margin-top: 1em;\n  margin-bottom: 0.75em;\n  height: 2em;\n}\n\n.confirmation-button {\n  background-repeat: no-repeat;\n  color: white;\n  cursor: pointer;\n  display: inline-block;\n  font-family: Arial;\n  font-weight: 700;\n  font-size: 14px;\n  height: 30px;\n  padding-top: 7px;\n  text-indent: -20px;\n  width: 60px;\n  margin: 0 1em;\n  opacity: 0.75;\n  -moz-transition: opacity 0.5s;\n  -webkit-transition: opacity 0.5s;\n  -o-transition: opacity 0.5s;\n}\n\n.confirmation-button:hover {\n  opacity: 1.0;\n}\n\n.confirmation-button.yes-button {\n  background-image: url(\"../img/yes.png\");\n} \n\n.confirmation-button.no-button {\n  background-image: url(\"../img/no.png\");\n}\n\n.accordion {\n  background-color:inherit;\n}\n\n.accordion + .accordion {\n  border-top: 1px solid #D6D6D6;\n}\n\n.publish-dialog.is-publishing .thimble-url-box {\n  background-image: url(../img/throbber.gif);\n  background-repeat: no-repeat;\n  background-position: 8px 8px;\n}\n\n.publish-dialog.is-publishing .thimble-url-box a {\n  font-size: 0;\n}\n\n.publish-dialog.is-publishing .share-result .thimble-additionals {\n  font-size: 0;\n  width: 100%;\n  height: 100%;\n  background-image: url(../img/throbber.gif);\n  background-repeat: no-repeat;\n  background-position: 50% 50%;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/css/modals_full_screen.css",
    "content": "/**\n * Styling for webpagemaker editor modal dialogs\n */\n\n.modal-overlay {\n  z-index: 2000;\n  display: block;\n  position: absolute;\n  top: 0px;\n  left: 0px;\n  background-color: rgba(0,0,0,0.45); \n  height: 100%; \n  width: 100%;\n}\n\n.thimble-modal-menu {\n  position: absolute;\n  top: 35%;\n  left: 50%;\n  width: 650px;\n  margin-left: -325px;\n  height: 210px;\n  background-color: #FDFDFD;\n  border: 1px solid #C0C0C0;\n}\n\n.thimble-branding {\n  display: inline-block;\n  width: 115px;\n  height: 210px;\n  background-image: url(\"../img/webmaker-logo.png\");\n  background-position: 50% 40%;\n  background-repeat: no-repeat;\n  border-right: 1px solid #C0C0C0;\n}\n\n.thimble-menu-content {\n  display: inline-block;\n  vertical-align: top;\n  height: 120px; /* 210 - 2 * 10 */\n  width: 405px;\n  margin: 50px;\n  /*\n  border: 1px solid black;\n  */\n}\n\n.thimble-title{\n  color: #4385F6;\n}\n\n.thimble-url-box {\n  background-color: #FFFFFF;\n  color: blue;\n  height: 30px;\n  width: 350px;\n  padding-top: 10px;\n  padding-left: 1em;\n  margin: 1em 0px;\n}\n\n.thimble-url-box a {\n  color: #50A5F8;\n}\n\n.thimble-url-box a:hover {\n  color: blue;\n}\n\n.thimble-additionals {\n  color: #222;\n  text-align: justify;\n}\n\n.thimble-additionals a {\n  text-decoration: none;\n  color: #3F9A31;\n}\n\n.thimble-additionals a:hover {\n  color: #236819;\n}\n\n.confirmation-buttons {\n  text-align: center;\n  margin-top: 1em;\n}\n\n.confirmation-button {\n  display: inline;\n  height: 30px;\n  border-radius: 10px;\n  padding: 5px 15px;\n  margin: auto;\n  color: white;\n  margin: 0px 1em;\n}\n\n.confirmation-button.yes-button {\n  background-color: #1DBF84;\n} \n\n.confirmation-button.no-button {\n  background-color: #F14D2A;\n}\n\n.confirmation-button .mark {\n  position: relative;\n  top: 0px;\n  display: inline-block;\n  width: 18px;\n  height: 18px;\n  border-radius: 10px;\n  background-color: rgba(0,0,0,0.4);\n  color: white;\n  margin-right: -9px;\n  background-position: 9px 5px;\n  background-repeat: no-repeat;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/css/opensans/stylesheet.css",
    "content": "/* The font family/weight/style of these rules is taken from Tabzilla's CSS:\n   https://raw.github.com/mozilla/tabzilla/master/media/css/tabzilla.css\n   \n   This is done to ensure that smart browsers won't load two separate\n   sets of fonts if friendlycode is used on the same page as Tabzilla. */\n\n@font-face {\n    font-family: 'Open Sans';\n    src: url('OpenSans-Regular-webfont.eot');\n    src: url('OpenSans-Regular-webfont.eot?#iefix') format('embedded-opentype'),\n         url('OpenSans-Regular-webfont.woff') format('woff'),\n         url('OpenSans-Regular-webfont.ttf') format('truetype'),\n         url('OpenSans-Regular-webfont.svg#OpenSansRegular') format('svg');\n    font-weight: normal;\n    font-style: normal;\n}\n\n@font-face {\n    font-family: 'Open Sans';\n    src: url('OpenSans-Semibold-webfont.eot');\n    src: url('OpenSans-Semibold-webfont.eot?#iefix') format('embedded-opentype'),\n         url('OpenSans-Semibold-webfont.woff') format('woff'),\n         url('OpenSans-Semibold-webfont.ttf') format('truetype'),\n         url('OpenSans-Semibold-webfont.svg#OpenSansSemibold') format('svg');\n    font-weight: bold;\n    font-style: normal;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/css/opensymbolcropped/stylesheet.css",
    "content": "/* \n  Crop of the Symbol set of the \"OpenSymbol\" font,\n  from the LibreOffice project, which is licensed\n  under LGPLv3+/GPLv3+/MPL1.1+\n\n  Consequently, these files are licensed under the\n  same terms.\n\n*/\n@font-face {\n    font-family: 'OpenSymbolCropped';\n    src: url('opensymbolcropped.eot');\n    src: url('opensymbolcropped.eot?#iefix') format('embedded-opentype'),\n         url('opensymbolcropped.woff') format('woff'),\n         url('opensymbolcropped.ttf') format('truetype');\n    font-weight: normal;\n    font-style: normal;\n}"
  },
  {
    "path": "site/examples/friendlycode/css/tipsy.css",
    "content": ".tipsy { font-size: 10px; position: absolute; padding: 5px; z-index: 100000; }\n  .tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 5px 8px 4px 8px; text-align: center; }\n\n  /* Rounded corners */\n  .tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }\n  \n  /* Uncomment for shadow */\n  /*.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }*/\n  \n  .tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; }\n  \n  /* Rules to colour arrows */\n  .tipsy-arrow-n { border-bottom-color: #000; }\n  .tipsy-arrow-s { border-top-color: #000; }\n  .tipsy-arrow-e { border-left-color: #000; }\n  .tipsy-arrow-w { border-right-color: #000; }\n  \n\t.tipsy-n .tipsy-arrow { top: 0; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }\n    .tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}\n    .tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none;  border-left-color: transparent; border-right-color: transparent;}\n  .tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none;  border-left-color: transparent; border-right-color: transparent; }\n    .tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none;  border-left-color: transparent; border-right-color: transparent; }\n    .tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }\n  .tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }\n  .tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }\n"
  },
  {
    "path": "site/examples/friendlycode/css/ubuntumono/stylesheet.css",
    "content": "/*\n    http://font.ubuntu.com\n*/\n\n@font-face {\n    font-family: 'Ubuntu Mono';\n    src: url('ubuntumono-r.eot');\n    src: url('ubuntumono-r.eot?#iefix') format('embedded-opentype'),\n         url('ubuntumono-r.woff') format('woff'),\n         url('ubuntumono-r.ttf') format('truetype');\n    font-weight: normal;\n    font-style: normal;\n}\n\n@font-face {\n    font-family: 'Ubuntu Mono';\n    src: url('ubuntumono-b.eot');\n    src: url('ubuntumono-b.eot?#iefix') format('embedded-opentype'),\n         url('ubuntumono-b.woff') format('woff'),\n         url('ubuntumono-b.ttf') format('truetype');\n    font-weight: bold;\n    font-style: normal;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/examples/alternate-publisher.html",
    "content": "<!DOCTYPE html>\n<html class=\"deployment-type-development\">\n  <head>\n    <meta charset=\"utf-8\">\n    <base target=\"_blank\">\n\n    <title>Alternate Publisher Friendlycode Editor</title>\n    <link rel=\"stylesheet\" href=\"../css/friendlycode.css\">\n  </head>\n  <body style=\"margin: 0\">\n    <div id=\"bare-fc-holder\" class=\"friendlycode-loading\"></div>\n\n    <script src=\"../js/require-config.js\"></script>\n    <script src=\"../js/require.min.js\"></script>\n    <script>\n    // Alternate publisher implementation that publishes to a hackpub\n    // endpoint. For more information, see:\n    // \n    //   https://github.com/hackasaurus/hackpub\n    //\n    // Note also that the Amazon S3 bucket hackpub publishes to must\n    // be configured with a CORS configuration that allows for cross-origin\n    // GET requests, e.g.:\n    //\n    //   <CORSConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">\n    //     <CORSRule>\n    //       <AllowedOrigin>*</AllowedOrigin>\n    //       <AllowedMethod>GET</AllowedMethod>\n    //     </CORSRule>\n    //   </CORSConfiguration>\n     \n    define(\"hackpub\", [\"jquery\"], function($) {\n      return function Hackpub(options) {\n        return {\n          loadCode: function(path, cb) {\n            var url = options.publishURL + path;\n            $.ajax({\n              type: \"GET\",\n              url: url,\n              dataType: 'text',\n              error: function(req) {\n                cb(req);\n              },\n              success: function(html) {\n                cb(null, html, url);\n              }\n            });\n          },\n          saveCode: function(data, originalURL, cb) {\n            $.ajax({\n              type: \"POST\",\n              url: options.hackpubURL + \"/publish\",\n              data: {\n                'html': data,\n                'original-url': originalURL\n              },\n              dataType: 'json',\n              error: function(req) {\n                cb(req);\n              },\n              success: function(result) {\n                var url = result['published-url'];\n                var path = '/' + url.match(/\\/([A-Za-z0-9]+)$/)[1];\n                cb(null, {path: path, url: options.publishURL + path});\n              }\n            });\n          }\n        };\n      };\n    });\n    </script>\n    <script>\n    require([\n      \"jquery\",\n      \"friendlycode\",\n      \"hackpub\"\n    ], function($, FriendlycodeEditor, Hackpub) {\n      return FriendlycodeEditor({\n        allowJS: true,\n        publisher: Hackpub({\n          hackpubURL: \"http://hackpub.hackasaurus.org\",\n          publishURL: \"http://poof.hksr.us\"\n        }),\n        container: $(\"#bare-fc-holder\")\n      });\n    });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/friendlycode/examples/bare-optimized.html",
    "content": "<!DOCTYPE html>\n<html class=\"deployment-type-development\">\n  <head>\n    <meta charset=\"utf-8\">\n    <base target=\"_blank\">\n\n    <title>Optimized Barebones Friendlycode Editor</title>\n    <link rel=\"stylesheet\" href=\"../css/friendlycode-built.css\">\n  </head>\n  <body style=\"margin: 0\">\n    <div id=\"bare-fc-holder\" class=\"friendlycode-loading\"></div>\n\n    <script src=\"../js/require.min.js\"></script>\n    <script src=\"../js/friendlycode-built.js\"\n            onerror=\"alert('please run build-require.js!');\"></script>\n    <script>\n    require([\"jquery\", \"friendlycode\"], function($, FriendlycodeEditor) {\n      return FriendlycodeEditor({\n        publishURL: \"https://webpagemaker-dev.allizom.org\",\n        container: $(\"#bare-fc-holder\")\n      });\n    });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/friendlycode/examples/bare.html",
    "content": "<!DOCTYPE html>\n<html class=\"deployment-type-development\">\n  <head>\n    <meta charset=\"utf-8\">\n    <base target=\"_blank\">\n\n    <title>Barebones Friendlycode Editor</title>\n    <link rel=\"stylesheet\" href=\"../css/friendlycode.css\">\n  </head>\n  <body style=\"margin: 0\">\n    <div id=\"bare-fc-holder\" class=\"friendlycode-loading\"></div>\n\n    <script src=\"../js/require-config.js\"></script>\n    <script src=\"../js/require.min.js\"></script>\n    <script>\n    require([\"jquery\", \"friendlycode\"], function($, FriendlycodeEditor) {\n      return FriendlycodeEditor({\n        publishURL: \"https://webpagemaker-dev.allizom.org\",\n        container: $(\"#bare-fc-holder\")\n      });\n    });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/friendlycode/examples/editor-only.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <base target=\"_blank\">\n\n    <title>Editor Only</title>\n    <link rel=\"stylesheet\" href=\"../css/friendlycode.css\">\n  </head>\n  <body style=\"margin: 0\">\n    <div id=\"editor\" class=\"friendlycode-loading\"></div>\n\n    <script src=\"../js/require-config.js\"></script>\n    <script src=\"../js/require.min.js\"></script>\n    <script>\n    require([\n      \"jquery\",\n      \"fc/ui/editor\"\n    ], function($, Editor) {\n      var editor = Editor({\n        container: $(\"#editor\"),\n        value: \"<p>Just an editor widget, no publishing.</p>\"\n      });\n      editor.panes.codeMirror.focus();\n    });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/friendlycode/index.html",
    "content": "<!DOCTYPE html>\n<html class=\"deployment-type-development\">\n  <head>\n    <meta charset=\"utf-8\">\n    <base target=\"_blank\">\n\n    <title>Barebones Friendlycode Editor</title>\n    <link rel=\"stylesheet\" href=\"css/friendlycode.css\">\n    <style type=\"text/css\" media=\"screen\">\n      /*reset Twitter Bootstrap*/\n      @media screen {\n        * {\n          -webkit-box-sizing: content-box !important;\n          -moz-box-sizing: content-box !important;\n          box-sizing: content-box !important;\n        }\n      }\n    </style>\n  </head>\n  <body style=\"margin: 0\">\n    <div id=\"bare-fc-holder\" class=\"friendlycode-loading\"></div>\n\n    <script src=\"js/require-config.js\"></script>\n    <script src=\"js/require.min.js\"></script>\n    <script>\n    require.baseUrl = \"js\";\n    // We don't want TogetherJS to try to load until after FriendlyCode is started\n    // up:\n    window._TogetherJSLoads = [];\n    window._TogetherJSOnLoad = function (callback) {\n      window._TogetherJSLoads.push(callback);\n    };\n    require([\"jquery\", \"friendlycode\"], function($, FriendlycodeEditor) {\n      var result = FriendlycodeEditor({\n        publishURL: \"https://webpagemaker-dev.allizom.org\",\n        container: $(\"#bare-fc-holder\")\n      });\n      result.ready.then(function () {\n        var el = $(\".publish-button\");\n        var newButton = $('<div class=\"wm-button wm-button-blue short\" title=\"Call The TogetherJS\">Collaborate</div>');\n        newButton.click(TogetherJS);\n        el.before(newButton);\n        window._TogetherJSLoads.forEach(function (callback) {\n          callback();\n        });\n      });\n      return result;\n    });\n    </script>\n    <script>\n      TogetherJSConfig_findRoom = {prefix: \"togetherjsfriendly\", max: 5};\n      TogetherJSConfig_suppressJoinConfirmation = true;\n      TogetherJSConfig_storagePrefix = \"tjs_friendlycode\";\n    </script>\n    <script src=\"/togetherjs.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/friendlycode/js/backbone-events.js",
    "content": "// This simple module is just a helper that allows us to go from this code:\n//\n//   _.extend(object, Backbone.Events)\n//\n// to this code:\n//\n//   BackboneEvents.mixin(object)\n// \n// This is useful in two ways:\n//\n// * A bunch of our modules only import underscore and backbone for\n//   the sole purpose of using Backbone.Events. Importing one module\n//   and using a one-argument function call is easier than importing two\n//   modules and using a two-argument function call.\n//\n// * If we \"standardize\" on the Backbone.Events interface and module name,\n//   it becomes easier for AMD modules from other projects to declare it as\n//   a dependency. AMD-based projects that use backbone and underscore\n//   can use a file like this one to provide backbone-events, while\n//   smaller projects that don't need the full power of underscore and\n//   backbone can provide a more lightweight alternative.\n\ndefine([\"underscore\", \"backbone\"], function(_, Backbone) {\n  return {\n    mixin: function(target) {\n      return _.extend(target, Backbone.Events);\n    }\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/current-page-manager.js",
    "content": "define(function() {\n  function defaultLoadPage(window) {\n    // We don't currently support dynamically changing the URL\n    // without a full page reload, unfortunately, so just trigger a\n    // reload if the user clicked the 'back' button after we pushed\n    // a new URL to it.    \n    return function() { window.location.reload() };\n  }\n  \n  return function CurrentPageManager(options) {\n    var self = {},\n        window = options.window,\n        pageToLoad = options.currentPage,\n        loadPage = options.loadPage || defaultLoadPage(window),\n        supportsPushState = window.history.pushState ? true : false;\n    \n    if (supportsPushState)\n      window.history.replaceState({pageToLoad: pageToLoad}, \"\",\n                                  window.location.href);\n\n    function getPageFromHash() {\n      var pageToLoad = window.location.hash.slice(1);\n      if (pageToLoad.indexOf(\"&\") != -1) {\n        pageToLoad = pageToLoad.slice(0, pageToLoad.indexOf(\"&\"));\n      }\n      if (! pageToLoad) {\n        return null;\n      }\n      return pageToLoad;\n    }\n    \n    // If a URL hash is specified, it should override anything provided by\n    // a server.\n    if (window.location.hash.slice(1))\n      pageToLoad = getPageFromHash();\n    \n    window.addEventListener(\"hashchange\", function(event) {\n      var newPageToLoad = getPageFromHash();\n      console.log(\"Loading page\", newPageToLoad);\n      if (newPageToLoad != pageToLoad) {\n        pageToLoad = newPageToLoad;\n        loadPage(pageToLoad);\n      }\n    }, false);\n\n    if (supportsPushState)\n      window.addEventListener(\"popstate\", function(event) {\n        // For some reason Webkit is sending a spurious popstate with\n        // state == null on page load, so we want to check that it's\n        // non-null first (see #39).\n        if (event.state && event.state.pageToLoad != pageToLoad) {\n          pageToLoad = event.state.pageToLoad;\n          loadPage(pageToLoad);\n        }\n      }, false);\n    \n    self.currentPage = function() { return pageToLoad; };\n    self.changePage = function(page, url) {\n      pageToLoad = page;\n      if (supportsPushState) {\n        window.history.pushState({pageToLoad: page}, \"\", url);\n      } else {\n        var rest = \"\";\n        if (window.location.hash.indexOf(\"&\") != -1) {\n          rest = window.location.hash.substr(window.location.indexOf(\"&\"));\n        }\n        window.location.hash = \"#\" + page + rest;\n      }\n    };\n    \n    return self;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/hacktionary-data.js",
    "content": "\"use strict\";\n\n// Data here is ultimately scraped from MDN:\n// https://github.com/toolness/hacktionary\ndefine(function() { return {\n  \"short-element-descriptions\": {\n    \"a\": \"anchor or hyperlink\",\n    \"abbr\": \"abbreviation\",\n    \"area\": \"image-map hyperlink\",\n    \"article\": \"independent article\",\n    \"aside\": \"tangential content\",\n    \"audio\": \"embedded audio stream\",\n    \"b\": \"bold\",\n    \"base\": \"base URL\",\n    \"bdi\": \"bi-directional text formatting\",\n    \"bdo\": \"bi-directional override\",\n    \"bgsound\": \"background sound\",\n    \"blockquote\": \"block quotation\",\n    \"body\": \"document body\",\n    \"br\": \"line break\",\n    \"button\": \"interactive button\",\n    \"canvas\": \"dynamic graphics drawing area\",\n    \"caption\": \"table caption\",\n    \"cite\": \"work title\",\n    \"code\": \"code fragment\",\n    \"col\": \"table column\",\n    \"colgroup\": \"table column group\",\n    \"command\": \"user action control\",\n    \"datalist\": \"list of predefined options\",\n    \"dd\": \"definition description\",\n    \"del\": \"deleted text\",\n    \"details\": \"on-demand control\",\n    \"dfn\": \"definition\",\n    \"div\": \"document division\",\n    \"dl\": \"definition list\",\n    \"dt\": \"definition term\",\n    \"em\": \"emphasis\",\n    \"fieldset\": \"set of form controls\",\n    \"figcaption\": \"figure caption\",\n    \"form\": \"user-submittable form\",\n    \"h1\": \"heading\",\n    \"h2\": \"heading\",\n    \"h3\": \"heading\",\n    \"h4\": \"heading\",\n    \"h5\": \"heading\",\n    \"h6\": \"heading\",\n    \"head\": \"document metadata container\",\n    \"hgroup\": \"heading group\",\n    \"hr\": \"horizontal rule\",\n    \"html\": \"document root\",\n    \"i\": \"italics\",\n    \"iframe\": \"inline frame\",\n    \"img\": \"image\",\n    \"input\": \"input form control\",\n    \"ins\": \"inserted text\",\n    \"kbd\": \"keyboard input\",\n    \"keygen\": \"key-pair generator\",\n    \"label\": \"form control label\",\n    \"legend\": \"field set legend\",\n    \"li\": \"list item\",\n    \"link\": \"metadata for inter-document relationships\",\n    \"map\": \"image map\",\n    \"mark\": \"marked text\",\n    \"menu\": \"list of commands\",\n    \"meta\": \"metadata\",\n    \"meter\": \"scalar gauge\",\n    \"nav\": \"navigation\",\n    \"nobr\": \"no breaks\",\n    \"noscript\": \"script fallback content\",\n    \"object\": \"embedded object\",\n    \"ol\": \"ordered list\",\n    \"optgroup\": \"option grouping\",\n    \"option\": \"option item\",\n    \"output\": \"calculated result\",\n    \"p\": \"paragraph\",\n    \"param\": \"object parameter\",\n    \"pre\": \"preformatted text\",\n    \"progress\": \"progress indicator\",\n    \"q\": \"quotation\",\n    \"samp\": \"sample text\",\n    \"script\": \"embedded script\",\n    \"section\": \"document outline section\",\n    \"select\": \"selection list\",\n    \"small\": \"small text\",\n    \"source\": \"embedded media source\",\n    \"spacer\": \"layout space\",\n    \"span\": \"text span\",\n    \"strong\": \"strong emphasis\",\n    \"style\": \"CSS style sheet\",\n    \"sub\": \"subscript\",\n    \"summary\": \"summary of details\",\n    \"sup\": \"superscript\",\n    \"table\": \"tabular data\",\n    \"tbody\": \"table body\",\n    \"td\": \"table data cell\",\n    \"textarea\": \"multi-line text input\",\n    \"tfoot\": \"table footer\",\n    \"th\": \"table header cell\",\n    \"thead\": \"table header\",\n    \"time\": \"date or time\",\n    \"title\": \"document title\",\n    \"tr\": \"table row\",\n    \"tt\": \"teletype text\",\n    \"u\": \"underline\",\n    \"ul\": \"unordered list\",\n    \"var\": \"variable\",\n    \"video\": \"embedded video stream\",\n    \"wbr\": \"word break opportunity\"\n  },\n  \"css-property-docs\": {\n    \"animation\": \"The <code>animation</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand property for <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/animation-name\\\">animation-name</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/animation-duration\\\">animation-duration</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/animation-timing-function\\\">animation-timing-function</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/animation-delay\\\">animation-delay</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/animation-iteration-count\\\">animation-iteration-count</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/animation-direction\\\">animation-direction</a></code>\\n.\",\n    \"animation-delay\": \"The <code>animation-delay</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies when the animation should start. This lets the animation sequence begin some time after it's applied to an element.\",\n    \"animation-direction\": \"The <code>animation-direction</code> CSS property indicates whether the animation should play in reverse on alternate cycles.\",\n    \"animation-duration\": \"The <code>animation-duration</code> CSS property specifies the length of time that an animation should take to complete one cycle.\",\n    \"animation-iteration-count\": \"The <code>animation-iteration-count</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property defines the number of times an animation cycle should be played before stopping.\",\n    \"animation-name\": \"The <code>animation-name</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies a list of animations that should be applied to the selected element. Each name indicates a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/@keyframes\\\">@keyframes</a></code>\\n at-rule that defines the property values for the animation sequence.\",\n    \"animation-play-state\": \"The <code>animation-play-state</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property determines whether an animation is running or paused. You can query this property's value to determine whether or not the animation is currently running; in addition, you can set its value to pause and resume playback of an animation.\",\n    \"animation-timing-function\": \"The <code>animation-timing-function</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies how a CSS animation should progress over the duration of each cycle. The possible values are one or several <span class=\\\"lang lang-en\\\"><code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/timing-function\\\">&lt;timing-function&gt;</a></code>\\n </span>.\",\n    \"azimuth\": \"In combination with<code> elevation</code>, <code>azimuth</code> enables different audio sources to be positioned spatially for aural presentation. This is important in that it provides a natural way to tell several voices apart, as each can be positioned to originate at a different location on the sound stage. Stereo output produce a lateral sound stage, while binaural headphones and multi-speaker setups allow for a fully three-dimensional stage.\",\n    \"backface-visibility\": \"The <code>backface-visibility</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property determines whether or not the back face of the element is visible when facing the user. The back face of an element always is a transparent background, letting, when visible, a mirror image of the front face be displayed.\",\n    \"background\": \"The<code> background </code>CSS property is a shorthand for setting the individual background values in a single place in the style sheet.<code> background </code>can be used to set the values for one or more of: <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-color\\\">background-color</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-image\\\">background-image</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-position\\\">background-position</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-repeat\\\">background-repeat</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-size\\\">background-size</a></code>\\n, and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-attachment\\\">background-attachment</a></code>\\n.\",\n    \"background-attachment\": \"If a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-image\\\">background-image</a></code>\\n is specified, the <code>background-attachment</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property determines whether that image's position is fixed within the viewport, or scrolls along with its containing block.\",\n    \"background-clip\": \"The<code> background-clip </code>CSS property specifies whether an element's background, either the color or image, extends underneath its border.\",\n    \"background-color\": \"The <code>background-color</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the background color of an element, either through a color value or the keyword <code>transparent</code>.\",\n    \"background-image\": \"The<code> background-image </code>CSS property sets the background images for an element. The images are drawn on successive stacking context layers, with the first specified being drawn as if it is the closest to the user. The <a title=\\\"border\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/cn/CSS/border\\\">borders</a> of the element are then drawn on top of them, and the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-color\\\">background-color</a></code>\\n is drawn beneath them.\",\n    \"background-origin\": \"The<code> background-origin </code>CSS property determines the background positioning area, that is the position of the origin of an image specified using the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-image\\\">background-image</a></code>\\n CSS property.\",\n    \"background-position\": \"The<code> background-position </code>CSS property sets the initial position, relative to the background position layer defined by <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/background-origin\\\">background-origin</a></code>\\n for each defined background image.\",\n    \"background-repeat\": \"The <code>background-repeat</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property defines how background images are repeated. A background image can be repeated along the horizontal axis, the vertical axis, both, or not repeated at all. When the repetition of the image tiles doesn't let them exactly cover the background, the way adjustments are done can be controlled by the author: by default, the last image is clipped, but the different tiles can instead be re-sized, or space can be inserted between the tiles.\",\n    \"background-size\": \"The<code> background-size </code>CSS property specifies the size of the background images.\",\n    \"bleed\": \"This property specifies the extent of the page bleed area outside the page box. This property only has effect if crop marks are enabled.\",\n    \"border\": \"The <code>border</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand property for setting the individual border property values in a single place in the style sheet. <code>border</code> can be used to set the values for one or more of: <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-width\\\">border-width</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-style\\\">border-style</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-color\\\">border-color</a></code>\\n.\",\n    \"border-bottom\": \"The <code>border-bottom</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand that sets the values of <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-bottom-color\\\">border-bottom-color</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-bottom-style\\\">border-bottom-style</a></code>\\n, and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-bottom-width\\\">border-bottom-width</a></code>\\n. These properties describe the bottom border of elements.\",\n    \"border-bottom-color\": \"The<code> border-bottom-color </code>CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties&nbsp; <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-color\\\">border-color</a></code>\\n or <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-bottom\\\">border-bottom</a></code>\\n are more convenient and preferable.\",\n    \"border-bottom-left-radius\": \"The <code>border-bottom-left-radius</code> CSS property sets the rounding of the bottom-left corner of the element. The rounding can be a circle or an ellipse, or if one of the value is <code>0</code> no rounding is done and the corner is square.\",\n    \"border-bottom-right-radius\": \"The <code>border-bottom-right-radius</code> CSS property sets the rounding of the bottom-right corner of the element. The rounding can be a circle or an ellipse, or if one of the value is <code>0</code> no rounding is done and the corner is square.\",\n    \"border-bottom-style\": \"The <code>border-bottom-style</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the line style of the bottom border of a box.\",\n    \"border-bottom-width\": \"The <code>border-bottom-width</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the width of the bottom border of a box.\",\n    \"border-collapse\": \"The<code> border-collapse </code>CSS property selects a table's border model. This has a big influence on the look and style of the table cells.\",\n    \"border-color\": \"The<code> border-color </code>CSS property is a shorthand for setting the color of the four sides of an element's border: <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-top-color\\\">border-top-color</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-right-color\\\">border-right-color</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-bottom-color\\\">border-bottom-color</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-left-color\\\">border-left-color</a></code>\\n\",\n    \"border-image\": \"The<code> border-image </code>CSS property allows drawing an image on the borders of elements. This makes drawing complex looking widgets much simpler than it has been and removes the need for nine boxes in some cases.\",\n    \"border-image-outset\": \"The <code>border-image-outset </code>property describes, by which amount <dfn id=\\\"border-image-area\\\">border image area</dfn> extends beyond the border box.\",\n    \"border-image-repeat\": \"The <code>border-image-repeat</code> CSS property defines how the middle part of a border image is handled to match the size of the border. It has a one-value syntax which describes the behavior for all sides, and a two-value syntax that sets a different value for the horizontal and vertical behavior.\",\n    \"border-image-source\": \"The <code>border-image-source</code> CSS property defines the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/image\\\">&lt;image&gt;</a></code>\\n to use instead of the style of the border. If this property is set to <code>none</code>, the style defined by <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-style\\\">border-style</a></code>\\n is used instead.\",\n    \"border-image-width\": \"The <code>border-image-width</code> CSS property defines the offset to use for dividing the border image in nine parts, the top-left corner, central top edge, top-right-corner, central right edge, bottom-right corner, central bottom edge, bottom-left corner, and central right edge. They represent inward distance from the top, right, bottom and right edges.\",\n    \"border-left\": \"The <code>border-left</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand that sets the values of <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-left-color\\\">border-left-color</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-left-style\\\">border-left-style</a></code>\\n, and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-left-width\\\">border-left-width</a></code>\\n. These properties describe the left border of elements.\",\n    \"border-left-color\": \"The<code> border-left-color </code>CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties&nbsp; <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-color\\\">border-color</a></code>\\n or <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-left\\\">border-left</a></code>\\n are more convenient and preferable.\",\n    \"border-left-style\": \"The <code>border-left-style</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the line style of the left border of a box.\",\n    \"border-left-width\": \"The <code>border-left-width</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the width of the left border of a box.\",\n    \"border-radius\": \"The <code>border-radius</code> CSS property allows Web authors to define how rounded border corners are. The curve of each corner is defined using one or two radii, defining its shape: circle or ellipse.\",\n    \"border-right\": \"The <code>border-right</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand that sets the values of <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-right-color\\\">border-right-color</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-right-style\\\">border-right-style</a></code>\\n, and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-right-width\\\">border-right-width</a></code>\\n. These properties describe the right border of elements.\",\n    \"border-right-color\": \"The<code> border-right-color </code>CSS property sets the color of the bottom border of an element. Note that in many cases the shorthand CSS properties&nbsp; <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-color\\\">border-color</a></code>\\n or <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-right\\\">border-right</a></code>\\n are more convenient and preferable.\",\n    \"border-right-style\": \"The <code>border-right-style</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the line style of the right border of a box.\",\n    \"border-right-width\": \"The <code>border-right-width</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the width of the right border of a box.\",\n    \"border-spacing\": \"The <code>border-spacing</code> CSS property specifies the distance between the borders of adjacent cells (only for the <a title=\\\"en/CSS/border-collapse\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-collapse\\\">separated borders model</a>). This is equivalent to the <code>cellspacing</code> attribute in presentational HTML, but an optional second value can be used to set different horizontal and vertical spacing.\",\n    \"border-style\": \"The <code>border-style</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand property for setting the line style for all four sides of the elements border.\",\n    \"border-top\": \"The <code>border-top</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand that sets the values of <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-top-color\\\">border-top-color</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-top-style\\\">border-top-style</a></code>\\n, and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-top-width\\\">border-top-width</a></code>\\n. These properties describe the top border of elements.\",\n    \"border-top-color\": \"The<code> border-top-color </code>CSS property sets the color of the top border of an element. Note that in many cases the shorthand CSS properties&nbsp; <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-color\\\">border-color</a></code>\\n or <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-top\\\">border-top</a></code>\\n are more convenient and preferable.\",\n    \"border-top-left-radius\": \"The <code>border-top-left-radius</code> CSS property sets the rounding of the top-left corner of the element. The rounding can be a circle or an ellipse, or if one of the value is <code>0</code> no rounding is done and the corner is square.\",\n    \"border-top-right-radius\": \"The <code>border-top-right-radius</code> CSS property sets the rounding of the top-right corner of the element. The rounding can be a circle or an ellipse, or if one of the value is <code>0</code> no rounding is done and the corner is square.\",\n    \"border-top-style\": \"The <code>border-top-style</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the line style of the top border of a box.\",\n    \"border-top-width\": \"The <code>border-top-width</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property sets the width of the top border of a box.\",\n    \"border-width\": \"The<code> border-width </code>CSS property sets the width of the border of a box. Using the shorthand property <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border\\\">border</a></code>\\n is often more convenient.\",\n    \"bottom\": \"The <code>bottom</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property participates in specifying the position of <em>positioned elements</em>.\",\n    \"box-shadow\": \"The <code>box-shadow</code> CSS property accepts one or more shadow effects as a comma-separated list. It allows casting a drop shadow from the frame of almost any element. If a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/border-radius\\\">border-radius</a></code>\\n is specified on the element with a box shadow, the box shadow takes on the same rounded corners. The z-ordering of multiple box shadows is the same as multiple <a title=\\\"text-shadow\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/text-shadow\\\">text shadows</a> (the first specified shadow is on top).\",\n    \"box-sizing\": \"The<code> box-sizing </code>CSS property is used to alter the default CSS box model used to calculate widths and heights of elements. It is possible to use this property to emulate the behavior of browsers that do not correctly support the CSS box model specification.\",\n    \"caption-side\": \"The <code>caption-side</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property positions the content of a table's <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/caption\\\">&lt;caption&gt;</a></code>\\n on the specified side.\",\n    \"clear\": \"The <code>clear</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies whether an element can be next to <a title=\\\"en/CSS/float\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/float\\\">floating</a> elements that precede it or must be moved down (cleared) below them.\",\n    \"clip\": \"The <code>clip</code> CSS property defines what portion of an element is visible. The <code>clip</code> property applies only to elements with <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/position\\\">position:absolute</a></code>\\n.\",\n    \"color\": \"The <code>color</code> CSS property sets the foreground color of an element's text content\",\n    \"column-count\": \"The <code>column-count </code>CSS property describes the number of columns of the element.\",\n    \"column-fill\": \"The <code>column-fill</code> CSS property controls how contents are partitioned into columns. Contents are either balanced, which means that contents in all columns will have the same height or, when using <code>auto</code>, just take up the room the content needs.\",\n    \"column-gap\": \"The <code>column-gap</code> CSS property sets the size of the gap between columns for elements which are specified to display as a multi-column element.\",\n    \"column-rule\": \"In multi-column layouts, the <code>column-rule</code> CSS property specifies a straight line, or \\\"rule\\\", to be drawn between each column. It is a convenient shorthand to avoid setting each of the individual <code>column-rule-*</code> properties separately : <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-rule-width\\\">column-rule-width</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-rule-style\\\">column-rule-style</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-rule-color\\\">column-rule-color</a></code>\\n.\",\n    \"column-rule-color\": \"The<code> column-rule-color </code>CSS property lets you set the color of the rule drawn between columns in multi-column layouts.\",\n    \"column-rule-style\": \"The<code> column-rule-style </code>CSS property lets you set the style of the rule drawn between columns in multi-column layouts.\",\n    \"column-rule-width\": \"The<code> column-rule-width </code>CSS property lets you set the width of the rule drawn between columns in multi-column layouts.\",\n    \"column-span\": \"The <code>column-span</code> CSS property makes it possible for an element to span across all columns when its value is set to <code>all</code>. An element that spans more than one column is called a <strong>spanning element</strong>.\",\n    \"column-width\": \"The <code>column-width</code> CSS property suggests an optimal column width. This is not a absolute value but a mere hint. Browser will adjust the width of the column around that suggested value, allowing to achieve scalable designs that fit different screen size. Especially in presence of the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-count\\\">column-count</a></code>\\n CSS property which has precedence, to set an exact column width, all length values must be specified. In horizontal text these are <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/width\\\">width</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-width\\\">column-width</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-gap\\\">column-gap</a></code>\\n, and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-rule-width\\\">column-rule-width</a></code>\\n.\",\n    \"columns\": \"The <code>columns</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand property allowing to set both the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-width\\\">column-width</a></code>\\n and the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/column-count\\\">column-count</a></code>\\n properties at the same time.\",\n    \"content\": \"The<code> content </code>CSS property is used with the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/%3Abefore\\\">:before</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/%3Aafter\\\">:after</a></code>\\n pseudo-elements to generate content in an element.\",\n    \"counter-increment\": \"The <code>counter-increment</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is used to increase the value of <a title=\\\"en/CSS_Counters\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS_Counters\\\">CSS Counters</a> by a given value. The counter's value can be reset using the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/counter-reset\\\">counter-reset</a></code>\\n CSS property.\",\n    \"counter-reset\": \"The <code>counter-reset</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is used to reset <a title=\\\"en/CSS_Counters\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS_Counters\\\">CSS Counters</a> to a given value.\",\n    \"cursor\": \"The<code> cursor </code>CSS property specifies the mouse cursor displayed when the mouse pointer is over an element.\",\n    \"direction\": \"The <code>direction</code> CSS property should be set to match the direction of the text: <code>rtl</code> for Hebrew or Arabic text and <code>ltr</code> for other scripts. This should normally be done as part of the document (e.g., using the <code>dir</code> attribute in HTML) rather than through direct use of CSS.\",\n    \"display\": \"The <code>display</code> CSS property specifies the type of rendering box used for an element. In HTML, default <code>display</code> property values are taken from behaviors described in the HTML specifications or from the browser/user default stylesheet. The default value in XML is <code>inline</code>.\",\n    \"empty-cells\": \"The <code>empty-cells </code>CSS property specifies how user agent should render borders and backgrounds around cells that have no visible content.\",\n    \"float\": \"The <code>float</code> CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it.\",\n    \"font\": \"The <code>font</code> CSS property is either a shorthand property for setting <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/font-style\\\">font-style</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/font-variant\\\">font-variant</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/font-weight\\\">font-weight</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/font-size\\\">font-size</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/line-height\\\">line-height</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/font-family\\\">font-family</a></code>\\n, or a way to set the element's font to a system font, using specific keywords.\",\n    \"font-family\": \"The<code> font-family </code>CSS property allows for a prioritized list of font family names and/or generic family names to be specified for the selected element. Unlike most other CSS properties, values are separated by a comma to indicate that they are alternatives. The browser will select the first font on the list that is installed on the computer, or that can be downloaded using the information provided by a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/@font-face\\\">@font-face</a></code>\\n at-rule.\",\n    \"font-size\": \"The <code>font-size</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies the size of the font. The font size may, in turn, change the size of other items, since it is used to compute the value of <code>em</code> and <code>ex</code> length units.\",\n    \"font-size-adjust\": \"The<code> font-size-adjust </code>CSS property specifies that font size should be chosen based on the height of lowercase letters rather than the height of capital letters.\",\n    \"font-stretch\": \"The<code> font-stretch </code>CSS property selects a normal, condensed, or extended face from a font family.\",\n    \"font-style\": \"The<code> font-style </code>CSS property allows<code> italic </code>or<code> oblique </code>faces to be selected within a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/font-family\\\">font-family</a></code>\\n.<br> \",\n    \"font-variant\": \"The<code> font-variant </code>CSS property selects a<code> normal</code>, or<code> small-caps </code>face from a font family. Setting<code> font-variant </code>is also possible by using the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/font\\\">font</a></code>\\n shorthand.\",\n    \"font-weight\": \"The <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/font-weight\\\">font-weight</a></code>\\n <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies the weight or boldness of the font. However, some fonts are not available in all weights; some are available only on <code>normal</code> and <code>bold</code>.\",\n    \"height\": \"The<code> height </code>CSS property specifies the height of the content area of an element. The <a title=\\\"en/CSS/Box_model#content\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/box_model#content\\\">content area</a> is <em>inside</em> the padding, border, and margin of the element.\",\n    \"hyphens\": \"The <code>hyphens</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property tells the browser how to go about splitting words to improve the layout of text when line-wrapping.\",\n    \"image-rendering\": \"The <code>image-rendering</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property provides a hint to the user agent about how to handle its image rendering.<br> <code>image-rendering </code>applies to scaled images (and other elements, see below). For example, if the natural size of the image is<em> 100×100px </em>but the page author specifies the dimensions to <code>200×200px</code> (or<code>50×50px</code>), then the image will be upscaled (or downscaled) to the new dimensions using the specified algorithm. Scaling may also apply due to user interaction (zooming).\",\n    \"left\": \"The <code>left</code> CSS property specifies part of the position of positioned elements.\",\n    \"letter-spacing\": \"The<code> letter-spacing </code>CSS property specifies spacing behavior between text characters.\",\n    \"line-height\": \"On inline elements, the<code> line-height </code>CSS property specifies the height that is used in the calculation of the line box height.<br>\\nOn block level elements,<code> line-height </code>specifies the minimal height of line boxes within the element.\",\n    \"list-style\": \"The<code> list-style </code>CSS property is a shorthand property for setting <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/list-style-type\\\">list-style-type</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/list-style-image\\\">list-style-image</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/list-style-position\\\">list-style-position</a></code>\\n.\",\n    \"list-style-image\": \"The<code> list-style-image </code>CSS property sets the image that will be used as the list item marker. It is often more convenient to use the shortcut <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/list-style\\\">list-style</a></code>\\n.\",\n    \"list-style-position\": \"The<code> list-style-position </code>CSS property specifies the position of the marker box in the principal block box. It is often more convenient to use the shortcut <span class=\\\"lang lang-en\\\"><code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/list-style\\\">list-style</a></code>\\n</span>.\",\n    \"list-style-type\": \"The<code> list-style-type </code>CSS property specifies appearance of a list item element. As it is the only one who defaults to <code>display:list-item</code>, this is usually a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/li\\\">&lt;li&gt;</a></code>\\n element, but can be any element with this <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/display\\\">display</a></code>\\n value.\",\n    \"margin\": \"The<code> margin </code>CSS property sets the margin for all four sides. It is a shorthand to avoid setting each side separately with the other margin properties:<br>\\n<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/margin-top\\\">margin-top</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/margin-right\\\">margin-right</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/margin-bottom\\\">margin-bottom</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/margin-left\\\">margin-left</a></code>\\n.<br>\\nNegative value are also allowed.\",\n    \"margin-bottom\": \"The <code>margin-bottom</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property of an element sets the margin space required on the bottom of an element. A negative value is also allowed.\",\n    \"margin-left\": \"The <code>margin-left</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property of an element sets the margin space required on the left side of an element. A negative value is also allowed.\",\n    \"margin-right\": \"The <code>margin-right</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property of an element sets the margin space required on the right side of an element. A negative value is also allowed.\",\n    \"margin-top\": \"The<code> margin-top </code>CSS property of an element sets the margin space required on the top of an element. A negative value is also allowed.\",\n    \"marker-offset\": \"&nbsp;\",\n    \"marks\": \"The <code>marks</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property adds crop and/or cross marks to the presentation of the document. <em>Crop marks</em> indicate where the page should be cut. <em>Cross marks</em> are used to align sheets.\",\n    \"max-height\": \"The<code> max-height </code>CSS property is used to set the maximum height of a given element. It prevents the used value of the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/height\\\">height</a></code>\\n property from becoming larger than the value specified for<code> max-height</code>.\",\n    \"max-width\": \"The<code> max-width </code>CSS property is used to set the maximum width of a given element. It prevents the used value of the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/width\\\">width</a></code>\\n property from becoming larger than the value specified for<code> max-width</code>.\",\n    \"min-height\": \"The<code> min-height </code>CSS property is used to set the minimum height of a given element. It prevents the used value of the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/height\\\">height</a></code>\\n property from becoming smaller than the value specified for<code> min-height</code>.\",\n    \"min-width\": \"The<code> min-width </code>CSS property is used to set the minimum width of a given element. It prevents the used value of the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/width\\\">width</a></code>\\n property from becoming smaller than the value specified for<code> min-width</code>.\",\n    \"opacity\": \"The <code>opacity</code> CSS property specifies the transparency of an element, that is, the degree to which the background behind the element is overlaid.\",\n    \"orphans\": \"The <code>orphans</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property refers to the <em>minimum</em> number of lines in a block container that must be left at the bottom of the page.&nbsp; This property is normally used to control how page breaks occur.\",\n    \"outline\": \"The<code> outline </code>CSS property is a shorthand property for setting one or more of the individual outline properties <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/outline-style\\\">outline-style</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/outline-width\\\">outline-width</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/outline-color\\\">outline-color</a></code>\\n in a single rule. In most cases the use of this shortcut is preferable and more convenient.\",\n    \"outline-color\": \"The<code> outline-color </code>CSS property sets the color of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\",\n    \"outline-offset\": \"The<code> outline-offset </code>CSS property is used to set space between an <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/outline\\\">outline</a></code>\\n and the edge or border of an element. An outline is a line that is drawn around elements, outside the border edge.\",\n    \"outline-style\": \"The<code> outline-style </code>CSS property is used to set the style of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\",\n    \"outline-width\": \"The<code> outline-width </code>CSS property is used to set the width of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out:\",\n    \"overflow\": \"The<code> overflow </code>CSS property specifies whether to clip content, render scroll bars or display overflow content of a block-level element.\",\n    \"overflow-x\": \"The <code>overflow-x </code><a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies whether to clip content, render a scroll bar or display overflow content of a block-level element, when it overflows at the left and right edges.\",\n    \"padding\": \"The<code> padding </code>CSS property sets the required padding space on all sides of an element. The <a title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/Box_model#padding\\\">padding area</a> is the space between the content of the element and its border. Negative values are not allowed.\",\n    \"padding-bottom\": \"The <code>padding-bottom</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property of an element sets the padding space required on the bottom of an element. The <a title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/box_model#padding\\\">padding area</a> is the space between the content of the element and it's border. A negative value is not allowed.\",\n    \"padding-left\": \"The <code>padding-left</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property of an element sets the padding space required on the left side of an element. The <a title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/box_model#padding\\\">padding area</a> is the space between the content of the element and it's border. A negative value is not allowed.\",\n    \"padding-right\": \"The <code>padding-right</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property of an element sets the padding space required on the right side of an element. The <a title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/box_model#padding\\\">padding area</a> is the space between the content of the element and its border. Negative values are not allowed.\",\n    \"padding-top\": \"The <code>padding-top</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property of an element sets the padding space required on the top of an element. The <a title=\\\"http://developer.mozilla.org/en/CSS/Box_model#padding\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/box_model#padding\\\">padding area</a> is the space between the content of the element and it's border. A negative values is not allowed.\",\n    \"page-break-after\": \"The <code>page-break-after</code> CSS property adjusts page breaks <em>after</em> the current element.\",\n    \"page-break-before\": \"The <code>page-break-before</code> CSS property adjusts page breaks <em>before</em> the current element.\",\n    \"page-break-inside\": \"The <code>page-break-inside</code> CSS property adjusts page breaks <em>inside</em> the current element.\",\n    \"perspective\": \"The <code>perspective</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property determines the distance between the z=0 plane and the user in order to give to the 3D-positioned element some perspective. Each 3D element that is placed between the z=0 and the user is enlarged, each 3D-element with z&lt;0 is shrinked. How much deformation is defined by the value of this property.\",\n    \"perspective-origin\": \"The <code>perspective-origin</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property determines the position the viewer is looking at. It is used as the <em>vanishing point</em> by the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/perspective\\\">perspective</a></code>\\n property.\",\n    \"position\": \"The<code> position </code>CSS property chooses alternative rules for positioning elements, designed to be useful for scripted animation effects.\",\n    \"quotes\": \"The <code>quotes</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property indicates how user agents should render quotation marks.\",\n    \"resize\": \"The <code>resize</code> CSS property lets you control the resizability of an element.\",\n    \"right\": \"The <code>right</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies part of the position of positioned elements.\",\n    \"tab-size\": \"The <code>tab-size</code> CSS property is used to customize the width of a tab (<code>U+0009</code>) character.\",\n    \"table-layout\": \"The <code>table-layout</code> CSS property defines the algorithm to be used to layout the table cells, rows, and columns.\",\n    \"text-align\": \"The<code> text-align </code>CSS property describes how inline content like text is aligned in its parent block element.<code> text-align </code>does not control the alignment of block elements itself, only their inline content.\",\n    \"text-align-last\": \"The <code>text-align-last</code> CSS property describes how the last line of a block or a line right before a forced line break is aligned.\",\n    \"text-decoration\": \"The<code> text-decoration </code>CSS property is used to set the text formattings <code>underline, overline, line-through</code> and <code>blink</code>.\",\n    \"text-decoration-color\": \"The <code>text-decoration-color</code> CSS property sets the color used when drawing underlines, overlines, or strike-throughs specified by <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/text-decoration-line\\\">text-decoration-line</a></code>\\n. This is the preferred way to color these text decorations, rather than using combinations of other HTML&nbsp;elements.\",\n    \"text-decoration-line\": \"The <code>text-decoration-line</code> CSS property sets what kind of line decorations are added to an element.\",\n    \"text-decoration-style\": \"The <code>text-decoration-style</code> CSS property defines the style of the lines specified by <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/text-decoration-line\\\">text-decoration-line</a></code>\\n. The style applies to all lines, there is no way to define different style for each of the line defined by <code>text-decoration-line</code>.\",\n    \"text-indent\": \"The<code> text-indent </code>CSS property specifies how much horizontal space should be left before beginning of the first line of the text content of an element. Horizontal spacing is with respect to the left (or right, for right-to-left layout) edge of the containing block element's box.\",\n    \"text-shadow\": \"The<code> text-shadow </code>CSS property adds shadows to text. It accepts a comma-separated list of shadows to be applied to the text and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/text-decoration\\\">text-decorations</a></code>\\n of the element.\",\n    \"text-transform\": \"The <code>text-transform</code> CSS property specifies how to capitalize an element's text. It can be used to make text appear in all-uppercase or all-lowercase, or with each word capitalized.\",\n    \"top\": \"The <code>top</code> CSS property specifies part of the position of positioned elements. It has no effect on non-positioned elements.\",\n    \"transform\": \"The <code>transform</code> CSS property lets you modify the coordinate space of the CSS visual formatting model. Using it, elements can be translated, rotated, scaled, and skewed according to the values set.\",\n    \"transform-origin\": \"The <code>transform-origin</code> CSS property lets you modify the origin for transformations of an element. For example, the transform-origin of the <code>rotate()</code> function is the centre of rotation. (This property is applied by first translating the element by the negated value of the property, then applying the element's transform, then translating by the property value.)\",\n    \"transform-style\": \"The <code>transform-style</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property determines if the children of the element are positioned in the 3D-space or are flattened in the plane of the element.\",\n    \"transition\": \"The<code> transition </code><a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is a shorthand property for <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/transition-property\\\">transition-property</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/transition-duration\\\">transition-duration</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/transition-timing-function\\\">transition-timing-function</a></code>\\n, and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/transition-delay\\\">transition-delay</a></code>\\n.\",\n    \"transition-delay\": \"The<code> transition-delay </code><a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies the amount of time to wait between a change being requested to a property that is to be transitioned and the start of the <a title=\\\"en/CSS/CSS transitions\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/CSS_transitions\\\">transition effect</a>.\",\n    \"transition-duration\": \"The<code> transition-duration </code><a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies the number of seconds or milliseconds a transition animation should take to complete. By default, the value is 0s, meaning that no animation will occur.\",\n    \"transition-property\": \"The <code>transition-property</code> CSS property is used to specify the names of CSS properties to which a <a title=\\\"en/CSS/CSS transitions\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/CSS_transitions\\\">transition effect</a> should be applied.\",\n    \"transition-timing-function\": \"The<code> transition-timing-function </code>CSS property is used to describe how the intermediate values of the CSS&nbsp;properties being affected by a <a title=\\\"en/CSS/CSS transitions\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/CSS_transitions\\\">transition effect</a> are calculated. This in essence lets you establish an acceleration curve, so that the speed of the transition can vary over its duration.\",\n    \"vertical-align\": \"The <code>vertical-align</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property specifies the vertical alignment of an inline or table-cell element.\",\n    \"visibility\": \"The<code> visibility </code>CSS property is used for two things:\",\n    \"white-space\": \"The<code> white-space </code>CSS property is used to to describe how whitespace inside the element is handled.\",\n    \"widows\": \"where:\",\n    \"width\": \"The<code> width </code>CSS property specifies the width of the content area of an element. The <a title=\\\"en/CSS/box_model#content\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS/box_model#content\\\">content area</a> is <em>inside</em> the padding, border, and margin of the element.\",\n    \"word-spacing\": \"The<code> word-spacing </code>CSS property specifies spacing behavior between tags and words.\",\n    \"word-wrap\": \"The <code>word-wrap</code> <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a> property is used to to specify whether or not the browser is allowed to break lines within words in order to prevent overflow when an otherwise unbreakable string is too long to fit.\",\n    \"z-index\": \"The<code> z-index </code>CSS property specifies the z-order of an element and its descendants. When elements overlap, z-order determines which one covers the other. An element with a larger z-index generally covers an element with a lower one.\"\n  },\n  \"html-element-docs\": {\n    \"a\": \"The HTML Anchor Element (<code>&lt;a&gt;</code>) defines a hyperlink, the named target destination for a hyperlink, or both.\",\n    \"abbr\": \"The HTML&nbsp;Abbreviation Element (<code>&lt;abbr&gt;</code>) represents an abbreviation and optionally provides a full description for it. If present, the <strong>title</strong> attribute must contain this full description and nothing else.\",\n    \"address\": \"The HTML Address&nbsp;Element (<code>&lt;address&gt;)</code> may be used by authors to supply contact information for its nearest <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/article\\\">&lt;article&gt;</a></code>\\n or <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/body\\\">&lt;body&gt;</a></code>\\n ancestor; in the later case, it applies to the whole document.\",\n    \"area\": \"The HTML <em>Area</em> element (<code>&lt;area&gt;</code>) defines a hot-spot region on an image, and optionally associates it with a hypertext link. This element is used only within a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/map\\\">&lt;map&gt;</a></code>\\n element.\",\n    \"article\": \"The <em>HTML Article Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;article&gt;</span>) represents a self-contained composition in a document, page, application, or site, which is intended to be independently distributable or reusable, e.g., in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content.\",\n    \"aside\": \"The <em>HTML Aside Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;aside&gt;</span>) represents a section of a page that consists of content that is tangentially related to the content around it, which could be considered separate from that content. Such sections are often represented as sidebars or as inserts; they often contains side explanation like a glossary definition, more loosely related stuff like advertisements, the biography of the author, or in web-applications, profile information or related blog links.\",\n    \"audio\": \"The <code>audio</code> element is used to embed sound content in an HTML&nbsp;or XHTML document.&nbsp; The <code>audio</code> element was added as part of HTML5.\",\n    \"b\": \"The HTML B Element (<code>&lt;b&gt;</code>) represents a span of text stylistically different from normal text, without a conveying any special importance or relevance. It is typically used for keywords in a summary, product names in a review, or other spans of text whose typical presentation would be boldfaced. Another example of its use is to mark the lead sentence of each paragraph of an article.\",\n    \"base\": \"The HTML&nbsp;<em>Base</em> element (<code>&lt;base&gt;</code>) specifies the base URL to use for all relative URLs contained within a document.&nbsp;\",\n    \"bdi\": \"The <em>HTML Bi-directional Isolation Element</em> (<code>&lt;bdi&gt;</code>) isolates a span of text that might be formatted in a different direction from other text outside it.\",\n    \"bdo\": \"The HTML Bidirectional Override Element (<span style=\\\"font-family: Courier New;\\\">&lt;bdo&gt;</span>) is used to override the current directionality of text. It causes the directionality of the characters to be ignored in favor of the specified directionality.\",\n    \"blockquote\": \"The HTML <em>Block Quotation</em> (<code>&lt;blockquote&gt;</code>) element indicates that the enclosed text is an extended quotation. Usually, this is rendered visually by indentation (see <a title=\\\"en/HTML/Element/blockquote#Notes\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/blockquote#Notes\\\">Notes</a> for how to change it). A URL for the source of the quotation may be given using the <strong>cite</strong> attribute, while a text representation of the source can be given using the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/cite\\\">&lt;cite&gt;</a></code>\\n element.\",\n    \"body\": \"The HTML&nbsp;Body (<code>&lt;body&gt;</code>) element represents the main content of an HTML&nbsp;document. There is only one <code>&lt;body&gt;</code> element in a document.\",\n    \"br\": \"The HTML&nbsp;<em>Line Break</em> element (<code>&lt;br&gt;</code>) produces a line break in text (carriage-return). It is useful for writing a poem or an address, where the division of lines is significant.&nbsp;\",\n    \"button\": \"The <em>button</em> (<span style=\\\"font-family: Courier New;\\\">&lt;button&gt;</span>)&nbsp;HTML element represents a clickable button.\",\n    \"canvas\": \"The <em>Canvas</em> (<code>&lt;canvas&gt;</code>) HTML element can be used to draw graphics via scripting (usually <a title=\\\"en/JavaScript\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/JavaScript\\\">JavaScript</a>). For example, it can be used to draw graphs, make photo compositions or even perform animations.\",\n    \"caption\": \"The <em>HTML Table Caption Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;caption&gt;</span>) represents the title of a table. Though it is always the first descendant of a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/table\\\">&lt;table&gt;</a></code>\\n, its styling, using CSS, may place it elsewhere, relative to the table.\",\n    \"cite\": \"The HTML&nbsp;Citation Element (<span style=\\\"font-family: Courier New;\\\">&lt;cite&gt;</span>) contains the title of a work, such as a book, song, movie, TV&nbsp;show, sculpture, etc.\",\n    \"code\": \"The HTML Code Element (<span style=\\\"font-family: Courier New;\\\">&lt;code&gt;</span>) represents a fragment of computer code. By default, it is displayed in the browser's default monospace font.\",\n    \"col\": \"The <em>HTML Table Column Element</em> (<code>&lt;col&gt;</code>) defines a column within a table and is used for defining common semantic on all common cells. It is generally found within a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/colgroup\\\">&lt;colgroup&gt;</a></code>\\n element.\",\n    \"colgroup\": \"The <em>HTML Table Column Group Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;colgroup&gt;</span>) defines a group of column within a table.\",\n    \"command\": \"The <code>command </code>element represents a command which the user can invoke.\",\n    \"datalist\": \"The <em>HTML Datalist Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;datalist&gt;</span>) contains a set of <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/option\\\">&lt;option&gt;</a></code>\\n elements that represent the possible options for the value of other controls.\",\n    \"dd\": \"The Definition Description Element (<span style=\\\"font-family: Courier New;\\\">&lt;dd&gt;</span>) indicates the definition of a term in a definition list (<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/dl\\\">&lt;dl&gt;</a></code>\\n) element. This element can occur only as a child element of a definition list and it must follow a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/dt\\\">&lt;dt&gt;</a></code>\\n element.\",\n    \"del\": \"The Deleted Text (<code>&lt;del&gt;</code>) HTML&nbsp;element represents a range of text that has been deleted from a document. This element is often (but need not be) rendered with strike-through text.\",\n    \"details\": \"The HTML <em>details</em> element (<code>&lt;details&gt;</code>) is used as a disclosure widget from which the user the retrieve additional information.\",\n    \"dfn\": \"The Definition (<code>&lt;dfn&gt;</code>)&nbsp;HTML element represents the defining instance of a term.\",\n    \"div\": \"The Document Division (&lt;div&gt;) HTML&nbsp;element is generic container for flow content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the <strong>class</strong> or <strong>id</strong> attributes), or because they share attribute values, such as <strong>lang</strong>. It should be used only when no other semantic element (such as <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/article\\\">&lt;article&gt;</a></code>\\n or <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/nav\\\">&lt;nav&gt;</a></code>\\n) is appropriate.\",\n    \"dl\": \"The HTML <em>Definition List</em> (<code>&lt;dl&gt;</code>) element encloses a list of pairs of terms and descriptions. A common use for this element is to implement a glossary.\",\n    \"dt\": \"The HTML Definition Term Element (<span style=\\\"font-family: Courier New;\\\">&lt;dt&gt;</span>) identifies a term in a definition list. This element can occur only as a child element of a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/dl\\\">&lt;dl&gt;</a></code>\\n. It is usually followed by a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/dd\\\">&lt;dd&gt;</a></code>\\n element; however, multiple <code>&lt;dt&gt;</code> elements in a row indicate several terms that are all defined by the immediate next <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/dd\\\">&lt;dd&gt;</a></code>\\n element.\",\n    \"em\": \"The HTML Emphasis Element (<span style=\\\"font-family: Courier New;\\\">&lt;em&gt;</span>) marks text that has stress emphasis. The <code>&lt;em&gt;</code> element can be nested, with each level of nesting indicating a greater degree of emphasis.\",\n    \"embed\": \"The <em>HTML&nbsp;Embed Element</em> (<code>&lt;embed&gt;</code>) represents an integration point for an external application or interactive content (in other words, a plug-in).\",\n    \"fieldset\": \"The HTML&nbsp;element<em> fieldset </em>(<span style=\\\"font-family: Courier New;\\\">&lt;fieldset&gt;</span>) is used to group several controls as well as labels (<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/label\\\">&lt;label&gt;</a></code>\\n) within a web form.\",\n    \"figcaption\": \"The <em>HTML Figcaption Element</em> (<code>&lt;figcaption&gt;</code>) represents a caption or a legend associated with a figure or an illustration described by the rest of the data of the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/figure\\\">&lt;figure&gt;</a></code>\\n element which is its immediate ancestor which means <code>&lt;figcaption&gt;</code> can be the first or last element inside a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/figure\\\">&lt;figure&gt;</a></code>\\n block.&nbsp;Also, the <em>HTML Figcaption Element&nbsp;</em>is optional; if not provided, then the parent figure element will have no caption.\",\n    \"figure\": \"The <em>HTML Figure Element&nbsp;</em>(<span style=\\\"font-family: Courier New;\\\">&lt;figure&gt;</span>) represents self-contained content, frequently with a caption&nbsp;(<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/figcaption\\\">&lt;figcaption&gt;</a></code>\\n)<em><code>,</code></em> and is&nbsp;typically referenced as a single unit. While it is related to the main flow, its position is independent of the main flow. Usually this is an image, an illustration, a diagram, a code snippet, or a schema that is referenced in the main text, but that can be moved to another page or to an appendix without affecting the main flow.\",\n    \"footer\": \"The <em>HTML Footer Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;footer&gt;</span>) represents a footer for its nearest sectioning content or <a title=\\\"en/Sections and Outlines of an HTML5 document#sectioning root\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/Sections_and_Outlines_of_an_HTML5_document#sectioning_root\\\">sectioning root</a> element (i.e, its nearest parent <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/article\\\">&lt;article&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/aside\\\">&lt;aside&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/nav\\\">&lt;nav&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/section\\\">&lt;section&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/blockquote\\\">&lt;blockquote&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/body\\\">&lt;body&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/details\\\">&lt;details&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/fieldset\\\">&lt;fieldset&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/figure\\\">&lt;figure&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/td\\\">&lt;td&gt;</a></code>\\n). A footer typically contains information about the author of the section, copyright data or links to related documents.\",\n    \"form\": \"The <em>form</em> (&lt;form&gt;) HTML&nbsp;element represents a section of document that contains interactive controls that enable a user to submit information to a web server.\",\n    \"h1\": \"<strong>Heading</strong> elements implement six levels of document headings, <code>&lt;h1&gt;</code> is the most important and <code>&lt;h6&gt;</code> is the least. A heading element briefly describes the topic of the section it introduces. Heading information may be used by user agents, for example, to construct a table of contents for a document automatically.\",\n    \"head\": \"The HTML <code>&lt;head&gt;</code> element represents a collection of metadata about the document, including links to or definitions of scripts and style sheets.\",\n    \"header\": \"The <em>HTML Header Element</em> (<code>&lt;header&gt;</code>) represents a group of introductory or navigational aids. It may contain some heading elements but also other elements like a logo, wrapped section's header, a search form, and so on.\",\n    \"hgroup\": \"The <em>HTML Headings Group Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;hgroup&gt;</span>) represents the heading of a section. It defines a single title that participates in <a title=\\\"en/Sections and Outlines of an HTML5 document\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/Sections_and_Outlines_of_an_HTML5_document\\\">the outline of the document</a> as the heading of the implicit or explicit section that it belongs too.\",\n    \"hr\": \"In \\n<span style=\\\"border: 1px solid rgb(129, 129, 250); background-color: rgb(174, 218, 229); font-size: x-small; white-space: nowrap; padding: 2px;\\\"><a rel=\\\"custom\\\" href=\\\"/en/HTML/HTML5\\\">HTML5</a></span> the &lt;hr&gt; element represents a thematic break between paragraph-level elements (for example, a change of scene in a story, or a shift of topic with a section). In previous versions of HTML, it represented a horizontal rule. It may still be displayed as a horizontal rule in visual browsers, but is now defined in semantic terms, rather than presentational terms.\",\n    \"html\": \"The HTML root element (<span style=\\\"font-family: Courier New;\\\">&lt;html&gt;</span>) represents the root of an HTML or XHTML document. All other elements must be descendants of this element.\",\n    \"i\": \"The HTML Offset Text (or Italics) Element (<span style=\\\"font-family: Courier New;\\\">&lt;i&gt;</span>) represents a range of text that is set off from the normal text for some reason, for example, technical terms, foreign language phrases, or fictional character thoughts. It is typically displayed in italic type.\",\n    \"iframe\": \"The HTML&nbsp;inline frame element (<code>&lt;iframe&gt;</code>) represents a nested browsing context, effectively embedding another HTML page into the current page. Each browsing context has its own session history and active document. The browsing context that contains the embedded content is called the <dfn id=\\\"parent\\\">parent</dfn> browsing context. The <dfn id=\\\"top-level\\\">top-level</dfn> browsing context (which has no parent) is typically the browser window.\",\n    \"img\": \"The HTML Image Element (<code>&lt;img&gt;</code>) represents an image to the document.\",\n    \"input\": \"The <em>input</em> (<code>&lt;input&gt;</code>) element is used to create interactive controls for web-based forms.\",\n    \"ins\": \"The <em>HTML&nbsp;Inserted Text</em> (<code>&lt;ins&gt;</code>) HTML represents a range of text that has been added to a document.\",\n    \"kbd\": \"The HTML Keyboard Input Element (<span style=\\\"font-family: Courier New;\\\">&lt;kbd&gt;</span>) produces an inline element displayed in the browser's default monotype font. This element is used to identify user input.\",\n    \"keygen\": \"The HTML <code>keygen</code> element exists to facilitate generation of key material, and submission of the public key as part of an HTML form. This mechanism is designed for use with Web-based certificate management systems. It is expected that the <code>keygen</code> element will be used in an HTML form along with other information needed to construct a certificate request, and that the result of the process will be a signed certificate.\",\n    \"label\": \"The <em>HTML Label Element</em> (<code>&lt;label&gt;</code>) represents a caption for an item in a user interface. It can be associated with a control either by using the <code>for</code> attribute, or by placing the control element inside the <code>label</code> element. Such a control is called the <em>labeled control</em> of the label element.\",\n    \"legend\": \"The <em>HTML Legend Field Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;legend&gt;</span>) represents a caption for the content of its parent <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/fieldset\\\">&lt;fieldset&gt;</a></code>\\n.\",\n    \"li\": \"The <em>HTML List item element</em> (<code>&lt;li&gt;</code>) is used to represent a list item. It should be contained in an ordered list (<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/ol\\\">&lt;ol&gt;</a></code>), an unordered list (<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/ul\\\">&lt;ul&gt;</a></code>) or a menu (<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/menu\\\">&lt;menu&gt;</a></code>), where it represents a single entity in that list.\",\n    \"link\": \"The <em>HTML Link Element</em> (&lt;link&gt;) specifies relationships between the current document and other documents. Possible uses for this element include defining a relational framework for navigation and linking the document to a style sheet.\",\n    \"map\": \"The HTML <em>Map</em> element (<code>&lt;map&gt;</code>) is used with <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/area\\\">&lt;area&gt;</a></code>\\n elements to define a image map.\",\n    \"mark\": \"The <em>HTML Mark Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;mark&gt;</span>) represents highlighted text, i.e., a run of text marked for reference purpose, due to its <em>relevance</em> in a particular context. For example it can be used in a page showing search results to highlight every instance of the searched for word.\",\n    \"menu\": \"The HTML <em>menu</em> element (<code>&lt;menu&gt;</code>) represents an unordered list of menu choices, or commands.\",\n    \"meta\": \"The <em>HTML Meta Element</em> (<code>&lt;meta&gt;</code>) represents any metadata information which cannot be represented using one of the other meta-related element (<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/base\\\">&lt;base&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/link\\\">&lt;link&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/script\\\">&lt;script&gt;</a></code>\\n, <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/style\\\">&lt;style&gt;</a></code>\\n or <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/title\\\">&lt;title&gt;</a></code>\\n). According to the attributes set, the kind of metadata can be one of the following:\",\n    \"meter\": \"The HTML <em>meter</em> element (<code>&lt;meter&gt;</code>) represents either a scalar value within a known range or a fractional value.\",\n    \"nav\": \"The <em>HTML Navigation Element</em> (<code>&lt;nav&gt;</code>) represents a section of a page that links to other pages or to parts within the page: a section with navigation links.\",\n    \"noscript\": \"The HTML NoScript Element (<code>&lt;noscript&gt;</code>) defines a section of html to be inserted if a script type on the page is unsupported or if scripting is currently turned off in the browser.\",\n    \"object\": \"The Embedded Object (&lt;object&gt;) element represents an external resource, which can be treated as an image, a nested browsing context, or a resource to be handled by a plugin.\",\n    \"ol\": \"The HTML <em>ordered list</em> element (<code>&lt;ol&gt;</code>) represents an ordered list of items. Typically, ordered-list items are displayed with a preceding numbering, which can be of any form, like numerals, letters or Romans numerals or even simple bullets. This numbered style is not defined in the HTML description of the page, but in its associated CSS, using the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/list-style-type\\\">list-style-type</a></code>\\n property.\",\n    \"optgroup\": \"In a web form, the HTML <em>optgroup</em> element (&lt;optgroup&gt;) creates a grouping of options within a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/select\\\">&lt;select&gt;</a></code>\\n element.\",\n    \"option\": \"In a web form, the HTML<em> option </em>element (<span style=\\\"font-family: Courier New;\\\">&lt;option&gt;</span>) is used to create a control representing an item within a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/select\\\">&lt;select&gt;</a></code>\\n, an <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/optgroup\\\">&lt;optgroup&gt;</a></code>\\n or a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/datalist\\\">&lt;datalist&gt;</a></code>\\n HTML5 element.\",\n    \"output\": \"The <em>output</em> (&lt;output&gt;) element represents the result of a calculation.\",\n    \"p\": \"<strong>Paragraph</strong> element (&lt;p&gt;) represents a paragraph. It is the most commonly used block-level element.\",\n    \"param\": \"<strong>Parameter </strong>element which defines parameters for <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/object\\\">&lt;object&gt;</a></code>\\n.\",\n    \"pre\": \"This element represents preformatted text. Text within this element is typically displayed in a non-proportional font exactly as it is laid out in the file. Whitespaces inside this element are displayed as typed.\",\n    \"progress\": \"The HTML <em>progress</em> (<code>&lt;progress&gt;</code>) element is used to view the completion progress of a task. While the specifics of how it's displayed is left up to the browser developer, it's typically displayed as a progress bar.\",\n    \"q\": \"The <strong>quote</strong> element indicates that the enclosed text is a short inline quotation.\",\n    \"s\": \"The <em>HTML&nbsp;Strikethrough Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;s&gt;</span>) renders text with a strike-through, or a line through it. Use the <code>&lt;s&gt;</code> element to represent things that are no longer relevant or no longer accurate. However, <code>&lt;s&gt;</code> is not appropriate when indicating document edits; for that, use the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/del\\\">&lt;del&gt;</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/ins\\\">&lt;ins&gt;</a></code>\\n elements, as appropriate.\",\n    \"samp\": \"The HTML Sample Text Element (<span style=\\\"font-family: Courier New;\\\">&lt;samp&gt;</span>) produces an inline element displayed in the browser's default monotype font (Lucida Console). This element was intended to identify sample output from a computer program.\",\n    \"script\": \"The <code>script</code> element is used to embed or reference an executable script within an <abbr title=\\\"Hypertext Markup Language\\\">HTML</abbr> or <abbr title=\\\"Extensible Hypertext Markup Language\\\">XHTML</abbr> document.\",\n    \"section\": \"The <em>HTML Section Element</em> (<code>&lt;section&gt;</code>) represents a generic section of a document, i.e., a thematic grouping of content, typically with a heading.\",\n    \"select\": \"The <em>select</em> (<code>&lt;select&gt;</code>) HTML element represents a control that presents menu of options. The options within the menu are represented by <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/option\\\">&lt;option&gt;</a></code>\\n elements, which can be grouped by <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/optgroup\\\">&lt;optgroup&gt;</a></code>\\n elements. Options can be pre-selected for the user.\",\n    \"small\": \"The HTML Small Element (<span style=\\\"font-family: Courier New;\\\">&lt;small&gt;</span>) makes the text <em>font size</em> one size smaller (for example, from large to medium, or from small to x-small) down to the browser's minimum font size.\",\n    \"source\": \"The <code>source</code> element is used to specify multiple media resources for <code> audio</code> and <code>video</code> elements in HTML5. It is an empty element. It is commonly used to serve the same media in <a title=\\\"En/Media formats supported by the audio and video elements\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements\\\">multiple formats supported by different browsers</a>.\",\n    \"span\": \"This HTML element is a generic inline container for phrasing content, which does not inherently represent anything. It can be used to group elements for styling purposes (using the <strong>class</strong> or <strong>id</strong> attributes), or because they share attribute values, such as <strong>lang</strong>. It should be used only when no other semantic element is appropriate. &lt;span&gt; is very much like a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/div\\\">&lt;div&gt;</a></code>\\n element, but <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/div\\\">&lt;div&gt;</a></code>\\n is a block-level element whereas a &lt;span&gt; is an inline element.\",\n    \"strong\": \"The HTML Strong Element (<span style=\\\"font-family: Courier New;\\\">&lt;strong&gt;</span>) gives text strong emphasis, typically this is displayed in bold.\",\n    \"style\": \"Style element contains style information for a document. Style information should go inside of this element, usually in the CSS language (see <a title=\\\"CSS\\\" rel=\\\"internal\\\" href=\\\"https://developer.mozilla.org/en/CSS\\\">CSS</a>).\",\n    \"sub\": \"The <em>HTML Subscript Element</em> (<code>&lt;sub&gt;</code>) defines a span of text that should be displayed, for typographic reasons, lower, and often smaller, than the main span of text.\",\n    \"summary\": \"The HTML <em>summary </em>element (<code>&lt;summary&gt;</code>) is used as a summary, caption or legend for the content of a <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/details\\\">&lt;details&gt;</a></code>\\n element.\",\n    \"sup\": \"The <em>HTML Superscript Element</em> (<code>&lt;sup&gt;</code>) defines a span of text that should be displayed, for typographic reasons, higher, and often smaller, than the main span of text.\",\n    \"table\": \"The <em>HTML Table Element </em>(<code>&lt;table&gt;</code>) represents data in two dimensions or more.\",\n    \"tbody\": \"The <em>HTML Table Body Element</em> (<code>&lt;tbody&gt;</code>) defines a set of rows defining the body of the table. Though not mandatory, as the rows of the body can be defined as <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/tr\\\">&lt;tr&gt;</a></code>\\n elements children of the parent <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/table\\\">&lt;table&gt;</a></code>\\n element, if present, all <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/tr\\\">&lt;tr&gt;</a></code>\\n elements part of the body must be included into a unique <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/tbody\\\">&lt;tbody&gt;</a></code>\\n element.\",\n    \"td\": \"The <em>HTML Table Cell Element</em> (<code>&lt;td&gt;</code>) defines a cell that content data.\",\n    \"textarea\": \"The <em>textarea</em> (<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/textarea\\\">&lt;textarea&gt;</a></code>\\n) HTML element represents a multi-line plain-text editing control.\",\n    \"tfoot\": \"The <em>HTML Table Foot Element</em> (<code>&lt;tfoot&gt;</code>) defines a set of rows summarizing the columns of the table.\",\n    \"th\": \"The <em>HTML Table Header Cell Element</em> (<code>&lt;th&gt;</code>) defines a cell that is a header for a group of cells of a table. The group of cells that the header refers to is defined by the \\n\\n<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/th#attr-scope\\\">scope</a></code>\\n and \\n\\n<code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/th#attr-headers\\\">headers</a></code>\\n attribute.\",\n    \"thead\": \"The <em>HTML Table Head Element</em> (<code>&lt;thead&gt;</code>) defines a set of rows defining the head of the columns of the table.\",\n    \"time\": \"The HTML <em>time</em> element (<code>&lt;time&gt;</code>) represents either time on a 24-hour clock or a precise date in the <a class=\\\"external\\\" title=\\\"http://en.wikipedia.org/wiki/Gregorian_calendar\\\" rel=\\\"external\\\" href=\\\"http://en.wikipedia.org/wiki/Gregorian_calendar\\\" target=\\\"_blank\\\">Gregorian calendar</a> (with optional time and timezone information).\",\n    \"title\": \"The <em>HTML Title Element</em> (<code>&lt;title&gt;</code>) defines the title of the document, shown in a browser's title bar or on the page's tab. It can only contain text and any contained tags are not interpreted.\",\n    \"tr\": \"The <em>HTML Table Row Element</em> (<code>&lt;tr&gt;</code>) defines a row of cells in a table. Those can be a mix of <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/td\\\">&lt;td&gt;</a></code>\\n and <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/HTML/Element/th\\\">&lt;th&gt;</a></code>\\n elements.\",\n    \"u\": \"The <em>HTML Underline Element</em> (<span style=\\\"font-family: Courier New;\\\">&lt;u&gt;</span>) renders text with an underline, a line under the baseline of its content.\",\n    \"ul\": \"The HTML <em>unordered list</em> element (<code>&lt;ul&gt;</code>) represents an unordered list of items, namely a collection of items that do not have a numerical ordering, and their order in the list is meaningless. Typically, unordered-list items are displayed with a bullet, which can be of several forms, like a dot, a circle or a squared. The bullet style is not defined in the HTML description of the page, but in its associated CSS, using the <code><a rel=\\\"custom\\\" href=\\\"https://developer.mozilla.org/en/CSS/list-style-type\\\">list-style-type</a></code>\\n property.\",\n    \"var\": \"The HTML Variable Element (<code>&lt;var&gt;</code>) represents a variable in a mathematical expression or a programming context.\",\n    \"video\": \"The HTML&nbsp; <code>&lt;video&gt;</code> element is used to embed video content in an HTML&nbsp;or XHTML document.\",\n    \"wbr\": \"The <em>Word Break Opportunit</em><em>y</em> (<code>&lt;wbr&gt;</code>) HTML element represents a position within text where the browser may optionally break a line, though its line-breaking rules would not otherwise create a break at that location.\"\n  },\n  \"css-selector-docs\": \"This is a CSS selector. It describes the kinds of HTML elements that a CSS rule's style will be applied to.\"\n}});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/help.js",
    "content": "\"use strict\";\n\ndefine([\"./hacktionary-data\"], function(HacktionaryData) {\n  // A help index provides context-sensitive help for an HTML document,\n  // indexed by characters in the HTML source code.\n  function HelpIndex() {\n    // A mapping from character indices in source code to associated\n    // context-sensitive help information.\n    var helpIndex = [];\n\n    return {\n      // Clear the help index.\n      clear: function() {\n        helpIndex = [];\n      },\n      // Build a new help index based on the given HTML and its DOM\n      // representation, which should be annotated by Slowparse.\n      build: function(document, html) {\n        buildHelpIndex(document, helpIndex, html);\n      },\n      // Return the context-sensitive help information for a particular\n      // position in the source code, or undefined if no help is available.\n      get: function(index) {\n        return getHelp(index, helpIndex);\n      }\n    };\n  }\n\n  // Return the context-sensitive help information for a particular\n  // position in the source code, or undefined if no help is available.\n  function getHelp(index, helpIndex) {\n    var help = helpIndex[index];\n    if (help) {\n      if (help.type == \"tag\" &&\n          help.value in HacktionaryData[\"html-element-docs\"])\n        return {\n          type: help.type,\n          html: HacktionaryData[\"html-element-docs\"][help.value],\n          url: Help.MDN_URLS.html + help.value,\n          highlights: help.highlights\n        };\n      else if (help.type == \"cssProperty\" &&\n               help.value in HacktionaryData[\"css-property-docs\"])\n        return {\n          type: help.type,\n          html: HacktionaryData[\"css-property-docs\"][help.value],\n          url: Help.MDN_URLS.css + help.value,\n          highlights: help.highlights\n        };\n      else if (help.type == \"cssSelector\")\n        return {\n          type: help.type,\n          html: HacktionaryData[\"css-selector-docs\"],\n          url: Help.MDN_URLS.cssSelectors,\n          highlights: help.highlights\n        };\n    }\n  }\n\n  // \"Normalize\" a tag name by converting e.g. any heading level to h1,\n  // so that they can be easily looked up in the hacktionary.\n  function normalizeTagName(tagName) {\n    tagName = tagName.toLowerCase();\n    if (tagName.match(/^h[1-6]$/))\n      return \"h1\";\n    return tagName;\n  }\n\n  // Recursively build the help index mapping source code indices \n  // to context-sensitive help.\n  function buildHelpIndex(element, helpIndex, html) {\n    var i, child,\n        pi = element.parseInfo,\n        tagInfo = {\n          type: \"tag\",\n          value: normalizeTagName(element.nodeName),\n          highlights: []\n        };\n    if (pi) {\n      if (pi.openTag) {\n        tagInfo.highlights.push(pi.openTag);\n        for (i = pi.openTag.start + 1;\n             i < pi.openTag.start + element.nodeName.length + 2;\n             i++)\n          helpIndex[i] = tagInfo;\n      }\n      if (pi.closeTag) {\n        tagInfo.highlights.push(pi.closeTag);\n        for (i = pi.closeTag.start + 1; i < pi.closeTag.end; i++)\n          helpIndex[i] = tagInfo;\n      }\n    }\n    for (i = 0; i < element.childNodes.length; i++) {\n      child = element.childNodes[i];\n      if (child.nodeType == element.ELEMENT_NODE) {\n        buildHelpIndex(child, helpIndex, html);\n      }\n      if (element.nodeName == \"STYLE\" && child.parseInfo.rules) {\n        child.parseInfo.rules.forEach(function(rule) {\n          var selectorInfo = {\n            type: \"cssSelector\",\n            highlights: [rule.selector]\n          };\n          for (var i = rule.selector.start; i < rule.selector.end; i++)\n            helpIndex[i] = selectorInfo;\n          rule.declarations.properties.forEach(function(prop) {\n            var cssInfo = {\n              type: \"cssProperty\",\n              value: html.slice(prop.name.start, prop.name.end).toLowerCase(),\n              highlights: [prop.name]\n            };\n            for (var i = prop.name.start; i < prop.name.end; i++)\n              helpIndex[i] = cssInfo;\n          });\n        });\n      }\n    }\n  }\n  \n  var Help = {\n    Index: HelpIndex,\n    // URLs for help on the Mozilla Developer Network.\n    MDN_URLS: {\n      html: \"https://developer.mozilla.org/en/HTML/Element/\",\n      css: \"https://developer.mozilla.org/en/CSS/\",\n      cssSelectors: \"https://developer.mozilla.org/en/CSS/\" +\n                    \"Getting_Started/Selectors\"\n    }\n  };\n\n  return Help;\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/parachute.js",
    "content": "\"use strict\";\n\n// This helper saves the editor's data to local storage just before\n// the page unloads, and provides a method to restore it. Useful for\n// when a user accidentally refreshes/navigates away from the editor\n// and wants to retrieve their old content.\n//\n// TODO: This could be a privacy concern, since people at shared terminals\n// might not want the next user to be able to see what they were just\n// working on. We're currently only saving the data for a few minutes, though,\n// so hopefully this shouldn't be that big a problem.\ndefine([\"lscache\"], function(lscache) {\n  return function Parachute(window, codeMirror, page) {  \n    // Amount of time, in minutes, to save parachute data.\n    var timeLimit = 5;\n    var prefix = \"FRIENDLYCODE_PARACHUTE_DATA_\";\n    var key = prefix + page;\n    var originalData = codeMirror.getValue();\n    var self = {\n      restore: function() {\n        var saved = lscache.get(key);\n        if (saved) {\n          if (saved == codeMirror.getValue()) {\n            // Our saved data is the same as the unmodified data, so there's\n            // no need to store it.\n            lscache.remove(key);\n          } else {\n            codeMirror.setValue(saved);\n            return true;\n          }\n        }\n        return false;\n      },\n      save: function() {\n        if (codeMirror.getValue() != originalData)\n          lscache.set(key, codeMirror.getValue(), timeLimit);\n      },\n      refresh: function() {\n        originalData = codeMirror.getValue();\n      },\n      clearCurrentPage: function() {\n        lscache.remove(key);\n      },\n      changePage: function(newPage) {\n        page = newPage;\n        key = prefix + page;\n      },\n      destroyAll: function() {\n        window.removeEventListener(\"beforeunload\", self.save, true);\n        lscache.flush();\n      }\n    };\n  \n    window.addEventListener(\"beforeunload\", self.save, true);\n    return self;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/prefs.js",
    "content": "define([\"backbone\", \"lscache\"], function(Backbone, lscache) {\n  \n  var Preferences = Backbone.Model.extend({\n    // Amount of time, in minutes, to store text size setting.\n    CACHE_TIME_LIMIT: 9000,\n    // Key to store our Preferences JSON blob in.\n    CACHE_KEY: 'FriendlycodePreferences',\n    // Used so that Model.isNew() is always false.\n    id: 1,\n    sync: function(method, model, options) {\n      var json;\n      \n      if (method == \"create\" || method == \"update\") {\n        json = model.toJSON();\n        lscache.set(this.CACHE_KEY, json, this.CACHE_TIME_LIMIT);\n        options.success(json);\n      } else if (method == \"delete\") {\n        lscache.remove(this.CACHE_KEY);\n      } else if (method == \"read\") {\n        json = lscache.get(this.CACHE_KEY);\n        if (!json || typeof(json) != \"object\")\n          json = {};\n        options.success(json);\n      }\n    }\n  });\n  \n  return new Preferences();\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/publisher.js",
    "content": "\"use strict\";\n\n// This class is responsible for communicating with a publishing server\n// to save and load published code.\ndefine([\"jquery\"], function($) {\n  var myOrigin = window.location.protocol + \"//\" + window.location.host;\n  \n  function Publisher(baseURL) {\n    // We want to support CORS for development but in production it doesn't\n    // matter because all requests will be same-origin. However, browsers\n    // that don't support CORS will barf if they're given absolute URLs to\n    // the same domain, so we want to return relative URLs in such cases.\n    function makeURL(path) {\n      if (baseURL == myOrigin)\n        return path;\n      path = baseURL + path;\n      if (!$.support.cors && window.console)\n        window.console.warn(\"No CORS detected for request to \" + path);\n      return path;\n    }\n\n    return {\n      baseURL: baseURL,\n      loadCode: function(path, cb) {\n        $.ajax({\n          type: 'GET',\n          url: makeURL(path),\n          dataType: 'text',\n          error: function(data) {\n            cb(data);\n          },\n          success: function(data) {\n            cb(null, fixDoctypeHeadBodyMunging(data), baseURL + path);\n          }\n        });\n      },\n      saveCode: function(data, originalURL, cb) {\n        $.ajax({\n          type: 'POST',\n          url: makeURL('/api/page'),\n          data: {\n            'html': data,\n            'original-url': originalURL || ''\n          },\n          dataType: 'text',\n          error: function(data) {\n            cb(data);\n          },\n          success: function(data) {\n            cb(null, {path: data, url: baseURL + data});\n          }\n        });\n      }\n    };\n  }\n  \n  // This is a fix for https://github.com/mozilla/webpagemaker/issues/20.\n  function fixDoctypeHeadBodyMunging(html) {\n    var lines = html.split('\\n');\n    if (lines.length > 2 &&\n        lines[0] == '<!DOCTYPE html><html><head>' &&\n        lines[lines.length-1] == '</body></html>') {\n      return '<!DOCTYPE html>\\n<html>\\n  <head>\\n' +\n             lines.slice(1, -1).join('\\n') + '</body>\\n</html>';\n    }\n    return html;\n  }\n  \n  // Exposing this for unit testing purposes only.\n  Publisher._fixDoctypeHeadBodyMunging = fixDoctypeHeadBodyMunging;\n  \n  return Publisher;\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/context-sensitive-help.js",
    "content": "\"use strict\";\n\n// Provides context-sensitive help for a ParsingCodeMirror based on\n// the current cursor position.\ndefine([\n  \"jquery\",\n  \"fc/prefs\",\n  \"./mark-tracker\"\n], function($, Preferences, MarkTracker) {\n  return function ContextSensitiveHelp(options) {\n    var self = {};\n    var codeMirror = options.codeMirror;\n    var template = options.template;\n    var helpArea = options.helpArea;\n    var relocator = options.relocator;\n    var helpIndex = options.helpIndex;\n    var lastEvent = null;\n    var timeout = null;\n    var lastHelp = null;\n    var HELP_DISPLAY_DELAY = 250;\n    \n    // The escape key should close hints \n    $(document).keyup(function(event) {\n      if (event.keyCode == 27)\n        clearHelp();\n    });\n\n    // Keep track of context-sensitive help highlighting.\n    var cursorHelpMarks = MarkTracker(codeMirror);\n\n    codeMirror.on(\"reparse\", function(event) {\n      clearHelp();\n      lastEvent = event;\n      helpIndex.clear();\n      if (!event.error)\n        helpIndex.build(event.document, event.sourceCode);\n    });\n    \n    function showHelp(cursorIndex, help) {\n      cursorHelpMarks.clear();\n\n      if (help.type == \"cssSelector\") {\n        // TODO: Because we're looking at the generated document fragment and\n        // not an actual HTML document, implied elements like <body> may not\n        // be captured here.\n        var selector = help.highlights[0].value;\n        var matches = lastEvent.document.querySelectorAll(selector).length;\n        help.matchCount = matches;\n      }\n      var oldOffset = helpArea.offset();\n      helpArea.html(template(help)).show();\n      var startMark = null;\n      help.highlights.forEach(function(interval) {\n        var start = interval.start,\n            end = interval.end;\n        // Show the help message closest to the highlight that\n        // encloses the current cursor position.\n        if (start <= cursorIndex && end >= cursorIndex)\n          startMark = start;\n        cursorHelpMarks.mark(start, end, \"cursor-help-highlight\");\n      });\n      if (startMark !== null) {\n        relocator.relocate(helpArea, startMark, \"help\");\n        var newOffset = helpArea.offset();\n        if (newOffset.top != oldOffset.top ||\n            newOffset.left != oldOffset.left) {\n          helpArea.hide();\n          helpArea.fadeIn();\n        }\n      }\n    }\n\n    function clearHelp() {\n      clearTimeout(timeout);\n      lastHelp = null;\n      cursorHelpMarks.clear();\n      helpArea.hide();\n      relocator.cleanup();\n    }\n    \n    codeMirror.on(\"change\", clearHelp);\n    codeMirror.on(\"cursor-activity\", function() {\n      clearTimeout(timeout);\n      \n      if (Preferences.get(\"showHints\") === false)\n        return;\n\n      // If the editor widget doesn't have input focus, this event\n      // was likely triggered through some programmatic manipulation rather\n      // than manual cursor movement, so don't bother displaying a hint.\n      if (!$(codeMirror.getWrapperElement()).hasClass(\"CodeMirror-focused\"))\n        return;\n\n      var cursorIndex = codeMirror.getCursorIndex();\n      var help = helpIndex.get(cursorIndex);\n\n      if (JSON.stringify(help) == lastHelp)\n        return;\n\n      clearHelp();\n      // same as error-help.js, \"reparse\" handler\n      if (help) {\n        timeout = setTimeout(function() {\n          lastHelp = JSON.stringify(help);\n          showHelp(cursorIndex, help);\n        }, HELP_DISPLAY_DELAY);\n      }\n    });\n\n    Preferences.on(\"change:showHints\", function() {\n      if (Preferences.get(\"showHints\") === false)\n        clearHelp();\n    });\n    \n    Preferences.trigger(\"change:showHints\");\n    return self;\n  };\n});"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/editor-panes.js",
    "content": "define(function(require) {\n  var $ = require(\"jquery\"),\n      Slowparse = require(\"slowparse/slowparse\"),\n      TreeInspectors = require(\"slowparse/tree-inspectors\"),\n      ParsingCodeMirror = require(\"fc/ui/parsing-codemirror\"),\n      Help = require(\"fc/help\"),\n      LivePreview = require(\"fc/ui/live-preview\"),\n      ErrorHelp = require(\"fc/ui/error-help\"),\n      ContextSensitiveHelp = require(\"fc/ui/context-sensitive-help\"),\n      PreviewToEditorMapping = require(\"fc/ui/preview-to-editor-mapping\"),\n      Relocator = require(\"fc/ui/relocator\"),\n      HelpMsgTemplate = require(\"template!help-msg\"),\n      ErrorMsgTemplate = require(\"template!error-msg\");\n  \n  require('slowparse-errors');\n  require(\"codemirror/html\");\n  \n  return function EditorPanes(options) {\n    var self = {},\n        div = options.container,\n        initialValue = options.value || \"\",\n        allowJS = options.allowJS || false,\n        sourceCode = $('<div class=\"source-code\"></div>').appendTo(div),\n        previewArea = $('<div class=\"preview-holder\"></div>').appendTo(div),\n        helpArea = $('<div class=\"help hidden\"></div>').appendTo(div),\n        errorArea =  $('<div class=\"error hidden\"></div>').appendTo(div);\n    \n    var codeMirror = self.codeMirror = ParsingCodeMirror(sourceCode[0], {\n      mode: \"text/html\",\n      theme: \"jsbin\",\n      tabMode: \"indent\",\n      lineWrapping: true,\n      lineNumbers: true,\n      value: initialValue,\n      parse: function(html) {\n        return Slowparse.HTML(document, html,\n                              allowJS ? [] : [TreeInspectors.forbidJS]);\n      }\n    });\n    var relocator = Relocator(codeMirror);\n    var cursorHelp = self.cursorHelp = ContextSensitiveHelp({\n      codeMirror: codeMirror,\n      helpIndex: Help.Index(),\n      template: HelpMsgTemplate,\n      helpArea: helpArea,\n      relocator: relocator\n    });\n    var errorHelp = ErrorHelp({\n      codeMirror: codeMirror,\n      template: ErrorMsgTemplate,\n      errorArea: errorArea,\n      relocator: relocator\n    });\n    var preview = self.preview = LivePreview({\n      codeMirror: codeMirror,\n      ignoreErrors: true,\n      previewArea: previewArea\n    });\n    var previewToEditorMapping = PreviewToEditorMapping(preview);\n    \n    return self;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/editor-toolbar.js",
    "content": "define(function(require) {\n  var $ = require(\"jquery-tipsy\"),\n      Preferences = require(\"fc/prefs\"),\n      HistoryUI = require(\"fc/ui/history\"),\n      NavOptionsTemplate = require(\"template!nav-options\"),\n      TextUI = require(\"fc/ui/text\");\n  \n  function HintsUI(options) {\n    var self = {},\n        hintsNavItem = options.navItem,\n        hintsCheckbox = hintsNavItem.find(\".checkbox\");\n    \n    Preferences.on(\"change:showHints\", function() {\n      if (Preferences.get(\"showHints\") === false)\n        hintsCheckbox.removeClass(\"on\").addClass(\"off\");\n      else\n        hintsCheckbox.removeClass(\"off\").addClass(\"on\");\n    });\n    \n    hintsNavItem.click(function() {\n      var isDisabled = (Preferences.get(\"showHints\") === false);\n      Preferences.set(\"showHints\", isDisabled);\n      Preferences.save();\n    });\n\n    Preferences.trigger(\"change:showHints\");\n    return self;\n  }\n  \n  return function Toolbar(options) {\n    var self = {},\n        div = options.container,\n        panes = options.panes,\n        navOptions = $(NavOptionsTemplate()).appendTo(div),\n        publishButton = navOptions.find(\".publish-button\"),\n        undoNavItem = navOptions.find(\".undo-nav-item\"),\n        startPublish;\n    \n    var historyUI = HistoryUI({\n      codeMirror: panes.codeMirror,\n      undo: undoNavItem,\n      redo: navOptions.find(\".redo-nav-item\")\n    });\n    var textUI = TextUI({\n      codeMirror: panes.codeMirror,\n      navItem: navOptions.find(\".text-nav-item\")\n    });\n    var hintsUI = HintsUI({\n      navItem: navOptions.find(\".hints-nav-item\")\n    });\n\n    function onChangeTitle(title) {\n      if (title.length)\n        $(\".preview-title\", navOptions).text(title).show();\n      else\n        $(\".preview-title\", navOptions).hide();\n    }\n    \n    panes.preview.on(\"change:title\", onChangeTitle);\n    onChangeTitle(panes.preview.title);\n    \n    // If the editor has no content, disable the publish button.\n    panes.codeMirror.on(\"change\", function() {\n      var codeLength = panes.codeMirror.getValue().trim().length;\n      publishButton.toggleClass(\"enabled\", codeLength ? true : false);\n    });\n    publishButton.click(function(){\n      if ($(this).hasClass(\"enabled\")) startPublish(this);\n    });\n    \n    self.refresh = function() {\n      historyUI.refresh();\n    };\n    self.setStartPublish = function(func) {\n      startPublish = func;\n      publishButton.toggle(!!startPublish);\n    };\n    self.showDataRestoreHelp = function() {\n      // Display a non-modal message telling the user that their\n      // previous data has been restored, and that they can click 'undo'\n      // to go back to the original version of the editor content.\n      // This is just a temporary workaround to avoid confusion until\n      // we figure out a better solution; see this issue for more\n      // discussion:\n      //\n      // https://github.com/mozilla/webpagemaker/issues/53\n      undoNavItem.tipsy({\n        gravity: 'n',\n        fade: true,\n        trigger: 'manual',\n        title: 'data-restore-help',\n        className: 'friendlycode-base'\n      }).tipsy(\"show\");\n      setTimeout(function() { undoNavItem.tipsy(\"hide\"); }, 6000);\n    };\n    \n    self.setStartPublish(null);\n    return self;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/editor.js",
    "content": "define([\n  \"jquery\",\n  \"./editor-panes\",\n  \"./editor-toolbar\"\n], function($, EditorPanes, EditorToolbar) {\n  return function Editor(options) {\n    var value = options.value,\n        container = options.container.empty()\n          .addClass(\"friendlycode-base\"),\n        toolbarDiv = $('<div class=\"friendlycode-toolbar\"></div>')\n          .appendTo(container),\n        panesDiv = $('<div class=\"friendlycode-panes\"></div>')\n          .appendTo(container);\n    \n    var panes = EditorPanes({\n      container: panesDiv,\n      value: value,\n      allowJS: options.allowJS\n    });\n    var toolbar = EditorToolbar({\n      container: toolbarDiv,\n      panes: panes\n    });\n    \n    container.removeClass(\"friendlycode-loading\");\n    panes.codeMirror.refresh();\n    \n    return {\n      container: container,\n      panes: panes,\n      toolbar: toolbar\n    };\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/error-help.js",
    "content": "\"use strict\";\n\n// Provides helpful Slowparse-based error suggestions for a\n// ParsingCodeMirror.\ndefine([\"jquery-slowparse\", \"./mark-tracker\"], function($, MarkTracker) {\n  // Display an animated arrow pointing at a particular position in a\n  // codeMirror instance. It disappears after a short delay.\n  function pointAtPosition(codeMirror, pos) {\n    var MOVE_TIME = 500;\n    var PAUSE_TIME = 1000;\n    var pointer = $('<div class=\"cursor-pointer\"></div>');\n    codeMirror.addWidget(pos, pointer[0], true);\n    pointer.css({\n      opacity: 0,\n      paddingTop: '50px'\n    });\n    pointer.animate({\n      opacity: 1,\n      paddingTop: 0\n    }, MOVE_TIME).delay(PAUSE_TIME).fadeOut(function() {\n      pointer.remove();\n    });\n  }\n\n  return function ErrorHelp(options) {\n    var self = {};\n    var codeMirror = options.codeMirror;\n    var template = options.template;\n    var errorArea = options.errorArea;\n    var relocator = options.relocator;\n    var timeout = null;\n    var ERROR_DISPLAY_DELAY = 250;\n\n    // The escape key should close error help \n    $(document).keyup(function(event) {\n      if (event.keyCode == 27)\n        clearError();\n    });\n\n    // Keep track of error highlighting.\n    var errorHelpMarks = MarkTracker(codeMirror, relocator);\n  \n    // Report the given Slowparse error.\n    function reportError(error) {\n      var startMark = null;\n      var errorHTML = $(\"<div></div>\").fillError(error);\n      errorArea.html(template({error: errorHTML.html()})).show();\n      errorArea.eachErrorHighlight(function(start, end, i) {\n        // Point the error message's arrow at the first occurrence of\n        // the word \"here\" in the error message.\n        if (startMark === null)\n          startMark = start;\n        errorHelpMarks.mark(start, end, \"highlight-\" + (i+1), this);\n        $(this).click(function() {\n          var pos = codeMirror.posFromIndex(start);\n          codeMirror.setCursor(pos);\n          pointAtPosition(codeMirror, pos);\n        });\n      });\n      relocator.relocate(errorArea, startMark, \"error\");\n      errorArea.hide();\n    }\n  \n    function clearError() {\n      clearTimeout(timeout);\n      errorHelpMarks.clear();\n      errorArea.hide();\n      relocator.cleanup();\n    }\n    \n    codeMirror.on(\"change\", clearError);\n    codeMirror.on(\"reparse\", function(event) {\n      clearError();\n      // same as context-sensitive-help.js, \"cursor-activity\" handling\n      if (event.error) {\n        timeout = setTimeout(function() {\n          reportError(event.error);\n        }, ERROR_DISPLAY_DELAY);\n      }\n    });\n    return self;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/gutter-pointer.js",
    "content": "\"use strict\";\n\n// gutterPointer(codeMirror, highlightClass)\n//\n// This function creates and returns an SVG shape that looks like this:\n//\n//   --\\\n//   |  \\\n//   |  /\n//   --/\n// \n// It also puts the shape between the gutter and the content of a\n// CodeMirror line. The shape will be vertically stretched to take up the\n// entire height of the line.\n//\n// The shape is given the class gutter-pointer, as well as the same\n// class as the highlightClass argument.\n//\n// Arguments:\n// \n//   codeMirror: The CodeMirror instance to apply the pointer to.\n//\n//   highlightClass: The class name used to \"highlight\" the desired\n//     gutter line via CodeMirror.setMarker().\n//\n// This function makes some assumptions about the way CodeMirror works,\n// as well as the styling applied to the CodeMirror instance, but we\n// try where possible to use methods and CSS classes documented in\n// the CodeMirror manual at http://codemirror.net/doc/manual.html.\n\ndefine([\"jquery\"], function($) {\n  var SVG_NS = \"http://www.w3.org/2000/svg\";\n  \n  function attrs(element, attributes) {\n    for (var name in attributes)\n      element.setAttribute(name, attributes[name].toString());\n  }\n  \n  return function gutterPointer(codeMirror, highlightClass) {    \n    var wrapper = $(codeMirror.getWrapperElement());\n    var highlight = $(\".CodeMirror-gutter-text .\" + highlightClass, wrapper);\n    var svg = document.createElementNS(SVG_NS, \"svg\");\n    var pointer = document.createElementNS(SVG_NS, \"polygon\");\n    var w = ($(\".CodeMirror-gutter\", wrapper).outerWidth() -\n             highlight.width()) * 2;\n    var h = highlight[0].getBoundingClientRect().height;\n    var pos = highlight.position();\n    \n    pos.left += highlight.width();\n    attrs(svg, {\n      'class': \"gutter-pointer \" + highlightClass,\n      viewBox: [0, 0, w, h].join(\" \")\n    });\n    attrs(pointer, {\n      points: [\n        \"0,0\",\n        (w/2) + \",0\",\n        w + \",\" + (h/2),\n        (w/2) + \",\" + h,\n        \"0,\" + h\n      ].join(\" \")\n    });\n    svg.appendChild(pointer);\n    $(svg).css({\n      position: 'absolute',\n      width: w + \"px\",\n      height: h + \"px\",\n      top: pos.top + \"px\",\n      left: pos.left + \"px\"\n    });\n\n    $(\".CodeMirror-scroll\", wrapper).append(svg);\n    \n    return $(svg);\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/history.js",
    "content": "\"use strict\";\n\n// This manages the UI for undo/redo.\ndefine(function() {\n  return function HistoryUI(options) {\n    var undo = options.undo;\n    var redo = options.redo;\n    var codeMirror = options.codeMirror;\n\n    function refreshButtons() {\n      var history = codeMirror.historySize();\n      undo.toggleClass(\"enabled\", history.undo == 0 ? false : true);\n      redo.toggleClass(\"enabled\", history.redo == 0 ? false : true);\n    }\n  \n    undo.click(function() {\n      codeMirror.undo();\n      codeMirror.reparse();\n      refreshButtons();\n    });\n    redo.click(function() {\n      codeMirror.redo();\n      codeMirror.reparse();\n      refreshButtons();\n    });\n    codeMirror.on(\"change\", refreshButtons);\n    refreshButtons();\n    return {refresh: refreshButtons};\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/indexable-codemirror.js",
    "content": "\"use strict\";\n\n// A subclass of CodeMirror which adds a few methods that make it easier\n// to work with character indexes rather than {line, ch} objects.\ndefine([\"codemirror\"], function(CodeMirror) {\n  return function IndexableCodeMirror(place, givenOptions) {\n    var codeMirror = CodeMirror(place, givenOptions);\n  \n    // Returns the character index of the cursor position.\n    codeMirror.getCursorIndex = function() {\n      return codeMirror.indexFromPos(codeMirror.getCursor());\n    };\n  \n    return codeMirror;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/live-preview.js",
    "content": "\"use strict\";\n\n// Displays the HTML source of a CodeMirror editor as a rendered preview\n// in an iframe.\ndefine([\"jquery\", \"backbone-events\"], function($, BackboneEvents) {\n  function LivePreview(options) {\n    var self = {codeMirror: options.codeMirror, title: \"\"},\n        codeMirror = options.codeMirror,\n        iframe;\n\n    codeMirror.on(\"reparse\", function(event) {\n      var isPreviewInDocument = $.contains(document.documentElement,\n                                           options.previewArea[0]);\n      if (!isPreviewInDocument) {\n        if (window.console)\n          window.console.log(\"reparse triggered, but preview area is not \" +\n                             \"attached to the document.\");\n        return;\n      }\n      if (!event.error || options.ignoreErrors) {\n        var x = 0,\n            y = 0,\n            doc, wind;\n        \n        if (iframe) {\n          doc = $(iframe).contents()[0];\n          wind = doc.defaultView;\n          x = wind.pageXOffset;\n          y = wind.pageYOffset;\n          $(iframe).remove();\n        }\n\n        iframe = document.createElement(\"iframe\");\n        options.previewArea.append(iframe);\n        \n        // Update the preview area with the given HTML.\n        doc = $(iframe).contents()[0];\n        wind = doc.defaultView;\n\n        doc.open();\n        doc.write(event.sourceCode);\n        doc.close();\n\n        // Insert a BASE TARGET tag so that links don't open in\n        // the iframe.\n        var baseTag = doc.createElement('base');\n        baseTag.setAttribute('target', '_blank');\n        doc.querySelector(\"head\").appendChild(baseTag);\n        \n        // TODO: If the document has images that take a while to load\n        // and the previous scroll position of the document depends on\n        // their dimensions being set on load, we may need to refresh\n        // this scroll position after the document has loaded.\n        wind.scroll(x, y);\n        \n        self.trigger(\"refresh\", {\n          window: wind,\n          documentFragment: event.document\n        });\n\n        if (wind.document.title != self.title) {\n          self.title = wind.document.title;\n          self.trigger(\"change:title\", self.title);\n        }\n      }\n    });\n\n    BackboneEvents.mixin(self);\n    return self;\n  };\n  \n  return LivePreview;\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/mark-tracker.js",
    "content": "\"use strict\";\n\n// This helper class keeps track of different kinds of highlighting in\n// a CodeMirror instance.\ndefine([\"jquery\"], function($) {\n  return function MarkTracker(codeMirror) {\n    var classNames = {};\n    var marks = [];\n\n    return {\n      // Mark a given start/end interval in the CodeMirror, based on character\n      // indices (not {line, ch} objects), with the given class name. If\n      // an element is provided, give it the class name too.\n      mark: function(start, end, className, element) {\n        if (!(className in classNames))\n          classNames[className] = [];\n        if (element) {\n          classNames[className].push(element);\n          $(element).addClass(className);\n        }\n        start = codeMirror.posFromIndex(start);\n        end = codeMirror.posFromIndex(end);\n        marks.push(codeMirror.markText(start, end, className));\n      },\n      // Clear all marks made so far and remove the class from any elements\n      // it was previously given to.\n      clear: function() {\n        marks.forEach(function(mark) {\n          // Odd, from the CodeMirror docs you'd think this would remove\n          // the class from the highlighted text, too, but it doesn't.\n          // I guess we're just garbage collecting here.\n          mark.clear();\n        });\n        var wrapper = codeMirror.getWrapperElement();\n        for (var className in classNames) {\n          classNames[className].forEach(function(element) {\n            $(element).removeClass(className);\n          });\n          $(\".\" + className, wrapper).removeClass(className);\n        }\n\n        marks = [];\n        classNames = {};\n      }\n    };\n  };\n});\n  "
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/modals.js",
    "content": "\"use strict\";\r\n\r\ndefine(function (require) {\r\n  var $ = require(\"jquery\"),\r\n      ErrorDialogTemplate = require(\"template!error-dialog\");\r\n  \r\n  return function(options) {\r\n    var self = {},\r\n        div = options.container,\r\n        errorDialog = $(ErrorDialogTemplate()).appendTo(div);\r\n\r\n    var hideModals = function() {\r\n      div.find(\".modal-overlay\").fadeOut();\r\n    }\r\n    \r\n    /**\r\n     * When someone clicks on the darkening-overlay, rather\r\n     * than the modal dialog, close the modal dialog again.\r\n     */\r\n    div.on(\"click\", \".modal-overlay\", function(event) { \r\n      if (event.target === this)\r\n        $(this).fadeOut(); \r\n    });\r\n\r\n    div.on(\"click\", \"[data-close-modal]\", hideModals);\r\n\r\n    /**\r\n     * The escape key should univerally close modal dialogs\r\n     */ \r\n    $(document).keyup(function(event) {\r\n      if (event.keyCode == 27)\r\n        hideModals();\r\n    });\r\n    \r\n    self.add = function() {\r\n      for (var i = 0; i < arguments.length; i++)\r\n        div.append(arguments[i]);\r\n    };\r\n    \r\n    self.showErrorDialog = function(options) {\r\n      $(\".error-text\", errorDialog).text(options.text);\r\n      errorDialog.show();\r\n    };\r\n    \r\n    return self;\r\n  };\r\n});\r\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/parsing-codemirror.js",
    "content": "\"use strict\";\n\n// A subclass of IndexableCodeMirror which continuously re-parses\n// the code in its editor. Also adds a Backbone.Events interface\n// for extension points to hook into.\ndefine([\n  \"backbone-events\",\n  \"./indexable-codemirror\"\n], function(BackboneEvents, IndexableCodeMirror) {\n  return function ParsingCodeMirror(place, givenOptions) {\n    // Called whenever content of the editor area changes.\n    function reparse() {\n      var sourceCode = codeMirror.getValue();\n      var result = givenOptions.parse(sourceCode);\n      codeMirror.trigger(\"reparse\", {\n        error: result.error,\n        sourceCode: sourceCode,\n        document: result.document\n      });\n      // Cursor activity would've been fired before us, so call it again\n      // to make sure it displays the right context-sensitive help based\n      // on the new state of the document.\n      onCursorActivity();\n    }\n\n    // Called whenever the user moves their cursor in the editor area.\n    function onCursorActivity() {\n      codeMirror.trigger(\"cursor-activity\");\n    }\n\n    // The number of milliseconds to wait before re-parsing the editor\n    // content.\n    var parseDelay = givenOptions.parseDelay || 300;\n    var time = givenOptions.time || window;\n    var reparseTimeout;\n\n    givenOptions.onChange = function() {\n      codeMirror.trigger(\"change\");\n      if (reparseTimeout !== undefined)\n        time.clearTimeout(reparseTimeout);\n      if (codeMirror.reparseEnabled)\n        reparseTimeout = time.setTimeout(reparse, parseDelay);\n    };\n    givenOptions.onCursorActivity = onCursorActivity;\n\n    var codeMirror = IndexableCodeMirror(place, givenOptions);\n    BackboneEvents.mixin(codeMirror);\n    codeMirror.reparse = reparse;\n    codeMirror.reparseEnabled = true;\n    return codeMirror;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/preview-to-editor-mapping.js",
    "content": "\"use strict\";\n\ndefine([\"jquery\", \"./mark-tracker\"], function($, MarkTracker) {\n  // Given a descendant of the given root element, returns a CSS\n  // selector that uniquely selects only the descendant from the\n  // root element.\n  function pathTo(root, descendant) {\n    var target = $(descendant).get(0);\n    var parts = [];\n    var node, nodeName, n, selector;\n\n    for (node = target; node && node != root; node = node.parentNode) {\n      nodeName = node.nodeName.toLowerCase();\n      n = $(node).prevAll(nodeName).length + 1;\n      selector = nodeName + ':nth-of-type(' + n + ')';\n      parts.push(selector);\n    }\n    \n    parts.reverse();\n    return ' > ' + parts.join(' > ');\n  }\n  \n  function nodeToCode(node, docFrag) {\n    var parallelNode = getParallelNode(node, docFrag);\n    var result = null;\n    if (parallelNode) {\n      var pi = parallelNode.parseInfo;\n      var isVoidElement = !pi.closeTag;\n      result = {\n        start: pi.openTag.start,\n        end: isVoidElement ? pi.openTag.end : pi.closeTag.end,\n        contentStart: isVoidElement ? pi.openTag.start : pi.openTag.end\n      };\n    }\n    return result;\n  }\n\n  function getParallelNode(node, docFrag) {\n    var root, i;\n    var htmlNode = docFrag.querySelector(\"html\");\n    var origDocFrag = docFrag;\n    var parallelNode = null;\n    if (htmlNode && docFrag.querySelector(\"body\")) {\n      root = node.ownerDocument.documentElement;\n    } else {\n      if (!htmlNode) {\n        docFrag = document.createDocumentFragment();\n        htmlNode = document.createElement(\"html\");\n        docFrag.appendChild(htmlNode);\n        for (i = 0; i < origDocFrag.childNodes.length; i++)\n          htmlNode.appendChild(origDocFrag.childNodes[i]);\n      }\n      root = node.ownerDocument.body;\n    }\n    var path = \"html \" + pathTo(root, node);\n    parallelNode = docFrag.querySelector(path);\n    if (origDocFrag != docFrag) {\n      for (i = 0; i < htmlNode.childNodes.length; i++)\n        origDocFrag.appendChild(htmlNode.childNodes[i]);\n    }\n    return parallelNode;\n  }\n\n  function PreviewToEditorMapping(livePreview) {\n    var codeMirror = livePreview.codeMirror;\n    var marks = MarkTracker(codeMirror);\n    $(\".CodeMirror-lines\", codeMirror.getWrapperElement())\n      .on(\"mouseup\", marks.clear);\n    livePreview.on(\"refresh\", function(event) {\n      var docFrag = event.documentFragment;\n      marks.clear();\n      $(event.window).on(\"mousedown\", function(event) {\n        marks.clear();\n        var tagName = event.target.tagName.toLowerCase();\n        var interval = null;\n        if (tagName !== \"html\" && tagName !== \"body\")\n          interval = nodeToCode(event.target, docFrag);\n        if (interval) {\n          var start = codeMirror.posFromIndex(interval.start);\n          var end = codeMirror.posFromIndex(interval.end);\n          var contentStart = codeMirror.posFromIndex(interval.contentStart);\n          var startCoords = codeMirror.charCoords(start, \"local\");\n          codeMirror.scrollTo(startCoords.x, startCoords.y);\n          marks.mark(interval.start, interval.end,\n                     \"preview-to-editor-highlight\");\n          codeMirror.focus();\n          event.preventDefault();\n          event.stopPropagation();\n        }\n      });\n    });\n  }\n  \n  PreviewToEditorMapping._pathTo = pathTo;\n  PreviewToEditorMapping._nodeToCode = nodeToCode;\n  \n  return PreviewToEditorMapping;\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/publish.js",
    "content": "\"use strict\";\n\ndefine(function (require) {\n  var $ = require(\"jquery\"),\n      BackboneEvents = require(\"backbone-events\"),\n      SocialMedia = require(\"./social-media\"),\n      ConfirmDialogTemplate = require(\"template!confirm-dialog\"),\n      PublishDialogTemplate = require(\"template!publish-dialog\");\n  \n  function makeSharingHotLoader(options) {\n    return function hotLoadEventHandler() {\n      var socialMedia = options.socialMedia,\n          urlToShare = options.urlToShare;\n      $(\"li[data-medium]\", this).each(function() {\n        var element = $(this),\n            medium = element.attr(\"data-medium\");\n        if (!element.hasClass(\"hotloaded\") && socialMedia[medium]) {\n          socialMedia.hotLoad(element[0], socialMedia[medium], urlToShare);\n          element.addClass(\"hotloaded\");\n        }\n      });\n    };\n  }\n\n  return function(options) {\n    var modals = options.modals,\n        confirmDialog = $(ConfirmDialogTemplate()),\n        publishDialog = $(PublishDialogTemplate()),\n        dialogs = confirmDialog.add(publishDialog),\n        codeMirror = options.codeMirror,\n        publisher = options.publisher,\n        baseRemixURL = options.remixURLTemplate,\n        shareResult = $(\".share-result\", publishDialog),\n        viewLink = $(\"a.view\", publishDialog),\n        remixLink = $(\"a.remix\", publishDialog),\n        accordions = $(\"div.accordion\", publishDialog),\n        origShareHTML = $(\".thimble-additionals\", shareResult).html(),\n        currURL = null,\n        socialMedia = SocialMedia();\n\n    modals.add(dialogs);\n\n    // Add accordion behaviour to the publication dialog.\n    accordions.click(function() {\n      accordions.addClass(\"collapsed\");\n      $(this).removeClass(\"collapsed\");\n    });\n    \n    // If the user's code has errors, warn them before publishing.\n    codeMirror.on(\"reparse\", function(event) {\n      var hasErrors = event.error ? true : false;\n      confirmDialog.toggleClass(\"has-errors\", hasErrors);\n    });\n    \n    $(\".yes-button\", confirmDialog).click(function(){\n      // Reset the publish modal.\n      shareResult.unbind('.hotLoad');\n      $(\".accordion\", publishDialog).addClass(\"collapsed\");\n      $(\".publication-result\", publishDialog).removeClass(\"collapsed\");\n      $(\".thimble-additionals\", shareResult).html(origShareHTML);\n      publishDialog.addClass(\"is-publishing\");\n      \n      // Start the actual publishing process, so that hopefully by the\n      // time the transition has finished, the user's page is published.\n      var code = codeMirror.getValue(),\n          publishErrorOccurred = false;\n      publisher.saveCode(code, currURL, function(err, info) {\n        if (err) {\n          publishDialog.stop().hide();\n          modals.showErrorDialog({\n            text: \"Sorry, an error occurred while trying to publish. \" +\n                  err.responseText\n          });\n          publishErrorOccurred = true;\n        } else {\n          var viewURL = info.url;\n          var remixURL = baseRemixURL.replace(\"{{VIEW_URL}}\",\n                                              escape(info.path));\n          viewLink.attr('href', viewURL).text(viewURL);\n          remixLink.attr('href', remixURL).text(remixURL);\n          \n          shareResult.bind('click.hotLoad', makeSharingHotLoader({\n            urlToShare: viewURL,\n            socialMedia: socialMedia\n          }));\n\n          // If the user has selected the sharing accordion while\n          // we were publishing, hot-load the sharing UI immediately.\n          if (!shareResult.hasClass(\"collapsed\"))\n            shareResult.click();\n\n          // The user is now effectively remixing the page they just\n          // published.\n          currURL = viewURL;\n\n          publishDialog.removeClass(\"is-publishing\");\n          self.trigger(\"publish\", {\n            viewURL: viewURL,\n            remixURL: remixURL,\n            path: info.path\n          });\n        }\n      });\n\n      // We want the dialogs to transition while the page-sized translucent\n      // overlay stays in place. Because each dialog has its own overlay,\n      // however, this is a bit tricky. Eventually we might want to move\n      // to a DOM structure where each modal dialog shares the same overlay.\n      $(\".thimble-modal-menu\", confirmDialog).fadeOut(function() {\n        $(this).show();\n        confirmDialog.hide();\n        if (!publishErrorOccurred) {\n          publishDialog.show();\n          $(\".thimble-modal-menu\", publishDialog).hide().fadeIn();\n        }\n      });\n    });\n    \n    var self = {\n      setCurrentURL: function(url) {\n        currURL = url;\n      },\n      start: function(publishButton) {\n        var bounds = publishButton.getBoundingClientRect();\n        var dialogBoxes = $('.thimble-modal-menu', dialogs);\n        dialogBoxes.css({\n          top: bounds.bottom + 'px',\n          left: (bounds.right - dialogBoxes.width()) + 'px'\n        });\n        confirmDialog.fadeIn();\n      }\n    };\n    \n    BackboneEvents.mixin(self);\n    return self;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/relocator.js",
    "content": "\"use strict\";\n\n// code will relocate an error or help message to near where the error actually is in CodeMirror.\ndefine([\"jquery\", \"./gutter-pointer\"], function($, gutterPointer) {\n  return function Relocator(codeMirror) {\n    var lastPos = null;\n    var lastElement = null;\n    var lastGutterPointer = null;\n    var lastToggle = document.createElement(\"div\");\n\n    function flipElementIfNeeded() {\n      var coords = codeMirror.charCoords(lastPos, \"local\");\n      var bottomChar = {line: codeMirror.lineCount(), ch: 0};\n      var bottomCoords = codeMirror.charCoords(bottomChar, \"local\");\n      var height = lastElement.height();\n      var bottom = Math.max(bottomCoords.yBot,\n                            $(codeMirror.getScrollerElement()).height());\n      var isPointingDown = coords.yBot + height > bottom;\n      lastElement.toggleClass(\"flipped\", isPointingDown);\n    }\n    \n    var relocator = {\n      // clear old markings\n      cleanup: function() {\n        if (lastPos) {\n          codeMirror.setLineClass(lastPos.line, null, null);\n          codeMirror.clearMarker(lastPos.line);\n          lastPos = null;\n        }\n        if (lastElement) {\n          lastElement.hide();\n          lastElement = null;\n        }\n        if (lastGutterPointer) {\n          lastGutterPointer.remove();\n          lastGutterPointer = null;\n        }\n        if (lastToggle.parentNode) {\n          $(lastToggle).remove();\n        }\n      },\n\n      // relocate an element to inside CodeMirror, pointing \"at\" the line for startMark\n      relocate: function(element, startMark, type) {\n        var highlightClass = \"gutter-highlight-\" + type;\n\n        this.cleanup();\n        lastElement = $(element);\n\n        // find the line and character position for the start mark. We want\n        // both because the line may actually span multiple screen lines due\n        // to soft-wrapping, so we want to make sure that we point at\n        // the right one.\n        lastPos = codeMirror.posFromIndex(startMark);\n        codeMirror.setLineClass(lastPos.line, null, \"CodeMirror-line-highlight\");\n        codeMirror.setMarker(lastPos.line, null, highlightClass);\n        lastGutterPointer = gutterPointer(codeMirror, highlightClass);\n\n        codeMirror.addWidget(lastPos, lastElement[0], false);\n        $(\".up-arrow, .down-arrow\", lastElement).css({\n          left: codeMirror.charCoords(lastPos, \"local\").x + \"px\"\n        });\n        flipElementIfNeeded();\n\n        // make sure to add the end-of-line marker\n        this.setupMarker(type);\n      },\n\n      // set up the end-of-line marker for hint/error toggling\n      setupMarker: function(type) {\n        var cursorPosition = codeMirror.getCursor();\n        lastElement.hide();\n        lastToggle.lastElement = lastElement;\n        codeMirror.addWidget(lastPos, lastToggle, false);\n        lastToggle.onclick = function() {\n          lastToggle.lastElement.toggle(); \n          codeMirror.focus();\n        };\n        $(lastToggle).attr(\"class\", \"hint-marker-positioning hint-marker-\" + type).show();\n      }\n    };\n\n    return relocator;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/social-media.js",
    "content": "\"use strict\";\n\n/**\n * A tiny library for load-loading social media share buttons.\n * If we don't do this, social media will track users even before\n * they click the like button and we don't like that kind of\n * monitoring behaviour.\n */\ndefine(function() {\n  return function SocialMedia() {\n    var urlPlaceHolder = \"__URL__PLACE__HOLDER__\";\n\n    /**\n     * The various social media all have the same API.\n     */\n    var self = {\n      facebook: {\n        id: \"facebook-jssdk\",\n        src: \"//connect.facebook.net/en_US/all.js#xfbml=1\",\n        html: \"<div class='fb-like' data-href='\"+urlPlaceHolder+\"' data-send='false' data-action='recommend' data-layout='button_count' data-show-faces='false' data-font='tahoma'></div>\",\n        afterHotLoad: function() {\n          // Facebook needs additional help, because it needs\n          // to be told that it has to refresh its button, rather\n          // than simply reloading.\n          if (typeof(FB) === \"object\" && FB.XFBML && FB.XFBML.parse) {\n            FB.XFBML.parse();\n          }\n        }\n      },\n\n\n\n      google: {\n        id: \"google-plus\",\n        src: \"//apis.google.com/js/plusone.js\",\n        html: \"<g:plusone annotation='none' href='\"+urlPlaceHolder+\"'></g:plusone>\"\n      },\n\n      twitter: {\n        id: \"twitter-wjs\",\n        src: \"//platform.twitter.com/widgets.js\",\n        html: \"<a href='https://twitter.com/share'class='twitter-share-button' data-text='Check out the #MozThimble page I just made: ' data-url='\"+urlPlaceHolder+\"' data-via='Mozilla' data-count='none'>Tweet</a>\"\n      },\n\n      /**\n       * Hot-load a social medium's button by first\n       * injecting the necessary HTML for the medium\n       * to perform its own iframe replacements, and\n       * then late-loading the script required for\n       * the medium to load up its functionality.\n       */\n      hotLoad:  function(element, socialMedium, url) {\n        var oldScript = document.getElementById(socialMedium.id);\n        if (oldScript)\n          oldScript.parentNode.removeChild(oldScript);\n        // TODO: Should we escape url? It's likely\n        // to not contain any characters that need escaping, and its value\n        // is trusted, but we may still want to do it.\n        var html = socialMedium.html.replace(urlPlaceHolder, url);\n        element.innerHTML = html;\n        (function(document, id, src, url) {\n          var script = document.createElement(\"script\");\n          script.type = \"text/javascript\";\n          script.id = id;\n          script.src = src;\n          document.head.appendChild(script);\n        }(document, socialMedium.id, socialMedium.src));\n        if (socialMedium.afterHotLoad)\n          socialMedium.afterHotLoad();\n      }\n    };\n\n    return self;\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/fc/ui/text.js",
    "content": "\"use strict\";\r\n\r\ndefine([\"jquery\", \"fc/prefs\"], function($, Preferences) {\r\n  return function(options) {\r\n    var codeMirror = options.codeMirror;\r\n    var navItem = options.navItem;\r\n    var menu = navItem.find(\"ul\");\r\n    var menuItems = menu.find(\"li\");\r\n    \r\n    function menuItem(size) {\r\n      var item = $(\"li[data-size=\" + size + \"]\", menu);\r\n      return item.length ? item : null;\r\n    }\r\n    \r\n    Preferences.on(\"change:textSize\", function() {\r\n      var size = $(\"li[data-default-size]\", menu).attr(\"data-size\");\r\n      var prefSize = Preferences.get(\"textSize\");\r\n      if (prefSize && typeof(prefSize) == \"string\" && menuItem(prefSize))\r\n        size = prefSize;\r\n      \r\n      $(codeMirror.getWrapperElement()).attr(\"data-size\", size);\r\n      codeMirror.refresh();\r\n\r\n      // Reparse as well, in case there were any errors.\r\n      codeMirror.reparse();\r\n\r\n      // Mark text size in drop-down.\r\n      menuItems.removeClass(\"selected\");\r\n      menuItem(size).addClass(\"selected\");\r\n    });\r\n\r\n    /**\r\n     * Show or hide the font size drop-down menu\r\n     */\r\n    navItem.hover(function() {\r\n      var t = $(this),\r\n          lp = t.position().left;\r\n      menu.css(\"display\",\"inline\")\r\n        .css(\"left\", (lp-1) + \"px\").css(\"top\",\"7px\");\r\n      return false;\r\n    }, function() {\r\n      menu.hide();\r\n    });\r\n\r\n    /**\r\n     * bind the resize behaviour to the various text resize options\r\n     */\r\n    menuItems.click(function() {\r\n      Preferences.set(\"textSize\", $(this).attr(\"data-size\"));\r\n      Preferences.save();\r\n      menu.hide();\r\n    });\r\n    \r\n    Preferences.trigger(\"change:textSize\");\r\n  };\r\n});\r\n"
  },
  {
    "path": "site/examples/friendlycode/js/friendlycode.js",
    "content": "define(function(require) {\n  var $ = require(\"jquery\"),\n      Preferences = require(\"fc/prefs\"),\n      Editor = require(\"fc/ui/editor\"),\n      Modals = require(\"fc/ui/modals\"),\n      Parachute = require(\"fc/parachute\"),\n      CurrentPageManager = require(\"fc/current-page-manager\"),\n      Publisher = require(\"fc/publisher\"),\n      PublishUI = require(\"fc/ui/publish\"),\n      DefaultContentTemplate = require(\"template!default-content\");\n\n  Preferences.fetch();\n\n  return function FriendlycodeEditor(options) {\n    var publishURL = options.publishURL,\n        pageToLoad = options.pageToLoad,\n        defaultContent = options.defaultContent || DefaultContentTemplate(),\n        remixURLTemplate = options.remixURLTemplate ||\n          location.protocol + \"//\" + location.host + \n          location.pathname + \"#{{VIEW_URL}}\",\n        editor = Editor({\n          container: options.container,\n          allowJS: options.allowJS\n        }),\n        ready = $.Deferred();\n    \n    var modals = Modals({\n      container: $('<div class=\"friendlycode-base\"></div>')\n        .appendTo(document.body)\n    });\n    var publisher = options.publisher || Publisher(publishURL);\n    var publishUI = PublishUI({\n      modals: modals,\n      codeMirror: editor.panes.codeMirror,\n      publisher: publisher,\n      remixURLTemplate: remixURLTemplate\n    });\n    var parachute = Parachute(window, editor.panes.codeMirror);\n    var pageManager = CurrentPageManager({\n      window: window,\n      currentPage: pageToLoad\n    });\n    \n    function doneLoading() {\n      editor.container.removeClass(\"friendlycode-loading\");\n      editor.panes.codeMirror.clearHistory();\n      editor.toolbar.refresh();\n      if (parachute.restore()) {\n        editor.toolbar.showDataRestoreHelp();\n      } else {\n        // Only save data on page unload if it's different from\n        // the URL we just (hopefully) loaded.\n        parachute.refresh();\n      }\n      editor.panes.codeMirror.reparse();\n      editor.panes.codeMirror.focus();\n      editor.panes.codeMirror.refresh();\n      ready.resolve();\n    }\n\n    editor.toolbar.setStartPublish(publishUI.start);\n    editor.container.addClass(\"friendlycode-loading\");\n    publishUI.on(\"publish\", function(info) {\n      // If the user clicks their back button, we don't want to show\n      // them the page they just published--we want to show them the\n      // page the current page is based on.\n      parachute.clearCurrentPage();\n      parachute.changePage(info.path);\n      // It's possible that the server sanitized some stuff that the\n      // user will be confused by, so save the new state of the page\n      // to be what they expect it to be, just in case.\n      parachute.save();\n      // Set the URL to be the new URL to remix the page the user just\n      // published, so they can share/bookmark the URL and it'll be what \n      // they expect it to be.\n      pageManager.changePage(info.path, info.remixURL);\n    });\n    \n    parachute.changePage(pageManager.currentPage());\n\n    if (!pageManager.currentPage()) {\n      setTimeout(function() {\n        editor.panes.codeMirror.setValue(defaultContent);\n        doneLoading();\n      }, 0);\n    } else\n      publisher.loadCode(pageManager.currentPage(), function(err, data, url) {\n        if (err) {\n          modals.showErrorDialog({\n            text: 'Sorry, an error occurred while trying to get the page.'\n          });\n        } else {\n          editor.panes.codeMirror.setValue(data);\n          publishUI.setCurrentURL(url);\n          doneLoading();\n        }\n      });\n    \n    return {\n      editor: editor,\n      codeMirror: editor.panes.codeMirror,\n      publishUI: publishUI,\n      parachute: parachute,\n      ready: ready\n    };\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/jquery.no-conflict.js",
    "content": "define([\"jquery.min\"], function(jQuery) {\n  // Prevent modules from accidentally accessing the $ global rather\n  // than requesting it as a dependency.\n  //\n  // We would call jQuery.noConflict(true) to get rid of the jQuery\n  // global as well, but tabzilla relies on it in a way that prevents\n  // us from ever removing it from the global namespace.\n  jQuery.noConflict();\n  return jQuery;\n});\n"
  },
  {
    "path": "site/examples/friendlycode/js/jquery.tipsy.js",
    "content": "// tipsy, facebook style tooltips for jquery\n// version 1.0.0a\n// (c) 2008-2010 jason frame [jason@onehackoranother.com]\n// released under the MIT license\n\n(function($) {\n    \n    function maybeCall(thing, ctx) {\n        return (typeof thing == 'function') ? (thing.call(ctx)) : thing;\n    };\n    \n    function Tipsy(element, options) {\n        this.$element = $(element);\n        this.options = options;\n        this.enabled = true;\n        this.fixTitle();\n    };\n    \n    Tipsy.prototype = {\n        show: function() {\n            var title = this.getTitle();\n            if (title && this.enabled) {\n                var $tip = this.tip();\n                \n                $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);\n                $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity\n                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);\n                \n                var pos = $.extend({}, this.$element.offset(), {\n                    width: this.$element[0].offsetWidth,\n                    height: this.$element[0].offsetHeight\n                });\n                \n                var actualWidth = $tip[0].offsetWidth,\n                    actualHeight = $tip[0].offsetHeight,\n                    gravity = maybeCall(this.options.gravity, this.$element[0]);\n                \n                var tp;\n                switch (gravity.charAt(0)) {\n                    case 'n':\n                        tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};\n                        break;\n                    case 's':\n                        tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};\n                        break;\n                    case 'e':\n                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};\n                        break;\n                    case 'w':\n                        tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};\n                        break;\n                }\n                \n                if (gravity.length == 2) {\n                    if (gravity.charAt(1) == 'w') {\n                        tp.left = pos.left + pos.width / 2 - 15;\n                    } else {\n                        tp.left = pos.left + pos.width / 2 - actualWidth + 15;\n                    }\n                }\n                \n                $tip.css(tp).addClass('tipsy-' + gravity);\n                $tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);\n                if (this.options.className) {\n                    $tip.addClass(maybeCall(this.options.className, this.$element[0]));\n                }\n                \n                if (this.options.fade) {\n                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});\n                } else {\n                    $tip.css({visibility: 'visible', opacity: this.options.opacity});\n                }\n            }\n        },\n        \n        hide: function() {\n            if (this.options.fade) {\n                this.tip().stop().fadeOut(function() { $(this).remove(); });\n            } else {\n                this.tip().remove();\n            }\n        },\n        \n        fixTitle: function() {\n            var $e = this.$element;\n            if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {\n                $e.attr('original-title', $e.attr('title') || '').removeAttr('title');\n            }\n        },\n        \n        getTitle: function() {\n            var title, $e = this.$element, o = this.options;\n            this.fixTitle();\n            var title, o = this.options;\n            if (typeof o.title == 'string') {\n                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);\n            } else if (typeof o.title == 'function') {\n                title = o.title.call($e[0]);\n            }\n            title = ('' + title).replace(/(^\\s*|\\s*$)/, \"\");\n            return title || o.fallback;\n        },\n        \n        tip: function() {\n            if (!this.$tip) {\n                this.$tip = $('<div class=\"tipsy\"></div>').html('<div class=\"tipsy-arrow\"></div><div class=\"tipsy-inner\"></div>');\n            }\n            return this.$tip;\n        },\n        \n        validate: function() {\n            if (!this.$element[0].parentNode) {\n                this.hide();\n                this.$element = null;\n                this.options = null;\n            }\n        },\n        \n        enable: function() { this.enabled = true; },\n        disable: function() { this.enabled = false; },\n        toggleEnabled: function() { this.enabled = !this.enabled; }\n    };\n    \n    $.fn.tipsy = function(options) {\n        \n        if (options === true) {\n            return this.data('tipsy');\n        } else if (typeof options == 'string') {\n            var tipsy = this.data('tipsy');\n            if (tipsy) tipsy[options]();\n            return this;\n        }\n        \n        options = $.extend({}, $.fn.tipsy.defaults, options);\n        \n        function get(ele) {\n            var tipsy = $.data(ele, 'tipsy');\n            if (!tipsy) {\n                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));\n                $.data(ele, 'tipsy', tipsy);\n            }\n            return tipsy;\n        }\n        \n        function enter() {\n            var tipsy = get(this);\n            tipsy.hoverState = 'in';\n            if (options.delayIn == 0) {\n                tipsy.show();\n            } else {\n                tipsy.fixTitle();\n                setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);\n            }\n        };\n        \n        function leave() {\n            var tipsy = get(this);\n            tipsy.hoverState = 'out';\n            if (options.delayOut == 0) {\n                tipsy.hide();\n            } else {\n                setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);\n            }\n        };\n        \n        if (!options.live) this.each(function() { get(this); });\n        \n        if (options.trigger != 'manual') {\n            var binder   = options.live ? 'live' : 'bind',\n                eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',\n                eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';\n            this[binder](eventIn, enter)[binder](eventOut, leave);\n        }\n        \n        return this;\n        \n    };\n    \n    $.fn.tipsy.defaults = {\n        className: null,\n        delayIn: 0,\n        delayOut: 0,\n        fade: false,\n        fallback: '',\n        gravity: 'n',\n        html: false,\n        live: false,\n        offset: 0,\n        opacity: 0.8,\n        title: 'title',\n        trigger: 'hover'\n    };\n    \n    // Overwrite this method to provide options on a per-element basis.\n    // For example, you could store the gravity in a 'tipsy-gravity' attribute:\n    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });\n    // (remember - do not modify 'options' in place!)\n    $.fn.tipsy.elementOptions = function(ele, options) {\n        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;\n    };\n    \n    $.fn.tipsy.autoNS = function() {\n        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';\n    };\n    \n    $.fn.tipsy.autoWE = function() {\n        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';\n    };\n    \n    /**\n     * yields a closure of the supplied parameters, producing a function that takes\n     * no arguments and is suitable for use as an autogravity function like so:\n     *\n     * @param margin (int) - distance from the viewable region edge that an\n     *        element should be before setting its tooltip's gravity to be away\n     *        from that edge.\n     * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer\n     *        if there are no viewable region edges effecting the tooltip's\n     *        gravity. It will try to vary from this minimally, for example,\n     *        if 'sw' is preferred and an element is near the right viewable \n     *        region edge, but not the top edge, it will set the gravity for\n     *        that element's tooltip to be 'se', preserving the southern\n     *        component.\n     */\n     $.fn.tipsy.autoBounds = function(margin, prefer) {\n\t\treturn function() {\n\t\t\tvar dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},\n\t\t\t    boundTop = $(document).scrollTop() + margin,\n\t\t\t    boundLeft = $(document).scrollLeft() + margin,\n\t\t\t    $this = $(this);\n\n\t\t\tif ($this.offset().top < boundTop) dir.ns = 'n';\n\t\t\tif ($this.offset().left < boundLeft) dir.ew = 'w';\n\t\t\tif ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';\n\t\t\tif ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';\n\n\t\t\treturn dir.ns + (dir.ew ? dir.ew : '');\n\t\t}\n\t};\n    \n})(jQuery);\n"
  },
  {
    "path": "site/examples/friendlycode/js/lscache.js",
    "content": "/**\n * lscache library\n * Copyright (c) 2011, Pamela Fox\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*jshint undef:true, browser:true */\n\n/**\n * Creates a namespace for the lscache functions.\n */\ndefine(function() {\n  // Prefix for all lscache keys\n  var CACHE_PREFIX = 'lscache-';\n\n  // Suffix for the key name on the expiration items in localStorage\n  var CACHE_SUFFIX = '-cacheexpiration';\n\n  // expiration date radix (set to Base-36 for most space savings)\n  var EXPIRY_RADIX = 10;\n\n  // time resolution in minutes\n  var EXPIRY_UNITS = 60 * 1000;\n\n  // ECMAScript max Date (epoch + 1e8 days)\n  var MAX_DATE = Math.floor(8.64e15/EXPIRY_UNITS);\n\n  var cachedStorage;\n  var cachedJSON;\n\n  // Determines if localStorage is supported in the browser;\n  // result is cached for better performance instead of being run each time.\n  // Feature detection is based on how Modernizr does it;\n  // it's not straightforward due to FF4 issues.\n  // It's not run at parse-time as it takes 200ms in Android.\n  function supportsStorage() {\n    var key = '__lscachetest__';\n    var value = key;\n\n    if (cachedStorage !== undefined) {\n      return cachedStorage;\n    }\n\n    try {\n      setItem(key, value);\n      removeItem(key);\n      cachedStorage = true;\n    } catch (exc) {\n      cachedStorage = false;\n    }\n    return cachedStorage;\n  }\n\n  // Determines if native JSON (de-)serialization is supported in the browser.\n  function supportsJSON() {\n    /*jshint eqnull:true */\n    if (cachedJSON === undefined) {\n      cachedJSON = (window.JSON != null);\n    }\n    return cachedJSON;\n  }\n\n  /**\n   * Returns the full string for the localStorage expiration item.\n   * @param {String} key\n   * @return {string}\n   */\n  function expirationKey(key) {\n    return key + CACHE_SUFFIX;\n  }\n\n  /**\n   * Returns the number of minutes since the epoch.\n   * @return {number}\n   */\n  function currentTime() {\n    return Math.floor((new Date().getTime())/EXPIRY_UNITS);\n  }\n\n  /**\n   * Wrapper functions for localStorage methods\n   */\n\n  function getItem(key) {\n    return localStorage.getItem(CACHE_PREFIX + key);\n  }\n\n  function setItem(key, value) {\n    // Fix for iPad issue - sometimes throws QUOTA_EXCEEDED_ERR on setItem.\n    localStorage.removeItem(CACHE_PREFIX + key);\n    localStorage.setItem(CACHE_PREFIX + key, value);\n  }\n\n  function removeItem(key) {\n    localStorage.removeItem(CACHE_PREFIX + key);\n  }\n\n  return {\n\n    /**\n     * Stores the value in localStorage. Expires after specified number of minutes.\n     * @param {string} key\n     * @param {Object|string} value\n     * @param {number} time\n     */\n    set: function(key, value, time) {\n      if (!supportsStorage()) return;\n\n      // If we don't get a string value, try to stringify\n      // In future, localStorage may properly support storing non-strings\n      // and this can be removed.\n      if (typeof value !== 'string') {\n        if (!supportsJSON()) return;\n        try {\n          value = JSON.stringify(value);\n        } catch (e) {\n          // Sometimes we can't stringify due to circular refs\n          // in complex objects, so we won't bother storing then.\n          return;\n        }\n      }\n\n      try {\n        setItem(key, value);\n      } catch (e) {\n        if (e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {\n          // If we exceeded the quota, then we will sort\n          // by the expire time, and then remove the N oldest\n          var storedKeys = [];\n          var storedKey;\n          for (var i = 0; i < localStorage.length; i++) {\n            storedKey = localStorage.key(i);\n\n            if (storedKey.indexOf(CACHE_PREFIX) === 0 && storedKey.indexOf(CACHE_SUFFIX) < 0) {\n              var mainKey = storedKey.substr(CACHE_PREFIX.length);\n              var exprKey = expirationKey(mainKey);\n              var expiration = getItem(exprKey);\n              if (expiration) {\n                expiration = parseInt(expiration, EXPIRY_RADIX);\n              } else {\n                // TODO: Store date added for non-expiring items for smarter removal\n                expiration = MAX_DATE;\n              }\n              storedKeys.push({\n                key: mainKey,\n                size: (getItem(mainKey)||'').length,\n                expiration: expiration\n              });\n            }\n          }\n          // Sorts the keys with oldest expiration time last\n          storedKeys.sort(function(a, b) { return (b.expiration-a.expiration); });\n\n          var targetSize = (value||'').length;\n          while (storedKeys.length && targetSize > 0) {\n            storedKey = storedKeys.pop();\n            removeItem(storedKey.key);\n            removeItem(expirationKey(storedKey.key));\n            targetSize -= storedKey.size;\n          }\n          try {\n            setItem(key, value);\n          } catch (e) {\n            // value may be larger than total quota\n            return;\n          }\n        } else {\n          // If it was some other error, just give up.\n          return;\n        }\n      }\n\n      // If a time is specified, store expiration info in localStorage\n      if (time) {\n        setItem(expirationKey(key), (currentTime() + time).toString(EXPIRY_RADIX));\n      } else {\n        // In case they previously set a time, remove that info from localStorage.\n        removeItem(expirationKey(key));\n      }\n    },\n\n    /**\n     * Retrieves specified value from localStorage, if not expired.\n     * @param {string} key\n     * @return {string|Object}\n     */\n    get: function(key) {\n      if (!supportsStorage()) return null;\n\n      // Return the de-serialized item if not expired\n      var exprKey = expirationKey(key);\n      var expr = getItem(exprKey);\n\n      if (expr) {\n        var expirationTime = parseInt(expr, EXPIRY_RADIX);\n\n        // Check if we should actually kick item out of storage\n        if (currentTime() >= expirationTime) {\n          removeItem(key);\n          removeItem(exprKey);\n          return null;\n        }\n      }\n\n      // Tries to de-serialize stored value if its an object, and returns the normal value otherwise.\n      var value = getItem(key);\n      if (!value || !supportsJSON()) {\n        return value;\n      }\n\n      try {\n        // We can't tell if its JSON or a string, so we try to parse\n        return JSON.parse(value);\n      } catch (e) {\n        // If we can't parse, it's probably because it isn't an object\n        return value;\n      }\n    },\n\n    /**\n     * Removes a value from localStorage.\n     * Equivalent to 'delete' in memcache, but that's a keyword in JS.\n     * @param {string} key\n     */\n    remove: function(key) {\n      if (!supportsStorage()) return null;\n      removeItem(key);\n      removeItem(expirationKey(key));\n    },\n\n    /**\n     * Returns whether local storage is supported.\n     * Currently exposed for testing purposes.\n     * @return {boolean}\n     */\n    supported: function() {\n      return supportsStorage();\n    },\n\n    /**\n     * Flushes all lscache items and expiry markers without affecting rest of localStorage\n     */\n    flush: function() {\n      if (!supportsStorage()) return;\n\n      // Loop in reverse as removing items will change indices of tail\n      for (var i = localStorage.length-1; i >= 0 ; --i) {\n        var key = localStorage.key(i);\n        if (key.indexOf(CACHE_PREFIX) === 0) {\n          localStorage.removeItem(key);\n        }\n      }\n    }\n  };\n});"
  },
  {
    "path": "site/examples/friendlycode/js/require-config.js",
    "content": "var require = {\n  baseUrl: \"js\",\n  shim: {\n    underscore: {\n      exports: function() {\n        return _.noConflict();\n      }\n    },\n    // Apparently jQuery 1.7 and above uses a named define(), which\n    // makes it a bona fide module which doesn't need a shim. However,\n    // it also doesn't bother calling jQuery.noConflict(), which we\n    // want, so we do a bit of configuration ridiculousness to\n    // accomplish this.\n    \"jquery.min\": {\n      exports: 'jQuery'\n    },\n    \"jquery-tipsy\": {\n      deps: [\"jquery\"],\n      exports: 'jQuery'\n    },\n    \"jquery-slowparse\": {\n      deps: [\"jquery\"],\n      exports: \"jQuery\"\n    },\n    backbone: {\n      deps: [\"underscore\", \"jquery\"],\n      exports: function() {\n        return Backbone.noConflict();\n      }\n    },\n    codemirror: {\n      exports: \"CodeMirror\"\n    },\n    \"codemirror/xml\": {\n      deps: [\"codemirror\"],\n      exports: \"CodeMirror\"\n    },\n    \"codemirror/javascript\": {\n      deps: [\"codemirror\"],\n      exports: \"CodeMirror\"\n    },\n    \"codemirror/css\": {\n      deps: [\"codemirror\"],\n      exports: \"CodeMirror\"\n    },\n    \"codemirror/html\": {\n      deps: [\n        \"codemirror/xml\",\n        \"codemirror/javascript\",\n        \"codemirror/css\"\n      ],\n      exports: \"CodeMirror\"\n    }\n  },\n  paths: {\n    jquery: \"jquery.no-conflict\",\n    \"jquery-tipsy\": \"jquery.tipsy\",\n    \"jquery-slowparse\": \"../slowparse/spec/errors.jquery\",\n    underscore: \"underscore.min\",\n    backbone: \"backbone.min\",\n    slowparse: \"../slowparse\",\n    codemirror: \"../codemirror2/lib/codemirror\",\n    \"codemirror/xml\": \"../codemirror2/mode/xml/xml\",\n    \"codemirror/javascript\": \"../codemirror2/mode/javascript/javascript\",\n    \"codemirror/css\": \"../codemirror2/mode/css/css\",\n    \"codemirror/html\": \"../codemirror2/mode/htmlmixed/htmlmixed\",\n    text: \"require-plugins/text\",\n    template: \"require-plugins/template\",\n    test: \"../test\",\n    templates: \"../templates\"\n  }\n};\n\nif (typeof(module) == 'object' && module.exports)\n  module.exports = require;\nelse (function() {\n  var RE = /^(https?:)\\/\\/([^\\/]+)\\/(.*)\\/require-config\\.js$/;\n  var me = document.querySelector('script[src$=\"require-config.js\"]');\n  var console = window.console || {log: function() {}};\n  if (me) {\n    var parts = me.src.match(RE);\n    if (parts) {\n      var protocol = parts[1];\n      var host = parts[2];\n      var path = '/' + parts[3];\n      if (protocol != location.protocol || host != location.host)\n        console.log(\"origins are different. requirejs text plugin may \" +\n                    \"not work.\");\n      require.baseUrl = path;\n    }\n  }\n  console.log('require.baseUrl is ' + require.baseUrl);\n})();\n"
  },
  {
    "path": "site/examples/friendlycode/js/require-plugins/template.js",
    "content": "// This is a simple RequireJS plugin that loads an underscore.js template.\ndefine([\"module\", \"text\", \"underscore\"], function (module, text, _) {\n  var buildMap = {},\n      masterConfig = module.config();\n\n  return {\n    load: function(name, req, onLoad, config) {\n      var url = req.toUrl(\"templates/\" + name).replace(\".js\", \".html\");\n\n      text.get(url, function (data) {\n        var template;\n        if (config.isBuild) {\n          template = buildMap[name] = \"_.template(\" + JSON.stringify(data)  +\n                     \")\";\n        } else {\n          template = _.template(data);\n        }\n\n        onLoad(template);\n      });\n    },\n    write: function (pluginName, moduleName, write) {\n      if (buildMap[moduleName]) {\n        var content = buildMap[moduleName];\n        write.asModule(pluginName + \"!\" + moduleName,\n          \"define(['underscore'], function (_) { \\n  return \" + content +\n          \";});\\n\");\n      }\n    }\n  };\n});"
  },
  {
    "path": "site/examples/friendlycode/js/require-plugins/text.js",
    "content": "/*\n RequireJS text 1.0.8 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.\n Available via the MIT or new BSD license.\n see: http://github.com/jrburke/requirejs for details\n*/\n(function(){var k=[\"Msxml2.XMLHTTP\",\"Microsoft.XMLHTTP\",\"Msxml2.XMLHTTP.4.0\"],m=/^\\s*<\\?xml(\\s)+version=[\\'\\\"](\\d)*.(\\d)*[\\'\\\"](\\s)*\\?>/im,n=/<body[^>]*>\\s*([\\s\\S]+)\\s*<\\/body>/im,i=typeof location!==\"undefined\"&&location.href,o=i&&location.protocol&&location.protocol.replace(/\\:/,\"\"),p=i&&location.hostname,q=i&&(location.port||void 0),j=[];define(function(){var e,l;e={version:\"1.0.8\",strip:function(a){if(a){var a=a.replace(m,\"\"),c=a.match(n);c&&(a=c[1])}else a=\"\";return a},jsEscape:function(a){return a.replace(/(['\\\\])/g,\n\"\\\\$1\").replace(/[\\f]/g,\"\\\\f\").replace(/[\\b]/g,\"\\\\b\").replace(/[\\n]/g,\"\\\\n\").replace(/[\\t]/g,\"\\\\t\").replace(/[\\r]/g,\"\\\\r\")},createXhr:function(){var a,c,b;if(typeof XMLHttpRequest!==\"undefined\")return new XMLHttpRequest;else if(typeof ActiveXObject!==\"undefined\")for(c=0;c<3;c++){b=k[c];try{a=new ActiveXObject(b)}catch(f){}if(a){k=[b];break}}return a},parseName:function(a){var c=!1,b=a.indexOf(\".\"),f=a.substring(0,b),a=a.substring(b+1,a.length),b=a.indexOf(\"!\");b!==-1&&(c=a.substring(b+1,a.length),\nc=c===\"strip\",a=a.substring(0,b));return{moduleName:f,ext:a,strip:c}},xdRegExp:/^((\\w+)\\:)?\\/\\/([^\\/\\\\]+)/,useXhr:function(a,c,b,f){var d=e.xdRegExp.exec(a),g;if(!d)return!0;a=d[2];d=d[3];d=d.split(\":\");g=d[1];d=d[0];return(!a||a===c)&&(!d||d===b)&&(!g&&!d||g===f)},finishLoad:function(a,c,b,f,d){b=c?e.strip(b):b;d.isBuild&&(j[a]=b);f(b)},load:function(a,c,b,f){if(f.isBuild&&!f.inlineText)b();else{var d=e.parseName(a),g=d.moduleName+\".\"+d.ext,h=c.toUrl(g),r=f&&f.text&&f.text.useXhr||e.useXhr;!i||r(h,\no,p,q)?e.get(h,function(c){e.finishLoad(a,d.strip,c,b,f)}):c([g],function(a){e.finishLoad(d.moduleName+\".\"+d.ext,d.strip,a,b,f)})}},write:function(a,c,b){if(j.hasOwnProperty(c)){var f=e.jsEscape(j[c]);b.asModule(a+\"!\"+c,\"define(function () { return '\"+f+\"';});\\n\")}},writeFile:function(a,c,b,f,d){var c=e.parseName(c),g=c.moduleName+\".\"+c.ext,h=b.toUrl(c.moduleName+\".\"+c.ext)+\".js\";e.load(g,b,function(){var b=function(a){return f(h,a)};b.asModule=function(a,b){return f.asModule(a,h,b)};e.write(a,g,\nb,d)},d)}};if(e.createXhr())e.get=function(a,c){var b=e.createXhr();b.open(\"GET\",a,!0);b.onreadystatechange=function(){b.readyState===4&&c(b.responseText)};b.send(null)};else if(typeof process!==\"undefined\"&&process.versions&&process.versions.node)l=require.nodeRequire(\"fs\"),e.get=function(a,c){var b=l.readFileSync(a,\"utf8\");b.indexOf(\"\\ufeff\")===0&&(b=b.substring(1));c(b)};else if(typeof Packages!==\"undefined\")e.get=function(a,c){var b=new java.io.File(a),f=java.lang.System.getProperty(\"line.separator\"),\nb=new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(b),\"utf-8\")),d,e,h=\"\";try{d=new java.lang.StringBuffer;(e=b.readLine())&&e.length()&&e.charAt(0)===65279&&(e=e.substring(1));for(d.append(e);(e=b.readLine())!==null;)d.append(f),d.append(e);h=String(d.toString())}finally{b.close()}c(h)};return e})})();\n"
  },
  {
    "path": "site/examples/friendlycode/js/slowparse-errors.js",
    "content": "\"use strict\";\n\ndefine([\n  'jquery-slowparse',\n  'text!slowparse/spec/errors.base.html',\n  'text!slowparse/spec/errors.forbidjs.html'\n], function($, base, forbidjs) {\n  [base, forbidjs].forEach(function(html) {\n    var div = $('<div></div>').html(html);\n    $.errorTemplates = $.errorTemplates.add($(\".error-msg\", div));\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/package.json",
    "content": "{\n  \"name\": \"build-require\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"description\": \"requirejs optimization script\",\n  \"main\": \"build-require.js\",\n  \"dependencies\": {\n    \"requirejs\": \"~2.x\"\n  },\n  \"scripts\": {\n    \"start\": \"node build-require.js\"\n  }\n}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/.gitignore",
    "content": "docs\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/LICENSE.html",
    "content": "<!DOCTYPE html>\n<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n  <meta charset=\"utf-8\">\n  <meta name=\"generator\" content=\"pandoc\">\n  <title>Mozilla Public License, version 2.0</title>\n  <!--[if lt IE 9]>\n    <script src=\"http://html5shim.googlecode.com/svn/trunk/html5.js\"></script>\n  <![endif]-->\n\n  <link href=\"LICENSE_files/css_002.css\" rel=\"stylesheet\" type=\"text/css\">\n  <link href=\"LICENSE_files/css_003.css\" rel=\"stylesheet\" type=\"text/css\">\n  <link href=\"LICENSE_files/css.css\" rel=\"stylesheet\" type=\"text/css\">\n\n  <style type=\"text/css\">\n\tbody { \tfont-family: 'Crimson Text', serif; \n\t\tmax-width: 30em; \n\t\tmargin-left:auto;\n\t\tmargin-right:auto;\n\t\ttext-align: justify;\n\t\t-moz-hyphens: auto;\n\t\tfont-size: 110%\n\t\t}\n\n\th1, h2, h3 { \n\t\tfont-family: 'Lora', serif;\n\t     \tfont-variant: small-caps;\n\t\t}\n\n\th1 { \n\t\ttext-align: center;\n\t\t-moz-hyphens: none;\n\t\tfont-size: 160%;\n\t\t}\n\th2 {\n\t\tfont-size: 140%;\n\t\t-moz-hyphens: none;\n\t\ttext-align: left;\n\t\t}\n\th3 {\t\n\t\tfont-size: 120%;\n\t\t-moz-hyphens: none;\n\t\ttext-align: left;\t\t\n\t\t}\n\n\tblockquote { \t\n\t\tfont-family: 'Droid Sans Mono', mono;\n\t\ttext-align: left; \n\t\t-moz-hyphens: none;\n\t\t}\n\t\n\tcode {\n\t\tfont-family: 'Droid Sans Mono', mono;\n\t\t}\n\n\tem {\n\t\tbackground: #FEFD80;\n\t\tborder: 30px solid #FEFD80;\n\t\tfloat: left;\n\t\tline-height: 1.25em;\n    \t\tmargin-left: 10px;\n\t\tmargin-right: 10px;\n\t\tmargin-bottom: 10px;\n\t\tmargin-top:-10px;\n/*\t\ttext-transform: uppercase; */\n\t\tfont-style: normal;\n\t}\n\n\tdt {\tfont-family: 'Lora', serif;\n\t\tfont-weight: bold; \n\t\tfont-size: 100%;\n\t\t}\n\n  </style>\n</head>\n<body>\n<h1 id=\"mozilla-public-license-version-2.0\">Mozilla Public License<br>Version 2.0</h1>\n<h2 id=\"definitions\">1. Definitions</h2>\n<dl>\n<dt>1.1. “Contributor”</dt>\n<dd><p>means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software.</p>\n</dd>\n<dt>1.2. “Contributor Version”</dt>\n<dd><p>means the combination of the Contributions of others (if any) \nused by a Contributor and that particular Contributor’s Contribution.</p>\n</dd>\n<dt>1.3. “Contribution”</dt>\n<dd><p>means Covered Software of a particular Contributor.</p>\n</dd>\n<dt>1.4. “Covered Software”</dt>\n<dd><p>means Source Code Form to which the initial Contributor has \nattached the notice in Exhibit A, the Executable Form of such Source \nCode Form, and Modifications of such Source Code Form, in each case \nincluding portions thereof.</p>\n</dd>\n<dt>1.5. “Incompatible With Secondary Licenses”</dt>\n<dd><p>means</p>\n<ol type=\"a\">\n<li><p>that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or</p></li>\n<li><p>that the Covered Software was made available under the terms of \nversion 1.1 or earlier of the License, but not also under the terms of a\n Secondary License.</p></li>\n</ol>\n</dd>\n<dt>1.6. “Executable Form”</dt>\n<dd><p>means any form of the work other than Source Code Form.</p>\n</dd>\n<dt>1.7. “Larger Work”</dt>\n<dd><p>means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software.</p>\n</dd>\n<dt>1.8. “License”</dt>\n<dd><p>means this document.</p>\n</dd>\n<dt>1.9. “Licensable”</dt>\n<dd><p>means having the right to grant, to the maximum extent possible, \nwhether at the time of the initial grant or subsequently, any and all of\n the rights conveyed by this License.</p>\n</dd>\n<dt>1.10. “Modifications”</dt>\n<dd><p>means any of the following:</p>\n<ol type=\"a\">\n<li><p>any file in Source Code Form that results from an addition to, \ndeletion from, or modification of the contents of Covered Software; or</p></li>\n<li><p>any new file in Source Code Form that contains any Covered Software.</p></li>\n</ol>\n</dd>\n<dt>1.11. “Patent Claims” of a Contributor</dt>\n<dd><p>means any patent claim(s), including without limitation, method, \nprocess, and apparatus claims, in any patent Licensable by such \nContributor that would be infringed, but for the grant of the License, \nby the making, using, selling, offering for sale, having made, import, \nor transfer of either its Contributions or its Contributor Version.</p>\n</dd>\n<dt>1.12. “Secondary License”</dt>\n<dd><p>means either the GNU General Public License, Version 2.0, the GNU\n Lesser General Public License, Version 2.1, the GNU Affero General \nPublic License, Version 3.0, or any later versions of those licenses.</p>\n</dd>\n<dt>1.13. “Source Code Form”</dt>\n<dd><p>means the form of the work preferred for making modifications.</p>\n</dd>\n<dt>1.14. “You” (or “Your”)</dt>\n<dd><p>means an individual or a legal entity exercising rights under \nthis License. For legal entities, “You” includes any entity that \ncontrols, is controlled by, or is under common control with You. For \npurposes of this definition, “control” means (a) the power, direct or \nindirect, to cause the direction or management of such entity, whether \nby contract or otherwise, or (b) ownership of more than fifty percent \n(50%) of the outstanding shares or beneficial ownership of such entity.</p>\n</dd>\n</dl>\n<h2 id=\"license-grants-and-conditions\">2. License Grants and Conditions</h2>\n<h3 id=\"grants\">2.1. Grants</h3>\n<p>Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license:</p>\n<ol type=\"a\">\n<li><p>under intellectual property rights (other than patent or \ntrademark) Licensable by such Contributor to use, reproduce, make \navailable, modify, display, perform, distribute, and otherwise exploit \nits Contributions, either on an unmodified basis, with Modifications, or\n as part of a Larger Work; and</p></li>\n<li><p>under Patent Claims of such Contributor to make, use, sell, offer\n for sale, have made, import, and otherwise transfer either its \nContributions or its Contributor Version.</p></li>\n</ol>\n<h3 id=\"effective-date\">2.2. Effective Date</h3>\n<p>The licenses granted in Section&nbsp;2.1 with respect to any \nContribution become effective for each Contribution on the date the \nContributor first distributes such Contribution.</p>\n<h3 id=\"limitations-on-grant-scope\">2.3. Limitations on Grant Scope</h3>\n<p>The licenses granted in this Section&nbsp;2 are the only rights \ngranted under this License. No additional rights or licenses will be \nimplied from the distribution or licensing of Covered Software under \nthis License. Notwithstanding Section&nbsp;2.1(b) above, no patent \nlicense is granted by a Contributor:</p>\n<ol type=\"a\">\n<li><p>for any code that a Contributor has removed from Covered Software; or</p></li>\n<li><p>for infringements caused by: (i) Your and any other third party’s\n modifications of Covered Software, or (ii) the combination of its \nContributions with other software (except as part of its Contributor \nVersion); or</p></li>\n<li><p>under Patent Claims infringed by Covered Software in the absence of its Contributions.</p></li>\n</ol>\n<p>This License does not grant any rights in the trademarks, service \nmarks, or logos of any Contributor (except as may be necessary to comply\n with the notice requirements in Section&nbsp;3.4).</p>\n<h3 id=\"subsequent-licenses\">2.4. Subsequent Licenses</h3>\n<p>No Contributor makes additional grants as a result of Your choice to \ndistribute the Covered Software under a subsequent version of this \nLicense (see Section&nbsp;10.2) or under the terms of a Secondary \nLicense (if permitted under the terms of Section&nbsp;3.3).</p>\n<h3 id=\"representation\">2.5. Representation</h3>\n<p>Each Contributor represents that the Contributor believes its \nContributions are its original creation(s) or it has sufficient rights \nto grant the rights to its Contributions conveyed by this License.</p>\n<h3 id=\"fair-use\">2.6. Fair Use</h3>\n<p>This License is not intended to limit any rights You have under \napplicable copyright doctrines of fair use, fair dealing, or other \nequivalents.</p>\n<h3 id=\"conditions\">2.7. Conditions</h3>\n<p>Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section&nbsp;2.1.</p>\n<h2 id=\"responsibilities\">3. Responsibilities</h2>\n<h3 id=\"distribution-of-source-form\">3.1. Distribution of Source Form</h3>\n<p>All distribution of Covered Software in Source Code Form, including \nany Modifications that You create or to which You contribute, must be \nunder the terms of this License. You must inform recipients that the \nSource Code Form of the Covered Software is governed by the terms of \nthis License, and how they can obtain a copy of this License. You may \nnot attempt to alter or restrict the recipients’ rights in the Source \nCode Form.</p>\n<h3 id=\"distribution-of-executable-form\">3.2. Distribution of Executable Form</h3>\n<p>If You distribute Covered Software in Executable Form then:</p>\n<ol type=\"a\">\n<li><p>such Covered Software must also be made available in Source Code \nForm, as described in Section&nbsp;3.1, and You must inform recipients \nof the Executable Form how they can obtain a copy of such Source Code \nForm by reasonable means in a timely manner, at a charge no more than \nthe cost of distribution to the recipient; and</p></li>\n<li><p>You may distribute such Executable Form under the terms of this \nLicense, or sublicense it under different terms, provided that the \nlicense for the Executable Form does not attempt to limit or alter the \nrecipients’ rights in the Source Code Form under this License.</p></li>\n</ol>\n<h3 id=\"distribution-of-a-larger-work\">3.3. Distribution of a Larger Work</h3>\n<p>You may create and distribute a Larger Work under terms of Your \nchoice, provided that You also comply with the requirements of this \nLicense for the Covered Software. If the Larger Work is a combination of\n Covered Software with a work governed by one or more Secondary \nLicenses, and the Covered Software is not Incompatible With Secondary \nLicenses, this License permits You to additionally distribute such \nCovered Software under the terms of such Secondary License(s), so that \nthe recipient of the Larger Work may, at their option, further \ndistribute the Covered Software under the terms of either this License \nor such Secondary License(s).</p>\n<h3 id=\"notices\">3.4. Notices</h3>\n<p>You may not remove or alter the substance of any license notices \n(including copyright notices, patent notices, disclaimers of warranty, \nor limitations of liability) contained within the Source Code Form of \nthe Covered Software, except that You may alter any license notices to \nthe extent required to remedy known factual inaccuracies.</p>\n<h3 id=\"application-of-additional-terms\">3.5. Application of Additional Terms</h3>\n<p>You may choose to offer, and to charge a fee for, warranty, support, \nindemnity or liability obligations to one or more recipients of Covered \nSoftware. However, You may do so only on Your own behalf, and not on \nbehalf of any Contributor. You must make it absolutely clear that any \nsuch warranty, support, indemnity, or liability obligation is offered by\n You alone, and You hereby agree to indemnify every Contributor for any \nliability incurred by such Contributor as a result of warranty, support,\n indemnity or liability terms You offer. You may include additional \ndisclaimers of warranty and limitations of liability specific to any \njurisdiction.</p>\n<h2 id=\"inability-to-comply-due-to-statute-or-regulation\">4. Inability to Comply Due to Statute or Regulation</h2>\n<p>If it is impossible for You to comply with any of the terms of this \nLicense with respect to some or all of the Covered Software due to \nstatute, judicial order, or regulation then You must: (a) comply with \nthe terms of this License to the maximum extent possible; and (b) \ndescribe the limitations and the code they affect. Such description must\n be placed in a text file included with all distributions of the Covered\n Software under this License. Except to the extent prohibited by statute\n or regulation, such description must be sufficiently detailed for a \nrecipient of ordinary skill to be able to understand it.</p>\n<h2 id=\"termination\">5. Termination</h2>\n<p>5.1. The rights granted under this License will terminate \nautomatically if You fail to comply with any of its terms. However, if \nYou become compliant, then the rights granted under this License from a \nparticular Contributor are reinstated (a) provisionally, unless and \nuntil such Contributor explicitly and finally terminates Your grants, \nand (b) on an ongoing basis, if such Contributor fails to notify You of \nthe non-compliance by some reasonable means prior to 60 days after You \nhave come back into compliance. Moreover, Your grants from a particular \nContributor are reinstated on an ongoing basis if such Contributor \nnotifies You of the non-compliance by some reasonable means, this is the\n first time You have received notice of non-compliance with this License\n from such Contributor, and You become compliant prior to 30 days after \nYour receipt of the notice.</p>\n<p>5.2. If You initiate litigation against any entity by asserting a \npatent infringement claim (excluding declaratory judgment actions, \ncounter-claims, and cross-claims) alleging that a Contributor Version \ndirectly or indirectly infringes any patent, then the rights granted to \nYou by any and all Contributors for the Covered Software under \nSection&nbsp;2.1 of this License shall terminate.</p>\n<p>5.3. In the event of termination under Sections&nbsp;5.1 or 5.2 \nabove, all end user license agreements (excluding distributors and \nresellers) which have been validly granted by You or Your distributors \nunder this License prior to termination shall survive termination.</p>\n<h2 id=\"disclaimer-of-warranty\">6. Disclaimer of Warranty</h2>\n<p><em>Covered Software is provided under this License on an “as is” \nbasis, without warranty of any kind, either expressed, implied, or \nstatutory, including, without limitation, warranties that the Covered \nSoftware is free of defects, merchantable, fit for a particular purpose \nor non-infringing. The entire risk as to the quality and performance of \nthe Covered Software is with You. Should any Covered Software prove \ndefective in any respect, You (not any Contributor) assume the cost of \nany necessary servicing, repair, or correction. This disclaimer of \nwarranty constitutes an essential part of this License. No use of any \nCovered Software is authorized under this License except under this \ndisclaimer.</em></p>\n<h2 id=\"limitation-of-liability\">7. Limitation of Liability</h2>\n<p><em>Under no circumstances and under no legal theory, whether tort \n(including negligence), contract, or otherwise, shall any Contributor, \nor anyone who distributes Covered Software as permitted above, be liable\n to You for any direct, indirect, special, incidental, or consequential \ndamages of any character including, without limitation, damages for lost\n profits, loss of goodwill, work stoppage, computer failure or \nmalfunction, or any and all other commercial damages or losses, even if \nsuch party shall have been informed of the possibility of such damages. \nThis limitation of liability shall not apply to liability for death or \npersonal injury resulting from such party’s negligence to the extent \napplicable law prohibits such limitation. Some jurisdictions do not \nallow the exclusion or limitation of incidental or consequential \ndamages, so this exclusion and limitation may not apply to You.</em></p>\n<h2 id=\"litigation\">8. Litigation</h2>\n<p>Any litigation relating to this License may be brought only in the \ncourts of a jurisdiction where the defendant maintains its principal \nplace of business and such litigation shall be governed by laws of that \njurisdiction, without reference to its conflict-of-law provisions. \nNothing in this Section shall prevent a party’s ability to bring \ncross-claims or counter-claims.</p>\n<h2 id=\"miscellaneous\">9. Miscellaneous</h2>\n<p>This License represents the complete agreement concerning the subject\n matter hereof. If any provision of this License is held to be \nunenforceable, such provision shall be reformed only to the extent \nnecessary to make it enforceable. Any law or regulation which provides \nthat the language of a contract shall be construed against the drafter \nshall not be used to construe this License against a Contributor.</p>\n<h2 id=\"versions-of-the-license\">10. Versions of the License</h2>\n<h3 id=\"new-versions\">10.1. New Versions</h3>\n<p>Mozilla Foundation is the license steward. Except as provided in \nSection&nbsp;10.3, no one other than the license steward has the right \nto modify or publish new versions of this License. Each version will be \ngiven a distinguishing version number.</p>\n<h3 id=\"effect-of-new-versions\">10.2. Effect of New Versions</h3>\n<p>You may distribute the Covered Software under the terms of the \nversion of the License under which You originally received the Covered \nSoftware, or under the terms of any subsequent version published by the \nlicense steward.</p>\n<h3 id=\"modified-versions\">10.3. Modified Versions</h3>\n<p>If you create software not governed by this License, and you want to \ncreate a new license for such software, you may create and use a \nmodified version of this License if you rename the license and remove \nany references to the name of the license steward (except to note that \nsuch modified license differs from this License).</p>\n<h3 id=\"distributing-source-code-form-that-is-incompatible-with-secondary-licenses\">10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses</h3>\n<p>If You choose to distribute Source Code Form that is Incompatible \nWith Secondary Licenses under the terms of this version of the License, \nthe notice described in Exhibit B of this License must be attached.</p>\n<h2 id=\"exhibit-a---source-code-form-license-notice\">Exhibit A - Source Code Form License Notice</h2>\n<blockquote>\n<p>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/.</p>\n</blockquote>\n<p>If it is not possible or desirable to put the notice in a particular \nfile, then You may include the notice in a location (such as a LICENSE \nfile in a relevant directory) where a recipient would be likely to look \nfor such a notice.</p>\n<p>You may add additional accurate notices of copyright ownership.</p>\n<h2 id=\"exhibit-b---incompatible-with-secondary-licenses-notice\">Exhibit B - “Incompatible With Secondary Licenses” Notice</h2>\n<blockquote>\n<p>This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.</p>\n</blockquote>\n\n\n</body></html>"
  },
  {
    "path": "site/examples/friendlycode/slowparse/LICENSE_files/css.css",
    "content": "@font-face {\n  font-family: 'Droid Sans Mono';\n  font-style: normal;\n  font-weight: normal;\n  src: local('Droid Sans Mono'), local('DroidSansMono'), url('http://themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJaH0X__W3S3MJL29bc5CWfs.woff') format('woff');\n}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/LICENSE_files/css_002.css",
    "content": "@font-face {\n  font-family: 'Crimson Text';\n  font-style: normal;\n  font-weight: normal;\n  src: local('Crimson Text'), local('CrimsonText-Roman'), url('http://themes.googleusercontent.com/static/fonts/crimsontext/v3/3IFMwfRa07i-auYR-B-zNaRDOzjiPcYnFooOUGCOsRk.woff') format('woff');\n}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/LICENSE_files/css_003.css",
    "content": "@font-face {\n  font-family: 'Lora';\n  font-style: normal;\n  font-weight: normal;\n  src: local('Lora'), url('http://themes.googleusercontent.com/static/fonts/lora/v5/nAKwuw6_dIh5kwvpj3ShNfesZW2xOQ-xsNqO47m55DA.woff') format('woff');\n}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/README.md",
    "content": "Slowparse is an experimental JavaScript-based HTML parser for Mozilla Webmaking initiatives.\n\nUntil now, most of Mozilla's Webmaking experiments that involve writing HTML ([lovebomb.me][], [Storything][], [X-Ray Goggles][], etc) have used `.innerHTML` to parse HTML into a DOM. However, this has a number of disadvantages:\n\n* It's difficult to map an element in the generated DOM back to its location in the original HTML source code. This is useful in a variety of scenarios such as Jessica Klein's [lovebomb mockups][] and [webmaker tutorials][].\n\n* It's completely insecure. For our webmaker initiatives that really need to scale, we'd like to have more fine-grained control over what kinds of elements and attributes are allowed in code.\n\n* It can be difficult to help the user pinpoint errors in their code, e.g. mismatching tags.\n\nSlowparse is intended to solve all of these problems. It parses HTML and uses a host DOM implementation to create the DOM representation of the page. Each generated DOM node has an expando property called `parseInfo` which provides metadata mapping the location of the node in the original source code. It also provides detailed error feedback so that users can easily pinpoint why their code isn't working the way they intend.\n\nFor more information, see:\n\n  * A [live demo][] to see how Slowparse interprets your code in real-time.\n  * The [error reporting specification][] to get an idea of what kinds of errors can be reported, and what their human-friendly descriptions are.\n  * The annotated source code for [slowparse.js][], [tree-inspectors.js][], and [spec/errors.jquery.js][].\n  * The [test suite][].\n  * The blog post [Learning and Grammatical Forgiveness][learning], which explains why Slowparse isn't an HTML/CSS validator.\n\n  [lovebomb.me]: http://lovebomb.me\n  [Storything]: http://storything.toolness.org/\n  [X-Ray Goggles]: http://hackasaurus.org/goggles/\n  [lovebomb mockups]: http://jessicaklein.blogspot.com/2012/03/iterating-on-bombs.html\n  [webmaker tutorials]: http://www.toolness.com/wp/2012/03/webmaker-tutorial-prototyping/\n  [error reporting specification]: http://mozilla.github.com/slowparse/spec/\n  [live demo]: http://mozilla.github.com/slowparse/demo/\n  [slowparse.js]: http://mozilla.github.com/slowparse/\n  [tree-inspectors.js]: http://mozilla.github.com/slowparse/?tree-inspectors.js\n  [spec/errors.jquery.js]: http://mozilla.github.com/slowparse/?errors.jquery.js\n  [test suite]: http://mozilla.github.com/slowparse/test/\n  [learning]: http://www.toolness.com/wp/2012/04/learning-and-grammatical-forgiveness/\n  "
  },
  {
    "path": "site/examples/friendlycode/slowparse/demo/hierarchic-source-code.css",
    "content": "div.element {\n  position: relative;\n  white-space: pre-wrap;\n  font-family: Monaco;\n  font-size: 9pt;\n  color: rgba(0,0,0,0.75);\n  border: 1px dotted black;\n  padding-bottom: 1.5em;\n  margin-left: 0.5em;\n  word-wrap: break-word;\n}\n\ndiv.element div.name {\n  display: inline;\n}\n\ndiv.element div.value {\n  display: inline-block;\n}\n\nli > div.element {\n  margin-bottom: 0.5em;\n  margin-top: 0.5em;  \n}\n\ndiv.element > div.start, div.element > div.end {\n  background: rgba(0,0,0,0.5);\n  color: white;\n}\n\ndiv.element > div.start:before {\n  content: '<';\n}\n\ndiv.element > div.start:after {\n  content: '>';\n}\n\ndiv.element > div.start > div.name {\n}\n\ndiv.element li {\n  display: inline;\n}\n\ndiv.element > div.start > ul.attributes {\n  display: inline;\n  padding: 0;\n}\n\ndiv.element > div.start > ul.attributes div.name {\n  color: rgba(255,255,255,0.7);\n}\n\ndiv.element > div.start > ul.attributes div.name:before {\n  content: ' ';\n}\n\ndiv.element > div.start > ul.attributes div.name:after {\n  content: '=';\n}\n\ndiv.element > div.start > ul.attributes div.value {\n  color: white;\n}\n\ndiv.element > div.start > ul.attributes div.value:before {\n  content: '\"';\n  color: rgba(255,255,255,0.7);\n}\n\ndiv.element > div.start > ul.attributes div.value:after {\n  content: '\"';\n  color: rgba(255,255,255,0.7);\n}\n\ndiv.element > ul.children {\n  padding-left: 0.5em;\n  padding-right: 0.5em;\n}\n\ndiv.element > div.end {\n  position: absolute;\n  right: 0px;\n  bottom: 0px;\n}\n\ndiv.element > div.end:before {\n  content: '</';\n}\n\ndiv.element > div.end:after {\n  content: '>';\n}\n\ndiv.text {\n  font-family: \"Helvetica Neue\";\n  color: black;\n}\n\n.drop-zone {\n  min-height: 8px;\n}\n\n.current-drag {\n}\n\n.current-drop {\n  background: rgba(0,0,0,0.25) !important;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/demo/index.html",
    "content": "<!DOCTYPE html>\n<meta charset=\"utf-8\">\n<title>Slowparse Demo</title>\n<link rel=\"stylesheet\" href=\"hierarchic-source-code.css\">\n<link rel=\"stylesheet\" href=\"../vendor/codemirror2/lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"jsbin-codemirror-theme.css\">\n<style>\nhtml, body {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  height: 100%;\n  margin: 0px;\n  padding: 0px;\n}\n\ntextarea.html {\n  width: 100%;\n  height: 200px;\n}\n\n.column {\n  width: 25%;\n  height: 100%;\n  display: inline-block;\n  vertical-align: top;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  border-left: 1px dotted black;\n  padding-left: 10px;\n  padding-right: 10px;\n}\n\n.column:first-child {\n  border-left: none;\n}\n\n.column > aside {\n  height: 6em;\n  font-size: small;\n}\n\n.error {\n  color: firebrick;\n}\n\n.error em[data-highlight] {\n  font-style: inherit;\n  color: red;\n  text-decoration: underline;\n  cursor: pointer;\n}\n</style>\n<div class=\"column\">\n  <h2>HTML Source</h2>\n  <aside>Tinker with this.</aside>\n  <textarea class=\"html\">&lt;p class=\"foo\"&gt;hi&lt;/i&gt;</textarea>\n</div><div class=\"column\">\n  <h2>DOM Diagram</h2>\n  <aside>This is the DOM generated by <a href=\"..\">slowparse</a>. Mouse over different parts to see where they correspond in the original source.</aside>\n  <div class=\"rendered-dom\"></div>\n</div><div class=\"column\">\n  <h2>DOM Rendering</h2>\n  <aside>This is what the DOM looks like on the Web.</aside>\n  <div class=\"dom\"></div>\n</div><div class=\"column\">\n  <h2>Errors</h2>\n  <aside>If any errors occurred while parsing, they will be shown here. Also see the <a href=\"../spec/\">spec</a>.</aside>\n  <div class=\"error\"></div>\n</div>\n<script src=\"../vendor/jquery.min.js\"></script>\n<script src=\"../vendor/codemirror2/lib/codemirror.js\"></script>\n<script src=\"../vendor/codemirror2/mode/xml/xml.js\"></script>\n<script src=\"../vendor/codemirror2/mode/javascript/javascript.js\"></script>\n<script src=\"../vendor/codemirror2/mode/css/css.js\"></script>\n<script src=\"../vendor/codemirror2/mode/htmlmixed/htmlmixed.js\"></script>\n<script src=\"../slowparse.js\"></script>\n<script src=\"utils.js\"></script>\n<script src=\"tag-colors.js\"></script>\n<script src=\"render-dom.js\"></script>\n<script src=\"../spec/errors.jquery.js\"></script>\n<script>\nvar editor;\n\nfunction selectInterval(interval) {\n  var start = editor.coordsFromIndex(interval.start);\n  var end = editor.coordsFromIndex(interval.end);\n  editor.setSelection(start, end);\n  editor.focus();\n}\n\nfunction linkRenderedDomToSource(rendered) {\n  function getDottedName(obj, dottedName) {\n    var parts = dottedName.split(\".\");\n    for (var i = 0; i < parts.length; i++) {\n      if (parts[i] in obj)\n        obj = obj[parts[i]];\n      else\n        return null;\n    }\n    return obj;\n  }\n  \n  function highlighter(property) {\n    return function(event) {\n      var linked = $(this).data(\"linked-node\");\n      if (!linked)\n        linked = $(this).parent().data(\"linked-node\");\n      if (linked) {\n        var interval = getDottedName(linked, property);\n        if (interval) {\n          selectInterval(interval);\n          event.stopPropagation();\n        }\n      }\n    }\n  }\n  \n  rendered.find(\".text\")\n    .mouseover(highlighter(\"parseInfo\"));\n  rendered.find(\".element .start\")\n    .mouseover(highlighter(\"parseInfo.openTag\"));\n  rendered.find(\".element .end\")\n    .mouseover(highlighter(\"parseInfo.closeTag\"));\n  rendered.find(\".element .attributes .name\")\n    .mouseover(highlighter(\"parseInfo.name\"));\n  rendered.find(\".element .attributes .value\")\n    .mouseover(highlighter(\"parseInfo.value\"));\n}\n\nfunction processHTML(html) {\n  $(\".dom, .rendered-dom, .error\").empty();\n  \n  try {\n    var result = Slowparse.HTML(document, html);\n  } catch (e) {\n    console.error(e);\n    $(\".error\").text(e.message);\n    return;\n  }\n  var div = $(\"<div></div>\").append($(result.document).contents());\n  var rendered = div.renderDom();\n  rendered.css({\n    backgroundColor: \"white\",\n    border: \"none\"\n  }).find(\"> .start, > .end\").remove();\n  $(\".dom\").append(div);\n  $(\".rendered-dom\").append(rendered);\n  linkRenderedDomToSource(rendered);\n  if (result.error) {\n    try {\n      $(\".error\").fillError(result.error);\n    } catch (e) {\n      $(\".error\").text(e.message);\n    }\n  }\n}\n\n$(document).on(\"mouseover\", \"[data-highlight]\", function(event) {\n  selectInterval($(this).errorHighlightInterval());\n});\n\n$(window).ready(function() {\n  jQuery.loadErrors(\"../spec/\", [\"base\"], function() {\n    function onChange() {\n      processHTML(editor.getValue());\n    }\n  \n    editor = CodeMirror.fromTextArea($(\".html\")[0], {\n      mode: \"text/html\",\n      theme: \"jsbin\",\n      tabMode: \"indent\",\n      lineWrapping: true,\n      lineNumbers: true,\n      onChange: onChange\n    });\n\n    editor.focus();\n    onChange();\n  });\n});\n</script>"
  },
  {
    "path": "site/examples/friendlycode/slowparse/demo/jsbin-codemirror-theme.css",
    "content": "/* jsbin - based on web inspector */\n.cm-s-jsbin span.cm-keyword {color: #AA0D91;}\n.cm-s-jsbin span.cm-atom {color: #219;}\n.cm-s-jsbin span.cm-number {color: #164;}\n.cm-s-jsbin span.cm-def {color: #00f;}\n.cm-s-jsbin span.cm-variable {color: black;}\n.cm-s-jsbin span.cm-variable-2 {color: #05a;}\n.cm-s-jsbin span.cm-variable-3 {color: #0a5;}\n.cm-s-jsbin span.cm-property {color: black;}\n.cm-s-jsbin span.cm-operator {color: black;}\n.cm-s-jsbin span.cm-comment {color: #236E25;}\n.cm-s-jsbin span.cm-string {color: #C41A16;}\n.cm-s-jsbin span.cm-meta {color: #555;}\n.cm-s-jsbin span.cm-error {color: #f00;}\n.cm-s-jsbin span.cm-qualifier {color: #555;}\n.cm-s-jsbin span.cm-builtin {color: #30a;}\n.cm-s-jsbin span.cm-bracket {color: #cc7;}\n.cm-s-jsbin span.cm-tag {color: #881280;}\n.cm-s-jsbin span.cm-attribute {color: #994500;}\n\n.CodeMirror {\n  font-family: Menlo, Monaco, consolas, monospace;\n  font-size: 12px;\n  line-height: 1.2em;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/demo/render-dom.js",
    "content": "(function(jQuery) {\n  \"use strict\";\n  \n  var $ = jQuery;\n\n  function makeAttributeList(node) {\n    var attribs = $('<ul class=\"attributes\"></ul>');\n    for (var i = 0; i < node.attributes.length; i++) {\n      var attr = node.attributes[i];\n      var name = $('<div class=\"name\"></div>').text(attr.name);\n      var value = $('<div class=\"value\"></div>').text(attr.value);\n      name.data(\"linked-node\", attr);\n      value.data(\"linked-node\", attr);\n      attribs.append($('<li></li>').append(name).append(value));\n    }\n    return attribs;\n  }\n  \n  function renderTextNode(node) {\n    var div = $('<div class=\"text\"></div>');\n    div.text(node.nodeValue);\n    div.data(\"linked-node\", node);\n    return div;\n  }\n  \n  function renderElement(node) {\n    node = $(node).get(0);\n    \n    var rendered = $('<div class=\"element\"></div>');\n    var start = $('<div class=\"start\"></div>');\n    var name = $('<div class=\"name\"></div>');\n    if ($(node).isVoidElement())\n      rendered.addClass(\"is-void\");\n    name.text(node.nodeName.toLowerCase());\n    start.append(name);\n    var attribs = makeAttributeList(node);\n    if (attribs.children().length)\n      start.append(attribs);\n    rendered.append(start);\n    var children = $('<ul class=\"children\"></ul>');\n    $(node).contents().each(function() {\n      var item = $('<li></li>');\n      switch (this.nodeType) {\n        case this.TEXT_NODE:\n        if (jQuery.trim(this.nodeValue).length) {\n          item.append(renderTextNode(this));\n          children.append(item);\n        }\n        break;\n        \n        case this.ELEMENT_NODE:\n        item.append(renderElement(this));\n        children.append(item);\n        break;\n\n        // TODO: What about other node types?\n      }\n    });\n    if (children.children().length) {\n      var end = $('<div class=\"end\"></div>').append(name.clone());\n      rendered.append(children).append(end);\n    }\n    rendered.addClass('tag-' + jQuery.colorForTag(name.text()).slice(1));\n    rendered.applyTagColor(node, 0.33);\n    rendered.data(\"linked-node\", node);\n    return rendered;\n  }\n    \n  jQuery.fn.extend({\n    renderDom: function renderDom() {\n      return renderElement(this);\n    }\n  });\n})(jQuery);\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/demo/tag-colors.js",
    "content": "(function(jQuery) {\n  \"use strict\";\n\n  var $ = jQuery;\n  \n  var TAG_COLORS = [\n    \"#C60C46\",\n    \"#00AEEF\",\n    \"#F3739B\",\n    \"#FF66FF\",\n    \"#E66124\",\n    \"#FFC328\",\n    \"#B2E725\",\n    \"#660066\",\n    \"#FF9900\"\n  ];\n\n  var NUM_TAG_COLORS = TAG_COLORS.length;\n\n  var TAG_COLOR_MAP = {\n    img: 0,\n    p: 1,\n    div: 2,\n    a: 3,\n    span: 4,\n    body: 5,\n    h1: 6,\n    html: 7,\n    footer: 8\n  };\n\n  var DEFAULT_OVERLAY_OPACITY = 0.7;\n\n  function tagNameToNumber(tagName) {\n    var total = 0;\n    for (var i = 0; i < tagName.length; i++)\n      total += tagName.charCodeAt(i);\n    return total;\n  }\n\n  jQuery.extend({\n    // This is only really exported so unit tests can use it.\n    NUM_TAG_COLORS: NUM_TAG_COLORS,\n\n    // Returns the color hex for the \"official\" Web X-Ray color\n    // for the given tag name, excluding angled brackets.\n    colorForTag: function colorForTag(tagName) {\n      var colorNumber;\n\n      tagName = tagName.toLowerCase();\n      if (tagName in TAG_COLOR_MAP)\n        colorNumber = TAG_COLOR_MAP[tagName];\n      else\n        colorNumber = (tagNameToNumber(tagName) % NUM_TAG_COLORS);\n\n      return TAG_COLORS[colorNumber];\n    }\n  });\n\n  jQuery.fn.extend({\n    // Applies the \"official\" Web X-Ray color for fromElement to\n    // the current set of matched elements with the given\n    // optional opacity. Returns the current set of matched\n    // elements to support chaining.\n    applyTagColor: function applyTagColor(fromElement, opacity) {\n      var bgColor;\n      var baseColor = $.colorForTag($(fromElement).get(0).nodeName);\n\n      if (opacity === undefined)\n        opacity = DEFAULT_OVERLAY_OPACITY;\n\n      bgColor = $.makeRGBA(baseColor, opacity);\n\n      this.css({backgroundColor: bgColor});\n      return this;\n    },\n    // Like $.overlay(), but applies the \"official\" Web X-Ray color\n    // for the element type being overlaid, with the given opacity.\n    // A default opacity is used if none is provided.\n    overlayWithTagColor: function overlayWithTagColor(opacity) {\n      return $(this).overlay().applyTagColor(this, opacity);\n    }\n  });\n})(jQuery);\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/demo/utils.js",
    "content": "(function(jQuery) {\n  \"use strict\";\n\n  var $ = jQuery;\n  var HEX_REGEXP = /#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i;\n  var RGB_REGEXP = /rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)/;\n\n  jQuery.extend({\n    // Load the given script. Returns a jQuery deferred that resolves\n    // when the script is loaded. Nothing happens if the\n    // script fails to load.\n    loadScript: function loadScript(url) {\n      var script = document.createElement('script');\n      var deferred = jQuery.Deferred();\n      script.setAttribute('src', url);\n      script.addEventListener(\"load\", function() {\n        document.head.removeChild(script);\n        deferred.resolve();\n      }, false);\n      document.head.appendChild(script);\n      return deferred;\n    },\n    // Return a string that is shortened to be the given maximum\n    // length, with a trailing ellipsis at the end. If the string\n    // isn't longer than the maximum length, the string is returned\n    // unaltered.\n    shortenText: function shortenText(text, maxLength) {\n      if (text.length > maxLength)\n        return text.substring(0, maxLength) + '\\u2026';\n      return text;\n    },\n    // Return an rgba()-style CSS color string given a color and an\n    // alpha value.\n    makeRGBA: function makeRGBA(color, alpha) {\n      // WebKit and Gecko use this.\n      var match = color.match(RGB_REGEXP);\n      if (!match) {\n        // This is what Opera uses.\n        var hexMatch = color.match(HEX_REGEXP);\n        if (hexMatch) {\n          match = [null];\n          for (var i = 1; i <= 3; i++)\n            match.push(parseInt(hexMatch[i], 16));\n        } else\n          throw new Error(\"Couldn't parse \" + color);\n      }\n      return \"rgba(\" + \n             match[1] + \", \" +\n             match[2] + \", \" +\n             match[3] + \", \" +\n             alpha + \")\";\n    },\n    // Like console.warn(), but only does anything if console exists.\n    warn: function warn() {\n      if (window.console && window.console.warn) {\n        if (window.console.warn.apply)\n          window.console.warn.apply(window.console, arguments);\n        else\n          // IE9's console.warn doesn't have an apply method...\n          window.console.warn(arguments[0] + \" \" + arguments[1]);\n      }\n    }\n  });\n  \n  jQuery.fn.extend({\n    // Turns all URLs in src and href attributes into absolute URLs\n    // if they're not already.\n    absolutifyURLs: function() {\n      var URL_PROPS = ['href', 'src'];\n      this.find('*').andSelf().each(function() {\n        var self = this;\n        URL_PROPS.forEach(function(name) {\n          if (name in self && self[name]) {\n            $(self).attr(name, self[name]);\n          }\n        });\n      });\n      return this;\n    },\n    // returns whether at least one of the matched elements is a\n    // void element (i.e., has no closing tag).\n    isVoidElement: function() {\n      // Taken from:\n      // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements\n      return this.is(\"area, base, br, col, command, embed, hr, img, \" +\n                     \"input, keygen, link, meta, param, source, \" +\n                     \"track, wbr\");\n    },\n    // works much like jQuery's html() with no arguments, but\n    // includes HTML code for the matched elements themselves.\n    // unlike jQuery, this will include all matched elements.\n    outerHtml: function outerHtml() {\n      var clonedElement = this.clone();\n      var trivialParent = $('<div></div>').append(clonedElement);\n      return trivialParent.html();\n    },\n    // Given a descendant on the first matched element, returns a CSS\n    // selector that uniquely selects only the descendant from the\n    // first matched element.\n    pathTo: function pathTo(descendant) {\n      var root = this[0];\n      var target = $(descendant).get(0);\n      var parts = [];\n\n      for (var node = target; node && node != root; node = node.parentNode) {\n        var n = $(node).prevAll(node.nodeName.toLowerCase()).length + 1;\n        var id = $(node).attr(\"id\");\n        var className = $(node).attr(\"class\");\n        var classNames = [];\n        var selector = node.nodeName.toLowerCase();\n\n        // Class and id parts are based on jQuery-GetPath code.\n        if (typeof(id) != \"undefined\" && id.length)\n          selector += \"#\" + id;\n\n        if (typeof(className) != \"undefined\" && className.length)\n          jQuery.each(jQuery.trim(className).split(/[\\s\\n]+/), function() {\n            // Only keep the sane-looking class names. The CSS standard\n            // does prescribe escape patterns for odd characters in\n            // selectors, but jQuery's selector parser isn't completely\n            // standards-compliant, so we'll stick with the safe ones.\n            if (/^[A-Za-z0-9_\\-]+$/.test(this))\n              classNames.push(this);\n          });\n        \n        if (classNames.length)\n          selector += \".\" + classNames.join('.');\n        \n        selector += ':nth-of-type(' + n + ')';\n        parts.push(selector);\n      }\n      \n      parts.reverse();\n      return ' > ' + parts.join(' > ');\n    },\n\n    // Temporarily remove the set of matched elements,\n    // returning a removal object with one method,\n    // undo(), that can be used to undo the removal.\n    temporarilyRemove: function temporarilyRemove() {\n      var undoers = [];\n      jQuery.each(this, function(i, element) {\n        var document = element.ownerDocument;\n        var replacer = document.createTextNode('');\n        element.parentNode.replaceChild(replacer, element);\n        undoers.push(function() {\n          replacer.parentNode.replaceChild(element, replacer);\n        });\n      });\n      return {\n        undo: function undo() {\n          jQuery.each(undoers, function(i, undoer) {\n            undoer();\n          });\n          undoers = null;\n        }\n      };\n    },\n    \n    // Return the nth ancestor of the first matched element.\n    ancestor: function ancestor(generation) {\n      var ancestor = this[0];\n      \n      for (var i = 0; i < generation; i++)\n        if (ancestor.parentNode)\n          ancestor = ancestor.parentNode;\n        else\n          return null;\n\n      return $(ancestor);\n    },\n    // Return the bounding client rectangle of the first element\n    // in the selection, taking CSS transforms into account if\n    // possible.\n    //\n    // The returned object has top/left/height/width properties.\n    bounds: function bounds() {\n      try {\n        var rect = this.get(0).getBoundingClientRect();\n        var window = this.get(0).ownerDocument.defaultView;\n        return {\n          top: rect.top + window.pageYOffset,\n          left: rect.left + window.pageXOffset,\n          height: rect.height,\n          width: rect.width\n        };\n      } catch (e) {\n        // Not sure if this will ever get called, but there's code in\n        // Tilt that deals with this kind of situation, and we'd like to\n        // gracefully fallback to code that we know works if the above\n        // fails. For more discussion, see bug #98:\n        //\n        // http://hackasaurus.lighthouseapp.com/projects/81472/tickets/98\n\n        var pos = this.offset();\n        return {\n          top: pos.top,\n          left: pos.left,\n          height: this.outerHeight(),\n          width: this.outerWidth()\n        };\n      }\n    },\n    // Create and return a div that floats above the first\n    // matched element.\n    overlay: function overlay() {\n      var html = this.get(0).ownerDocument.documentElement;\n      var overlay = $('<div class=\"webxray-base webxray-overlay\">' +\n                      '&nbsp;</div>');\n\n      overlay.css(this.bounds());\n      $(html).append(overlay);\n      return overlay;\n    },\n    // Like jQuery.append(), but accepts an arbitrary number of arguments,\n    // and automatically converts string arguments into text nodes.\n    emit: function emit() {\n      for (var i = 0; i < arguments.length; i++) {\n        var arg = arguments[i];\n        if (typeof(arg) == \"string\")\n          arg = document.createTextNode(arg);\n        this.append(arg);\n      }\n    },\n    // Resizes and repositions the currently matched element to\n    // match the size and position of the given target by animating\n    // it and then executing the given callback.\n    resizeTo: function resizeTo(target, cb) {\n      var overlay = this;\n\n      var hasNoStyle = $(target).attr('style') === undefined;\n      overlay.animate($(target).bounds(), cb);\n      if (hasNoStyle && $(target).attr('style') == '')\n        $(target).removeAttr('style');\n    },\n    // Resizes and repositions the currently matched element to\n    // match the size and position of the given target by animating\n    // it, then fades out the currently matched element and\n    // removes it from the DOM.\n    resizeToAndFadeOut: function resizeToAndFadeOut(target) {\n      this.resizeTo(target, function() {\n        $(this).fadeOut(function() { $(this).remove(); });\n      });\n    },\n    // Removes the class and, if the class attribute is now empty, \n    // removes the attribute as well (jQuery remove class does not)..\n    reallyRemoveClass: function reallyRemoveClass(classname) {\n      this.removeClass(classname).filter('[class=\"\"]').removeAttr('class');\n      return this;\n    }\n  });\n})(jQuery);\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/index.html",
    "content": "<!DOCTYPE html>\n<meta charset=\"utf-8\">\n<link rel=\"stylesheet\" href=\"vendor/docco.css\">\n<title></title>\n<div id=\"container\">\n  <div id=\"background\"></div>\n  <div id=\"jump_to\">\n    Jump To &hellip;\n    <div id=\"jump_wrapper\">\n      <div id=\"jump_page\">\n        <a class=\"source\">slowparse.js</a>\n        <a class=\"source\">tree-inspectors.js</a>\n        <a class=\"source\">spec/errors.jquery.js</a>\n      </div>\n  </div>\n</div>\n<script src=\"vendor/showdown.js\"></script>\n<script src=\"vendor/codemirror2/lib/codemirror.js\"></script>\n<script src=\"vendor/codemirror2/mode/javascript/javascript.js\"></script>\n<script src=\"vendor/brocco.js\"></script>\n<script src=\"vendor/jump-to.js\"></script>\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/slowparse.js",
    "content": "\"use strict\";\n\n// Slowparse is a token stream parser for HTML and CSS text,\n// recording regions of interest during the parse run and\n// signaling any errors detected accompanied by relevant\n// regions in the text stream, to make debugging easy. Each\n// error type is documented in the [error specification][].\n//\n// Slowparse also builds a DOM as it goes, attaching metadata\n// to each node build that points to where it came from in\n// the original source.\n//\n// For more information on the rationale behind Slowparse, as\n// well as its design goals, see the [README][].\n//\n// If [RequireJS] is detected, this file is defined as a module via\n// `define()`. Otherwise, a global called `Slowparse` is exposed.\n//\n// ## Implementation\n//\n// Slowparse is effectively a finite state machine for\n// HTML and CSS strings, and will switch between the HTML\n// and CSS parsers while maintaining a single token stream.\n//\n//   [RequireJS]: http://requirejs.org/\n//   [error specification]: spec/\n//   [README]: https://github.com/mozilla/slowparse#readme\nvar Slowparse = (function() {\n  // ### Character Entity Parsing\n  //\n  // We currently only parse the most common named character entities.\n  var CHARACTER_ENTITY_REFS = {\n    lt: \"<\",\n    gt: \">\",\n    apos: \"'\",\n    quot: '\"',\n    amp: \"&\"\n  };\n\n  // `replaceEntityRefs()` will replace named character entity references\n  // (e.g. `&lt;`) in the given text string and return the result. If an\n  // entity name is unrecognized, don't replace it at all. Writing HTML\n  // would be surprisingly painful without this forgiving behavior.\n  //\n  // This function does not currently replace numeric character entity\n  // references (e.g., `&#160;`).\n  function replaceEntityRefs(text) {\n    return text.replace(/&([A-Za-z]+);/g, function(ref, name) {\n      name = name.toLowerCase();\n      if (name in CHARACTER_ENTITY_REFS)\n        return CHARACTER_ENTITY_REFS[name];\n      return ref;\n    });\n  }\n\n\n  // ### Errors\n  //\n  // `ParseError` is an internal error class used to indicate a parsing error.\n  // It never gets seen by Slowparse clients, as parse errors are an\n  // expected occurrence. However, they are used internally to simplify\n  // flow control.\n  //\n  // The first argument is the name of an error type, followed by\n  // arbitrary positional arguments specific to that error type. Every\n  // instance has a `parseInfo` property which contains the error\n  // object that will be exposed to Slowparse clients when parsing errors\n  // occur.\n  function ParseError(type) {\n    this.name = \"ParseError\";\n    if (!(type in ParseErrorBuilders))\n      throw new Error(\"Unknown ParseError type: \" + type);\n    var args = [];\n    for (var i = 1; i < arguments.length; i++)\n      args.push(arguments[i]);\n    var parseInfo = ParseErrorBuilders[type].apply(ParseErrorBuilders, args);\n\n    /* This may seem a weird way of setting an attribute, but we want\n     * to make the JSON serialize so the 'type' appears first, as it\n     * makes our documentation read better. */\n    parseInfo = ParseErrorBuilders._combine({\n      type: type\n    }, parseInfo);\n    this.message = type;\n    this.parseInfo = parseInfo;\n  }\n\n  ParseError.prototype = Error.prototype;\n\n  // `ParseErrorBuilders` contains Factory functions for all our types of\n  // parse errors, indexed by error type.\n  //\n  // Each public factory function returns a `parseInfo` object, sans the\n  // `type` property. For more information on each type of error,\n  // see the [error specification][].\n  //\n  //   [error specification]: spec/\n  var ParseErrorBuilders = {\n    /* Create a new object that has the properties of both arguments\n     * and return it. */\n    _combine: function(a, b) {\n      var obj = {}, name;\n      for (name in a) {\n        obj[name] = a[name];\n      }\n      for (name in b) {\n        obj[name] = b[name];\n      }\n      return obj;\n    },\n    // These are HTML errors.\n    UNCLOSED_TAG: function(parser) {\n      return {\n        openTag: this._combine({\n          name: parser.domBuilder.currentNode.nodeName.toLowerCase()\n        }, parser.domBuilder.currentNode.parseInfo.openTag)\n      };\n    },\n    INVALID_TAG_NAME: function(tagName, token) {\n      return {\n        openTag: this._combine({\n          name: tagName\n        }, token.interval)\n      };\n    },\n    UNEXPECTED_CLOSE_TAG: function(parser, closeTagName, token) {\n      return {\n        closeTag: this._combine({\n          name: closeTagName\n        }, token.interval)\n      };\n    },\n    MISMATCHED_CLOSE_TAG: function(parser, openTagName, closeTagName, token) {\n      return {\n        openTag: this._combine({\n          name: openTagName\n        }, parser.domBuilder.currentNode.parseInfo.openTag),\n        closeTag: this._combine({\n          name: closeTagName\n        }, token.interval)\n      };\n    },\n    CLOSE_TAG_FOR_VOID_ELEMENT: function(parser, closeTagName, token) {\n      return {\n        closeTag: this._combine({\n          name: closeTagName\n        }, token.interval)\n      };\n    },\n    UNTERMINATED_COMMENT: function(token) {\n      return {\n        start: token.interval.start\n      };\n    },\n    UNTERMINATED_ATTR_VALUE: function(parser, nameTok) {\n      return {\n        openTag: this._combine({\n          name: parser.domBuilder.currentNode.nodeName.toLowerCase()\n        }, parser.domBuilder.currentNode.parseInfo.openTag),\n        attribute: {\n          name: {\n            value: nameTok.value,\n            start: nameTok.interval.start,\n            end: nameTok.interval.end\n          },\n          value: {\n            start: parser.stream.makeToken().interval.start\n          }\n        },\n      };\n    },\n    UNQUOTED_ATTR_VALUE: function(parser) {\n      var pos = parser.stream.pos;\n      if (!parser.stream.end())\n        pos = parser.stream.makeToken().interval.start;\n      return {\n        start: pos\n      };\n    },\n    UNTERMINATED_OPEN_TAG: function(parser) {\n      return {\n        openTag: {\n          start: parser.domBuilder.currentNode.parseInfo.openTag.start,\n          end: parser.stream.pos,\n          name: parser.domBuilder.currentNode.nodeName.toLowerCase()\n        }\n      };\n    },\n    SELF_CLOSING_NON_VOID_ELEMENT: function(parser, tagName) {\n      return {\n        name: tagName,\n        start: parser.domBuilder.currentNode.parseInfo.openTag.start,\n        end: parser.stream.makeToken().interval.end\n      };\n    },\n    UNTERMINATED_CLOSE_TAG: function(parser) {\n      var end = parser.stream.pos;\n      if (!parser.stream.end())\n        end = parser.stream.makeToken().interval.start;\n      return {\n        closeTag: {\n          name: parser.domBuilder.currentNode.nodeName.toLowerCase(),\n          start: parser.domBuilder.currentNode.parseInfo.closeTag.start,\n          end: end\n        }\n      };\n    },\n    // These are CSS errors.\n    MISSING_CSS_SELECTOR: function(parser, start, end) {\n      return {\n        cssBlock: {\n          start: start,\n          end: end\n        }\n      };\n    },\n    UNFINISHED_CSS_SELECTOR: function(parser, start, end, selector) {\n      return {\n        cssSelector: {\n          start: start,\n          end: end,\n          selector: selector\n        }\n      };\n    },\n    MISSING_CSS_BLOCK_OPENER: function(parser, start, end, selector) {\n      return {\n        cssSelector: {\n          start: start,\n          end: end,\n          selector: selector\n        }\n      };\n    },\n    INVALID_CSS_PROPERTY_NAME: function(parser, start, end, property) {\n      return {\n        cssProperty: {\n          start: start,\n          end: end,\n          property: property\n        }\n      };\n    },\n    MISSING_CSS_PROPERTY: function(parser, start, end, selector) {\n      return {\n        cssSelector: {\n          start: start,\n          end: end,\n          selector: selector\n        }\n      };\n    },\n    UNFINISHED_CSS_PROPERTY: function(parser, start, end, property) {\n      return {\n        cssProperty: {\n          start: start,\n          end: end,\n          property: property\n        }\n      };\n    },\n    MISSING_CSS_VALUE: function(parser, start, end, property) {\n      return {\n        cssProperty: {\n          start: start,\n          end: end,\n          property: property\n        }\n      };\n    },\n    UNFINISHED_CSS_VALUE: function(parser, start, end, value) {\n      return {\n        cssValue: {\n          start: start,\n          end: end,\n          value: value\n        }\n      };\n    },\n    MISSING_CSS_BLOCK_CLOSER: function(parser, start, end, value) {\n      return {\n        cssValue: {\n          start: start,\n          end: end,\n          value: value\n        }\n      };\n    },\n    UNCAUGHT_CSS_PARSE_ERROR: function(parser, start, end, msg) {\n      return {\n        error: {\n          start: start,\n          end: end,\n          msg: msg\n        }\n      };\n    },\n    UNTERMINATED_CSS_COMMENT: function(start) {\n      return {\n        start: start\n      };\n    },\n    HTML_CODE_IN_CSS_BLOCK: function(parser, start, end) {\n      return {\n        html: {\n          start: start,\n          end: end\n        }\n      }\n    }\n  };\n\n  // ### Streams\n  //\n  // `Stream` is an internal class used for tokenization. The interface for\n  // this class is inspired by the analogous class in [CodeMirror][].\n  //\n  //   [CodeMirror]: http://codemirror.net/doc/manual.html#modeapi\n  function Stream(text) {\n    this.text = text;\n    this.pos = 0;\n    this.tokenStart = 0;\n  }\n\n  Stream.prototype = {\n    // `Stream.peek()` returns the next character in the stream without\n    // advancing it. It will return `undefined` at the end of the text.\n    peek: function() {\n      return this.text[this.pos];\n    },\n    // `Stream.substream(len)` returns a substream from the stream\n    // without advancing it, with length `len`.\n    substream: function(len) {\n      return this.text.substring(this.pos, this.pos + len);\n    },\n    // `Stream.next()` returns the next character in the stream and advances\n    // it. It also returns `undefined` when no more characters are available.\n    next: function() {\n      if (!this.end())\n        return this.text[this.pos++];\n    },\n    // `Stream.end()` returns true only if the stream is at the end of the\n    // text.\n    end: function() {\n      return (this.pos == this.text.length);\n    },\n    // `Stream.eat()` takes a regular expression. If the next character in\n    // the stream matches the given argument, it is consumed and returned.\n    // Otherwise, `undefined` is returned.\n    eat: function(match) {\n      if (!this.end() && this.peek().match(match))\n        return this.next();\n    },\n    // `Stream.eatWhile()` repeatedly calls `eat()` with the given argument,\n    // until it fails. Returns `true` if any characters were eaten.\n    eatWhile: function(matcher) {\n      var wereAnyEaten = false;\n      while (!this.end()) {\n        if (this.eat(matcher))\n          wereAnyEaten = true;\n        else\n          return wereAnyEaten;\n      }\n    },\n    // `Stream.eatSpace()` is a shortcut for `eatWhile()` when matching\n    // white-space (including newlines).\n    eatSpace: function() {\n      return this.eatWhile(/[\\s\\n]/);\n    },\n    // `Stream.eatCSSWhile()` is like `eatWhile()`, but it\n    // automatically deals with eating block comments like `/* foo */`.\n    eatCSSWhile: function(matcher) {\n      var wereAnyEaten = false,\n          chr = '',\n          peek = '',\n          next = '';\n      while (!this.end()) {\n        chr = this.eat(matcher);\n        if (chr)\n          wereAnyEaten = true;\n        else\n          return wereAnyEaten;\n        if (chr === '/') {\n          peek = this.peek();\n          if (peek === '*') {\n            /* Block comment found. Gobble until resolved. */\n            while(next !== '/' && !this.end()) {\n              this.eatWhile(/[^*]/);\n              this.next();\n              next = this.next();\n            }\n            next = '';\n          }\n        }\n      }\n    },\n    // `Stream.markTokenStart()` will set the start for the next token to\n    // the current stream position (i.e., \"where we are now\").\n    markTokenStart: function() {\n      this.tokenStart = this.pos;\n    },\n    // `Stream.markTokenStartAfterSpace()` is a wrapper function for eating\n    // up space, then marking the start for a new token.\n    markTokenStartAfterSpace: function() {\n      this.eatSpace();\n      this.markTokenStart();\n    },\n    // `Stream.makeToken()` generates a JSON-serializable token object\n    // representing the interval of text between the end of the last\n    // generated token and the current stream position.\n    makeToken: function() {\n      if (this.pos == this.tokenStart)\n        return null;\n      var token = {\n        value: this.text.slice(this.tokenStart, this.pos),\n        interval: {\n          start: this.tokenStart,\n          end: this.pos\n        }\n      };\n      this.tokenStart = this.pos;\n      return token;\n    },\n    // `Stream.match()` acts like a multi-character eat—if *consume* is `true`\n    // or not given—or a look-ahead that doesn't update the stream\n    // position—if it is `false`. *string* must be a string. *caseFold* can\n    // be set to `true` to make the match case-insensitive.\n    match: function(string, consume, caseFold) {\n      var substring = this.text.slice(this.pos, this.pos + string.length);\n      if (caseFold) {\n        string = string.toLowerCase();\n        substring = substring.toLowerCase();\n      }\n      if (string == substring) {\n        if (consume)\n          this.pos += string.length;\n        return true;\n      }\n      return false;\n    }\n  };\n\n\n  // ### CSS Parsing\n  //\n  // `CSSParser` is our internal CSS token stream parser object. This object\n  // has references to the stream, as well as the HTML DOM builder that is\n  // used by the HTML parser.\n  function CSSParser(stream, domBuilder) {\n    this.stream = stream;\n    this.domBuilder = domBuilder;\n  }\n\n  CSSParser.prototype = {\n    // We keep a list of all currently valid CSS properties (CSS1-CSS3).\n    // This list does not contain vendor prefixes.\n    cssProperties: [\n      \"alignment-adjust\",\"alignment-baseline\",\"animation\",\"animation-delay\",\n      \"animation-direction\",\"animation-duration\",\"animation-iteration-count\",\n      \"animation-name\",\"animation-play-state\",\"animation-timing-function\",\n      \"appearance\",\"azimuth\",\"backface-visibility\",\"background\",\n      \"background-attachment\",\"background-clip\",\"background-color\",\n      \"background-image\",\"background-origin\",\"background-position\",\n      \"background-repeat\",\"background-size\",\"baseline-shift\",\"binding\",\n      \"bleed\",\"bookmark-label\",\"bookmark-level\",\"bookmark-state\",\n      \"bookmark-target\",\"border\",\"border-bottom\",\"border-bottom-color\",\n      \"border-bottom-left-radius\",\"border-bottom-right-radius\",\n      \"border-bottom-style\",\"border-bottom-width\",\"border-collapse\",\n      \"border-color\",\"border-image\",\"border-image-outset\",\n      \"border-image-repeat\",\"border-image-slice\",\"border-image-source\",\n      \"border-image-width\",\"border-left\",\"border-left-color\",\n      \"border-left-style\",\"border-left-width\",\"border-radius\",\"border-right\",\n      \"border-right-color\",\"border-right-style\",\"border-right-width\",\n      \"border-spacing\",\"border-style\",\"border-top\",\"border-top-color\",\n      \"border-top-left-radius\",\"border-top-right-radius\",\"border-top-style\",\n      \"border-top-width\",\"border-width\",\"bottom\",\"box-decoration-break\",\n      \"box-shadow\",\"box-sizing\",\"break-after\",\"break-before\",\"break-inside\",\n      \"caption-side\",\"clear\",\"clip\",\"color\",\"color-profile\",\"column-count\",\n      \"column-fill\",\"column-gap\",\"column-rule\",\"column-rule-color\",\n      \"column-rule-style\",\"column-rule-width\",\"column-span\",\"column-width\",\n      \"columns\",\"content\",\"counter-increment\",\"counter-reset\",\"crop\",\"cue\",\n      \"cue-after\",\"cue-before\",\"cursor\",\"direction\",\"display\",\n      \"dominant-baseline\",\"drop-initial-after-adjust\",\n      \"drop-initial-after-align\",\"drop-initial-before-adjust\",\n      \"drop-initial-before-align\",\"drop-initial-size\",\"drop-initial-value\",\n      \"elevation\",\"empty-cells\",\"filter\",\"fit\",\"fit-position\",\"flex-align\",\n      \"flex-flow\",\"flex-line-pack\",\"flex-order\",\"flex-pack\",\"float\",\"float-offset\",\n      \"font\",\"font-family\",\"font-size\",\"font-size-adjust\",\"font-stretch\",\n      \"font-style\",\"font-variant\",\"font-weight\",\"grid-columns\",\"grid-rows\",\n      \"hanging-punctuation\",\"height\",\"hyphenate-after\",\"hyphenate-before\",\n      \"hyphenate-character\",\"hyphenate-lines\",\"hyphenate-resource\",\"hyphens\",\n      \"icon\",\"image-orientation\",\"image-rendering\",\"image-resolution\",\n      \"inline-box-align\",\"left\",\"letter-spacing\",\"line-break\",\"line-height\",\n      \"line-stacking\",\"line-stacking-ruby\",\"line-stacking-shift\",\n      \"line-stacking-strategy\",\"list-style\",\"list-style-image\",\n      \"list-style-position\",\"list-style-type\",\"margin\",\"margin-bottom\",\n      \"margin-left\",\"margin-right\",\"margin-top\",\"marker-offset\",\"marks\",\n      \"marquee-direction\",\"marquee-loop\",\"marquee-play-count\",\"marquee-speed\",\n      \"marquee-style\",\"max-height\",\"max-width\",\"min-height\",\"min-width\",\n      \"move-to\",\"nav-down\",\"nav-index\",\"nav-left\",\"nav-right\",\"nav-up\",\n      \"opacity\",\"orphans\",\"outline\",\"outline-color\",\"outline-offset\",\n      \"outline-style\",\"outline-width\",\"overflow\",\"overflow-style\",\n      \"overflow-wrap\",\"overflow-x\",\"overflow-y\",\"padding\",\"padding-bottom\",\n      \"padding-left\",\"padding-right\",\"padding-top\",\"page\",\"page-break-after\",\n      \"page-break-before\",\"page-break-inside\",\"page-policy\",\"pause\",\n      \"pause-after\",\"pause-before\",\"perspective\",\"perspective-origin\",\n      \"phonemes\",\"pitch\",\"pitch-range\",\"play-during\",\"pointer-events\",\n      \"position\",\n      \"presentation-level\",\"punctuation-trim\",\"quotes\",\"rendering-intent\",\n      \"resize\",\"rest\",\"rest-after\",\"rest-before\",\"richness\",\"right\",\n      \"rotation\",\"rotation-point\",\"ruby-align\",\"ruby-overhang\",\n      \"ruby-position\",\"ruby-span\",\"src\",\"size\",\"speak\",\"speak-header\",\n      \"speak-numeral\",\"speak-punctuation\",\"speech-rate\",\"stress\",\"string-set\",\n      \"tab-size\",\"table-layout\",\"target\",\"target-name\",\"target-new\",\n      \"target-position\",\"text-align\",\"text-align-last\",\"text-decoration\",\n      \"text-decoration-color\",\"text-decoration-line\",\"text-decoration-skip\",\n      \"text-decoration-style\",\"text-emphasis\",\"text-emphasis-color\",\n      \"text-emphasis-position\",\"text-emphasis-style\",\"text-height\",\n      \"text-indent\",\"text-justify\",\"text-outline\",\"text-shadow\",\n      \"text-space-collapse\",\"text-transform\",\"text-underline-position\",\n      \"text-wrap\",\"top\",\"transform\",\"transform-origin\",\"transform-style\",\n      \"transition\",\"transition-delay\",\"transition-duration\",\n      \"transition-property\",\"transition-timing-function\",\"unicode-bidi\",\n      \"vertical-align\",\"visibility\",\"voice-balance\",\"voice-duration\",\n      \"voice-family\",\"voice-pitch\",\"voice-pitch-range\",\"voice-rate\",\n      \"voice-stress\",\"voice-volume\",\"volume\",\"white-space\",\"widows\",\"width\",\n      \"word-break\",\"word-spacing\",\"word-wrap\",\"z-index\"],\n    // This helper verifies that a specific string is a known CSS property.\n    // We include vendor-prefixed known CSS properties, like `-o-transition`.\n    _knownCSSProperty: function(propertyName) {\n      propertyName = propertyName.replace(/^-.+?-/,'');\n      return this.cssProperties.indexOf(propertyName) > -1;\n    },\n    // #### The CSS Master Parse Function\n    //\n    // Here we process the token stream, assumed to have its pointer inside a\n    // CSS element, and will try to parse the content inside it as CSS until\n    // we hit the end of the CSS element.\n    //\n    // Any parse errors along the way will result in a `ParseError`\n    // being thrown.\n    parse: function() {\n      // We'll use some instance variables to keep track of our parse\n      // state:\n\n      // * A list of the CSS rulesets for the CSS block.\n      this.rules = [];\n\n      // * A list of comment blocks inside the CSS.\n      this.comments = [];\n\n      // Parsing is based on finite states, and a call\n      // to `_parseSelector()` will run through any number\n      // of states until it either throws an error,\n      // or terminates cleanly.\n      var sliceStart = this.stream.pos;\n      this.stream.markTokenStartAfterSpace();\n      this._parseSelector();\n      var sliceEnd = this.stream.pos;\n\n      // If we get here, the CSS block has no errors,\n      // and we report the start/end of the CSS block\n      // in the stream, as well as the rules/comments\n      // for the calling `HTMLparser` instance to work with.\n      var cssBlock = {\n        value: this.stream.text.slice(sliceStart, sliceEnd),\n        parseInfo: {\n          start: sliceStart,\n          end: sliceEnd,\n          rules: this.rules,\n          comments: this.comments\n        }\n      };\n\n      this.rules = null;\n      this.comments = null;\n      return cssBlock;\n    },\n    // #### CSS Comment Parsing\n    //\n    // Here we record the position of comments in *term* in the instance's\n    // comment list, and return *term* with all its comments stripped.\n    stripComments: function(term, startPos) {\n      var pos,\n          last = term.length,\n          commentStart, commentEnd,\n          prev, next,\n          stripped = \"\";\n      for (pos=0; pos < last; pos++) {\n        if (term[pos] === '/' && pos<last-1 && term[pos+1] === '*') {\n          commentStart = startPos + pos;\n          pos += 3;\n          while(pos < last-1 && term.substr(pos-1,2) !== \"*/\") {\n            pos++;\n          }\n          if (pos >= last-1 && term.substr(pos-1,2) !== \"*/\")\n            throw new ParseError(\"UNTERMINATED_CSS_COMMENT\", commentStart);\n          commentEnd = startPos + pos + 1;\n          this.comments.push({start: commentStart, end: commentEnd});\n        } else {\n          stripped += term[pos];\n        }\n      }\n      return stripped.trim();\n    },\n    // #### CSS Comment Filtering\n    //\n    // Here we filter a token so that its start and end positions\n    // point to the content without leading and trailing comments,\n    // with comments in the token.value completely removed.\n    filterComments: function(token) {\n      var text = token.value,\n          tsize = text.length,\n          ntsize,\n          stripped = this.stripComments(text, token.interval.start);\n      // strip leading comments\n      text = text.replace(/^\\s+/,\"\");\n      text = text.replace(/^\\/\\*[\\w\\W]*?\\*\\/\\s*/,'');\n      ntsize = text.length;\n      token.interval.start += tsize - ntsize;\n      // strip trailing comments (=reverse and repeat previous)\n      tsize = ntsize;\n      text = text.split('').reverse().join('');\n      text = text.replace(/^\\s+/,\"\");\n      text = text.replace(/^\\/\\*[\\w\\W]*?\\*\\/\\s*/,'');\n      // FIXME: this still fails comments like this: /* ... /* ... */,\n      //        which is a single block. The problems is that in the\n      //        reversed string this looks like /* ... */ ... */ which\n      //        counts as one block plus left-over junk.\n      ntsize = text.length;\n      token.interval.end -= tsize - ntsize;\n      // commit text change\n      token.value = stripped;\n    },\n    // #### CSS Selector Parsing\n    //\n    // A selector is a string, and terminates on `{`, which signals\n    // the start of a CSS property/value pair (which may be empty).\n    //\n    // There are a few characters in selectors that are an immediate error:\n    //\n    // * `;`  Rule terminator (ERROR: missing block opener)\n    // * `}`  End of css block (ERROR: missing block opener)\n    // * `<`  End of `<style>` element, start of `</style>`\n    //   (ERROR: css declaration has no body)\n    //\n    // Note that we cannot flag `:` as an error because pseudo-classes use\n    // it as their prefix.\n    _parseSelector: function() {\n      // Depending on our state, we may be coming from having just parsed\n      // a rule. If that's the case, add it to our list of rules.\n      if (this.currentRule) {\n        this.rules.push(this.currentRule);\n        this.currentRule = null;\n      }\n\n      // Gobble all characters that could be part of the selector.\n      this.stream.eatCSSWhile(/[^\\{;\\}<]/);\n      var token = this.stream.makeToken(),\n          peek = this.stream.peek();\n\n      // If there was nothing to select, we're either done,\n      // or an error occurred.\n      if (token === null) {\n        if (!this.stream.end() && this.stream.peek() === '<') {\n          // if this is the start of <!-- make sure to throw an error\n          if (this.stream.substream(2) !== \"</\") {\n            throw new ParseError(\"HTML_CODE_IN_CSS_BLOCK\", this, this.stream.pos-1,\n                                 this.stream.pos);\n          }\n          return;\n        }\n        throw new ParseError(\"MISSING_CSS_SELECTOR\", this, this.stream.pos-1,\n                             this.stream.pos);\n      }\n\n      // If we get here, we have a selector string.\n      // Filter the token for comments before continueing.\n      this.filterComments(token);\n      var selector = token.value,\n          selectorStart = token.interval.start,\n          selectorEnd = token.interval.end;\n\n      if (selector === '') {\n        this._parseSelector();\n        return;\n      }\n\n      // Now we'll set up a ruleset object for this selector.\n      this.currentRule = {\n        selector: {\n          value: selector,\n          start: selectorStart,\n          end: selectorEnd\n        },\n        declarations: {\n          start: null,\n          end: null,\n          properties: []\n        }\n      };\n\n      // Now we start to analyse whether we can continue,\n      // or whether we're in a terminal state, based on the\n      // next character in the stream.\n      if (this.stream.end() || peek === '<') {\n        throw new ParseError(\"UNFINISHED_CSS_SELECTOR\", this, selectorStart,\n                             selectorEnd, selector);\n      }\n\n      if (!this.stream.end()) {\n        var next = this.stream.next(),\n            errorMsg = \"[_parseSelector] Expected {, }, ; or :, \" +\n                       \"instead found \" + next;\n        if (next === '{') {\n          // The only legal continuation after a selector is the opening\n          // `{` character. If that's the character we see, we can mark the\n          // start of the declarations block and start parsing them.\n          this.currentRule.declarations.start = this.stream.pos-1;\n          this._parseDeclaration(selector, selectorStart);\n        } else if (next === ';' || next === '}') {\n          // Otherwise, this is a parse error; we should have seen `{`\n          // instead.\n          throw new ParseError(\"MISSING_CSS_BLOCK_OPENER\", this,\n                               selectorStart, selectorEnd, selector);\n        } else {\n          // We get here if an unexpected character was found.\n          throw new ParseError(\"UNCAUGHT_CSS_PARSE_ERROR\", this,\n                               token.interval.start, token.interval.end,\n                               errorMsg);\n        }\n      } else {\n        // If the stream ended after the selector, we want the user to follow\n        // up with `{`.\n        throw new ParseError(\"MISSING_CSS_BLOCK_OPENER\", this, selectorStart,\n                             selectorEnd, selector);\n      }\n    },\n    // #### CSS Declaration Parsing\n    //\n    // A declaration is a `property: value;` pair. It can be empty,\n    // in which case the next character must be `}`.\n    _parseDeclaration: function(selector, selectorStart, value) {\n      // First, we forward the stream to the next non-space character.\n      this.stream.markTokenStartAfterSpace();\n      var peek = this.stream.peek();\n      if (peek === '}') {\n        // If the next character is `}` then this is an empty block, and we\n        // should move on to trying to read a new selector ruleset.\n        this.stream.next();\n        this.currentRule.declarations.end = this.stream.pos;\n        this.stream.markTokenStartAfterSpace();\n        this._parseSelector();\n      }\n      // Administratively important: there are two ways for this function\n      // to have been called. One is from `_parseSelector()`, which is\n      // \"the normal way\", the other from `_parseValue()`, after finding a\n      // properly closed `property:value;` pair. In this case *value* will be\n      // the last declaration's value, which will let us throw a sensible\n      // debug error in case the stream is empty at this point, or points to\n      // `</style>`.\n      else if (value && (this.stream.end() || peek === '<')) {\n        throw new ParseError(\"MISSING_CSS_BLOCK_CLOSER\", this, selectorStart,\n                             selectorStart+value.length, value);\n      }\n\n      // If we're still in this function at this point, all is well\n      // and we can move on to property parsing.\n      else {\n        this._parseProperty(selector, selectorStart);\n      }\n    },\n    // #### CSS Property Parsing\n    // There is a fixed list of CSS properties, and we must check two things:\n    //\n    // 1. Does the token string contain a syntax-legal property?\n    // 2. Is that property in the set of known ones?\n    //\n    // Properties are terminated by `:`, but we might also see the following\n    // characters, which should signal an error:\n    //\n    // * `;` rule terminator (ERROR: missing value)\n    // * `}` end of CSS block (ERROR: missing value)\n    // * `<` end of `<style>` element, start of `</style>`\n    //   (ERROR: missing value)\n    _parseProperty: function(selector, selectorStart) {\n      var property = this.stream.eatCSSWhile(/[^\\{\\}<;:]/),\n          token = this.stream.makeToken();\n\n      if (token === null) {\n        throw new ParseError(\"MISSING_CSS_PROPERTY\", this, selectorStart,\n                             selectorStart + selector.length, selector);\n      }\n\n      this.filterComments(token)\n      var property = token.value,\n          propertyStart = token.interval.start,\n          propertyEnd = token.interval.end;\n\n      if (property === '') {\n        this._parseDeclaration(selector, selectorStart);\n        return;\n      }\n\n      var next = this.stream.next(),\n          errorMsg = \"[_parseProperty] Expected }, {, <, ; or :, \" +\n                     \"instead found \" + next;\n\n      if (next === '{') {\n        throw new ParseError(\"MISSING_CSS_BLOCK_CLOSER\", this, selectorStart,\n                             propertyStart, selector);\n      }\n\n\n      if ((this.stream.end() && next !== ':') || next === '<' ||\n          next === '}') {\n        throw new ParseError(\"UNFINISHED_CSS_PROPERTY\", this, propertyStart,\n                             propertyEnd, property);\n      }\n\n      // We record `property: value` pairs as we run through the stream,\n      // which are added to the set of `property: value` pairs in the\n      // instance's `rules.properties` array. The push happens when we have a\n      // clean run in `_parseValue()`.\n      this.currentProperty = {\n        name: {\n          value: property,\n          start: propertyStart,\n          end: propertyEnd\n        }\n      };\n\n      // If we find a colon, we have a property and now need a value to go\n      // along with it.\n      if (next === ':') {\n        // Before we continue, we must make sure the string we found is a real\n        // CSS property.\n        if (!( property && property.match(/^[a-z\\-]+$/)) ||\n            !this._knownCSSProperty(property))\n          throw new ParseError(\"INVALID_CSS_PROPERTY_NAME\", this,\n                               propertyStart, propertyEnd, property);\n        this.stream.markTokenStartAfterSpace();\n        this._parseValue(selector, selectorStart, property, propertyStart);\n      }\n      // Otherwise, anything else at this point constitutes an error.\n      else if (next === ';') {\n        throw new ParseError(\"MISSING_CSS_VALUE\", this, propertyStart,\n                             propertyEnd, property);\n      }\n      else {\n        throw new ParseError(\"UNCAUGHT_CSS_PARSE_ERROR\", this,\n                             token.interval.start, token.interval.end,\n                             errorMsg);\n      }\n    },\n    // #### CSS Value Parsing\n    //\n    // A value must end either in `;` or in `}`. However, we may also find:\n    //\n    // * `<` end of `<style>` element, start of `</style>`\n    //   (ERROR: missing block closer)\n    _parseValue: function(selector, selectorStart, property, propertyStart) {\n      var rule = this.stream.eatCSSWhile(/[^}<;]/),\n          token = this.stream.makeToken();\n\n      if(token === null) {\n        throw new ParseError(\"MISSING_CSS_VALUE\", this, propertyStart,\n                             propertyStart+property.length, property);\n      }\n\n      var next = (!this.stream.end() ? this.stream.next() : \"end of stream\"),\n          errorMsg = \"[_parseValue] Expected }, <, or ;, instead found \"+next;\n\n\n      this.filterComments(token);\n      var value = token.value,\n          valueStart = token.interval.start,\n          valueEnd = token.interval.end;\n\n      if (value === '') {\n        throw new ParseError(\"MISSING_CSS_VALUE\", this, this.stream.pos-1,\n                             this.stream.pos);\n      }\n\n      // At this point we can fill in the *value* part of the current\n      // `property: value;` pair. However, we hold off binding it until\n      // we are sure there are no parse errors.\n      this.currentProperty.value = {\n        value: value,\n        start: valueStart,\n        end: valueEnd\n      }\n\n      if ((this.stream.end() && next !== ';') || next === '<') {\n        throw new ParseError(\"UNFINISHED_CSS_VALUE\", this, valueStart,\n                             valueEnd, value);\n      }\n\n      if (next === ';') {\n        // This is normal CSS rule termination; try to read a new\n        // property/value pair.\n        this._bindCurrentRule();\n        this.stream.markTokenStartAfterSpace();\n        this._parseDeclaration(selector, valueStart, value);\n      }\n      else if (next === '}') {\n        // This is block level termination; try to read a new selector.\n        this.currentRule.declarations.end = this.stream.pos;\n        this._bindCurrentRule();\n        this.stream.markTokenStartAfterSpace();\n        this._parseSelector();\n      }\n      else {\n        throw new ParseError(\"UNCAUGHT_CSS_PARSE_ERROR\", this,\n                             token.interval.start, token.interval.end,\n                             errorMsg);\n      }\n    },\n    // This helper function binds the currrent `property: value` object\n    // in the current ruleset, and resets it for the next selector block.\n    _bindCurrentRule: function() {\n      this.currentRule.declarations.properties.push(this.currentProperty);\n      this.currentProperty = null;\n    }\n  }\n\n\n  // ### HTML Parsing\n  //\n  // The HTML token stream parser object has references to the stream,\n  // as well as a DOM builder that is used to construct the DOM while we\n  // run through the token stream.\n  function HTMLParser(stream, domBuilder) {\n    this.stream = stream;\n    this.domBuilder = domBuilder;\n    this.cssParser = new CSSParser(stream, domBuilder);\n  }\n\n  HTMLParser.prototype = {\n    // since SVG requires a slightly different code path,\n    // we need to track whether we're in HTML or SVG mode.\n    parsingSVG: false,\n\n    // For SVG DOM elements, we need to know the SVG namespace.\n    svgNameSpace: \"http://www.w3.org/2000/svg\",\n\n    // HTML5 documents have a special doctype that we must use\n    html5Doctype: \"<!DOCTYPE html>\",\n\n    // Void HTML elements are the ones that don't need to have a closing tag.\n    voidHtmlElements: [\"area\", \"base\", \"br\", \"col\", \"command\", \"embed\", \"hr\",\n                       \"img\", \"input\", \"keygen\", \"link\", \"meta\", \"param\",\n                       \"source\", \"track\", \"wbr\"],\n\n    // We keep a list of all valid HTML5 elements.\n    htmlElements: [\"a\", \"abbr\", \"address\", \"area\", \"article\", \"aside\",\n                   \"audio\", \"b\", \"base\", \"bdi\", \"bdo\", \"bgsound\", \"blink\",\n                   \"blockquote\", \"body\", \"br\", \"button\", \"canvas\", \"caption\",\n                   \"cite\", \"code\", \"col\", \"colgroup\", \"command\", \"datalist\",\n                   \"dd\", \"del\", \"details\", \"dfn\", \"div\", \"dl\", \"dt\", \"em\",\n                   \"embed\", \"fieldset\", \"figcaption\", \"figure\", \"footer\",\n                   \"form\", \"frame\", \"frameset\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\",\n                   \"h6\", \"head\", \"header\", \"hgroup\", \"hr\", \"html\", \"i\",\n                   \"iframe\", \"img\", \"input\", \"ins\", \"kbd\", \"keygen\", \"label\",\n                   \"legend\", \"li\", \"link\", \"map\", \"mark\", \"marquee\", \"menu\",\n                   \"meta\", \"meter\", \"nav\", \"nobr\", \"noscript\", \"object\", \"ol\",\n                   \"optgroup\", \"option\", \"output\", \"p\", \"param\", \"pre\",\n                   \"progress\", \"q\", \"rp\", \"rt\", \"ruby\", \"samp\", \"script\",\n                   \"section\", \"select\", \"small\", \"source\", \"spacer\", \"span\",\n                   \"strong\", \"style\", \"sub\", \"summary\", \"sup\", \"svg\", \"table\",\n                   \"tbody\", \"td\", \"textarea\", \"tfoot\", \"th\", \"thead\", \"time\",\n                   \"title\", \"tr\", \"track\", \"u\", \"ul\", \"var\", \"video\", \"wbr\"],\n\n    // HTML5 allows SVG elements\n    svgElements:  [\"a\", \"altglyph\", \"altglyphdef\", \"altglyphitem\", \"animate\",\n                   \"animatecolor\", \"animatemotion\", \"animatetransform\", \"circle\",\n                   \"clippath\", \"color-profile\", \"cursor\", \"defs\", \"desc\",\n                   \"ellipse\", \"feblend\", \"fecolormatrix\", \"fecomponenttransfer\",\n                   \"fecomposite\", \"feconvolvematrix\", \"fediffuselighting\",\n                   \"fedisplacementmap\", \"fedistantlight\", \"feflood\", \"fefunca\",\n                   \"fefuncb\", \"fefuncg\", \"fefuncr\", \"fegaussianblur\", \"feimage\",\n                   \"femerge\", \"femergenode\", \"femorphology\", \"feoffset\",\n                   \"fepointlight\", \"fespecularlighting\", \"fespotlight\",\n                   \"fetile\", \"feturbulence\", \"filter\", \"font\", \"font-face\",\n                   \"font-face-format\", \"font-face-name\", \"font-face-src\",\n                   \"font-face-uri\", \"foreignobject\", \"g\", \"glyph\", \"glyphref\",\n                   \"hkern\", \"image\", \"line\", \"lineargradient\", \"marker\", \"mask\",\n                   \"metadata\", \"missing-glyph\", \"mpath\", \"path\", \"pattern\",\n                   \"polygon\", \"polyline\", \"radialgradient\", \"rect\", \"script\",\n                   \"set\", \"stop\", \"style\", \"svg\", \"switch\", \"symbol\", \"text\",\n                   \"textpath\", \"title\", \"tref\", \"tspan\", \"use\", \"view\", \"vkern\"],\n\n    // We also keep a list of HTML elements that are now obsolete, but\n    // may still be encountered in the wild on popular sites.\n    obsoleteHtmlElements: [\"acronym\", \"applet\", \"basefont\", \"big\", \"center\",\n                           \"dir\", \"font\", \"isindex\", \"listing\", \"noframes\",\n                           \"plaintext\", \"s\", \"strike\", \"tt\", \"xmp\"],\n\n    // This is a helper function to determine whether a given string\n    // is a legal HTML5 element tag.\n    _knownHTMLElement: function(tagName) {\n      return this.voidHtmlElements.indexOf(tagName) > -1 ||\n              this.htmlElements.indexOf(tagName) > -1 ||\n              this.obsoleteHtmlElements.indexOf(tagName) > -1;\n    },\n    // This is a helper function to determine whether a given string\n    // is a legal SVG element tag.\n    _knownSVGElement: function(tagName) {\n      return this.svgElements.indexOf(tagName) > -1;\n    },\n    // This is a helper function to determine whether a given string\n    // is a void HTML element tag.\n    _knownVoidHTMLElement: function(tagName) {\n      return this.voidHtmlElements.indexOf(tagName) > -1;\n    },\n    // #### The HTML Master Parse Function\n    //\n    // The HTML master parse function works the same as the CSS\n    // parser: it takes the token stream and will try to parse\n    // the content as a sequence of HTML elements.\n    //\n    // Any parse errors along the way will result in the code\n    // throwing a `ParseError`.\n    parse: function() {\n      // First we check to see if the beginning of our stream is\n      // an HTML5 doctype tag. We're currently quite strict and don't\n      // parse XHTML or other doctypes.\n      if (this.stream.match(this.html5Doctype, true, true))\n        this.domBuilder.fragment.parseInfo = {\n          doctype: {\n            start: 0,\n            end: this.stream.pos\n          }\n        };\n\n      // Next, we parse \"tag soup\", creating text nodes and diving into\n      // tags as we find them.\n      while (!this.stream.end()) {\n        if (this.stream.peek() == '<') {\n          this._buildTextNode();\n          this._parseStartTag();\n        } else\n          this.stream.next();\n      }\n\n      this._buildTextNode();\n\n      // At the end, it's possible we're left with an open tag, so\n      // we test for that.\n      if (this.domBuilder.currentNode != this.domBuilder.fragment)\n        throw new ParseError(\"UNCLOSED_TAG\", this);\n    },\n    // This is a helper to build a DOM text node.\n    _buildTextNode: function() {\n      var token = this.stream.makeToken();\n      if (token) {\n        this.domBuilder.text(replaceEntityRefs(token.value), token.interval);\n      }\n    },\n    // #### HTML Tag Parsing\n    //\n    // This is the entry point for parsing the beginning of an HTML tag.\n    // It assumes the stream is on a `<` character.\n    _parseStartTag: function() {\n      if (this.stream.next() != '<')\n        throw new Error('assertion failed, expected to be on \"<\"');\n\n      if (this.stream.match('!--', true)) {\n        this._parseComment();\n        return;\n      }\n\n      this.stream.eat(/\\//);\n      this.stream.eatWhile(/[\\w\\d]/);\n      var token = this.stream.makeToken();\n      var tagName = token.value.slice(1).toLowerCase();\n\n      if (tagName === \"svg\")\n        this.parsingSVG = true;\n\n      // If the character after the `<` is a `/`, we're on a closing tag.\n      // We want to report useful errors about whether the tag is unexpected\n      // or doesn't match with the most recent opening tag.\n      if (tagName[0] == '/') {\n        var closeTagName = tagName.slice(1).toLowerCase();\n        if (closeTagName === \"svg\")\n          this.parsingSVG = false;\n        if (this._knownVoidHTMLElement(closeTagName))\n          throw new ParseError(\"CLOSE_TAG_FOR_VOID_ELEMENT\", this,\n                               closeTagName, token);\n        if (!this.domBuilder.currentNode.parseInfo)\n          throw new ParseError(\"UNEXPECTED_CLOSE_TAG\", this, closeTagName,\n                               token);\n        this.domBuilder.currentNode.parseInfo.closeTag = {\n          start: token.interval.start\n        };\n        var openTagName = this.domBuilder.currentNode.nodeName.toLowerCase();\n        if (closeTagName != openTagName)\n          throw new ParseError(\"MISMATCHED_CLOSE_TAG\", this, openTagName,\n                               closeTagName, token);\n        this._parseEndCloseTag();\n      }\n\n      else {\n        if (!tagName || (tagName && ((this.parsingSVG && !this._knownSVGElement(tagName)) || (!this.parsingSVG && !this._knownHTMLElement(tagName)))))\n          throw new ParseError(\"INVALID_TAG_NAME\", tagName, token);\n\n        var parseInfo = { openTag: { start: token.interval.start }};\n        var nameSpace = (this.parsingSVG ? this.svgNameSpace : undefined);\n        this.domBuilder.pushElement(tagName, parseInfo, nameSpace);\n\n        if (!this.stream.end())\n          this._parseEndOpenTag(tagName);\n      }\n    },\n    // This helper parses HTML comments. It assumes the stream has just\n    // passed the beginning `<!--` of an HTML comment.\n    _parseComment: function() {\n      var token;\n      while (!this.stream.end()) {\n        if (this.stream.match('-->', true)) {\n          token = this.stream.makeToken();\n          this.domBuilder.comment(token.value.slice(4, -3), token.interval);\n          return;\n        }\n        this.stream.next();\n      }\n      token = this.stream.makeToken();\n      throw new ParseError(\"UNTERMINATED_COMMENT\", token);\n    },\n    // This helper parses CDATA content, which should be treated as raw text,\n    // rather than being parsed for markup. It assumes the stream has just\n    // passed the beginning `<tagname` of an HTML element.\n    _parseCDATA: function(tagname) {\n      var token,\n           matchString = '</'+tagname+'>',\n           text,\n           textInterval = { start: 0, end: 0 },\n           openTagEnd = this.domBuilder.currentNode.parseInfo.openTag.end,\n           closeTagInterval;\n\n      this.stream.makeToken();\n      while (!this.stream.end()) {\n        if (this.stream.match(matchString, true)) {\n          token = this.stream.makeToken();\n          text = token.value.slice(0, -matchString.length);\n          closeTagInterval = {\n            start: openTagEnd + text.length,\n            end: token.interval.end\n          };\n          this.domBuilder.currentNode.parseInfo.closeTag = closeTagInterval;\n          textInterval.start = token.interval.start;\n          textInterval.end = token.interval.end - (closeTagInterval.end - closeTagInterval.start);\n          this.domBuilder.text(text, textInterval);\n          this.domBuilder.popElement();\n          return;\n        }\n        this.stream.next();\n      }\n      throw new ParseError(\"UNCLOSED_TAG\", this);\n    },\n    // This helper function parses the end of a closing tag. It expects\n    // the stream to be right after the end of the closing tag's tag\n    // name.\n    _parseEndCloseTag: function() {\n      this.stream.eatSpace();\n      if (this.stream.next() != '>')\n        throw new ParseError(\"UNTERMINATED_CLOSE_TAG\", this);\n      var end = this.stream.makeToken().interval.end;\n      this.domBuilder.currentNode.parseInfo.closeTag.end = end;\n      this.domBuilder.popElement();\n    },\n    // This helper function parses the rest of an opening tag after\n    // its tag name, looking for `attribute=\"value\"` data until a\n    // `>` is encountered.\n    _parseEndOpenTag: function(tagName) {\n      /* FIXME: we probably don't need while() here, as the parser will\n       *        either cleanly terminate or throw a ParseError anyway? */\n      while (!this.stream.end()) {\n        if (this.stream.eatWhile(/[A-Za-z\\-]/)) {\n          this._parseAttribute();\n        }\n        else if (this.stream.eatSpace()) {\n          this.stream.makeToken();\n        }\n        else if (this.stream.peek() == '>' || this.stream.match(\"/>\")) {\n          var selfClosing = this.stream.match(\"/>\", true);\n          if (selfClosing) {\n            if (!this.parsingSVG && !this._knownVoidHTMLElement(tagName))\n              throw new ParseError(\"SELF_CLOSING_NON_VOID_ELEMENT\", this,\n                                   tagName);\n          } else\n            this.stream.next();\n          var end = this.stream.makeToken().interval.end;\n          this.domBuilder.currentNode.parseInfo.openTag.end = end;\n\n          // If the opening tag represents a void element, there will not be\n          // a closing element, so we tell our DOM builder that we're done.\n          if (tagName && ((selfClosing && this._knownSVGElement(tagName)) || this._knownVoidHTMLElement(tagName)))\n            this.domBuilder.popElement();\n\n          // If the opening tag represents a `<style>` element, we hand\n          // off parsing to our CSS parser.\n          if (!this.stream.end() && tagName === \"style\") {\n            var cssBlock = this.cssParser.parse();\n            this.domBuilder.text(cssBlock.value, cssBlock.parseInfo);\n          }\n\n          // If the opening tag represents a `<textarea>` element, we need\n          // to parse all its contents as CDATA (unparsed character data)\n          if (tagName && tagName === \"script\") {\n            this._parseCDATA(\"script\");\n          }\n\n          // If the opening tag represents a `<textarea>` element, we need\n          // to parse all its contents as CDATA (unparsed character data)\n          if (tagName && tagName === \"textarea\") {\n            this._parseCDATA(\"textarea\");\n          }\n\n          return;\n        } else\n          throw new ParseError(\"UNTERMINATED_OPEN_TAG\", this);\n      }\n    },\n    // This helper function parses an HTML tag attribute. It expects\n    // the stream to be right after the end of an attribute name.\n    _parseAttribute: function() {\n      var nameTok = this.stream.makeToken();\n      nameTok.value = nameTok.value.toLowerCase();\n      this.stream.eatSpace();\n      // If the character after the attribute name is a `=`, then we\n      // look for an attribute value; otherwise, this is a boolean\n      // attribute.\n      if (this.stream.peek() == '=') {\n        this.stream.next();\n        // Currently, we only support quoted attribute values, even\n        // though the HTML5 standard allows them to sometimes go unquoted.\n        this.stream.eatSpace();\n        this.stream.makeToken();\n        var quoteType = this.stream.next();\n        if (quoteType !== '\"' && quoteType !== \"'\") {\n          throw new ParseError(\"UNQUOTED_ATTR_VALUE\", this);\n        }\n        if (quoteType === '\"') {\n          this.stream.eatWhile(/[^\"]/);\n        } else {\n          this.stream.eatWhile(/[^']/);\n        }\n        if (this.stream.next() !== quoteType) {\n          throw new ParseError(\"UNTERMINATED_ATTR_VALUE\", this, nameTok);\n        }\n        var valueTok = this.stream.makeToken();\n        var unquotedValue = replaceEntityRefs(valueTok.value.slice(1, -1));\n        this.domBuilder.attribute(nameTok.value, unquotedValue, {\n          name: nameTok.interval,\n          value: valueTok.interval\n        });\n      } else {\n        this.stream.makeToken();\n        this.domBuilder.attribute(nameTok.value, '', {\n          name: nameTok.interval\n        });\n      }\n    }\n  };\n\n  // ### The DOM Builder\n  //\n  // The DOM builder is used to construct a DOM representation of the\n  // HTML/CSS being parsed. Each node contains a `parseInfo` expando\n  // property that contains information about the text extents of the\n  // original source code that the DOM element maps to.\n  //\n  // The DOM builder is given a single document DOM object that will\n  // be used to create all necessary DOM nodes.\n  function DOMBuilder(document) {\n    this.document = document;\n    this.fragment = document.createDocumentFragment();\n    this.currentNode = this.fragment;\n  }\n\n  DOMBuilder.prototype = {\n    // This method pushes a new element onto the DOM builder's stack.\n    // The element is appended to the currently active element and is\n    // then made the new currently active element.\n    pushElement: function(tagName, parseInfo, nameSpace) {\n      var node = (nameSpace ? this.document.createElementNS(nameSpace,tagName)\n                            : this.document.createElement(tagName));\n      node.parseInfo = parseInfo;\n      this.currentNode.appendChild(node);\n      this.currentNode = node;\n    },\n    // This method pops the current element off the DOM builder's stack,\n    // making its parent element the currently active element.\n    popElement: function() {\n      this.currentNode = this.currentNode.parentNode;\n    },\n    // This method appends an HTML comment node to the currently active\n    // element.\n    comment: function(data, parseInfo) {\n      var comment = this.document.createComment('');\n      comment.nodeValue = data;\n      comment.parseInfo = parseInfo;\n      this.currentNode.appendChild(comment);\n    },\n    // This method appends an attribute to the currently active element.\n    attribute: function(name, value, parseInfo) {\n      var attrNode = this.document.createAttribute(name);\n      attrNode.parseInfo = parseInfo;\n      attrNode.nodeValue = value;\n      this.currentNode.attributes.setNamedItem(attrNode);\n    },\n    // This method appends a text node to the currently active element.\n    text: function(text, parseInfo) {\n      var textNode = this.document.createTextNode(text);\n      textNode.parseInfo = parseInfo;\n      this.currentNode.appendChild(textNode);\n    }\n  };\n\n  // ### Exported Symbols\n  //\n  // `Slowparse` is the object that holds all exported symbols from\n  // this library.\n  var Slowparse = {\n    // We export our list of recognized HTML elements and CSS properties\n    // for clients to use if needed.\n    HTML_ELEMENT_NAMES: HTMLParser.prototype.voidHtmlElements.concat(\n                          HTMLParser.prototype.htmlElements.concat(\n                            HTMLParser.prototype.obsoleteHtmlElements)),\n    CSS_PROPERTY_NAMES: CSSParser.prototype.cssProperties,\n\n    // We also export a few internal symbols for use by Slowparse's\n    // testing suite.\n    replaceEntityRefs: replaceEntityRefs,\n    Stream: Stream,\n\n    // `Slowparse.HTML()` is the primary function we export. Given\n    // a DOM document object (or a DOMBuilder instance) and a string\n    // of HTML, we return an object with the following keys:\n    //\n    // * `document` is a DOM document fragment containing the DOM of\n    //   the parsed HTML. If an error occurred while parsing, this\n    //   document is incomplete, and represents what was built before\n    //   the error was encountered.\n    //\n    // * `error` is a JSON-serializable object representing any error\n    //   that occurred while parsing. If no errors occurred while parsing,\n    //   its value is `null`. For a list of the types of errors that\n    //   can be returned, see the [error specification][].\n    //\n    // An array of error detector functions can also be passed as a\n    // third argument to this function. An error detector function takes\n    // the HTML and generated document fragment as arguments and returns\n    // an error object if an error is detected, or `undefined` otherwise.\n    // This can be used for further error checking on the parsed document.\n    //\n    //   [error specification]: spec/\n    HTML: function(document, html, errorDetectors) {\n      var stream = new Stream(html),\n          domBuilder,\n          parser,\n          error = null;\n\n      if (document.pushElement)\n        domBuilder = document;\n      else\n        domBuilder = new DOMBuilder(document);\n      parser = new HTMLParser(stream, domBuilder);\n\n      try {\n        parser.parse();\n      } catch (e) {\n        if (e.parseInfo) {\n          error = e.parseInfo;\n        } else\n          throw e;\n      }\n\n      (errorDetectors || []).forEach(function(detector) {\n        if (!error)\n          error = detector(html, domBuilder.fragment) || null;\n      });\n\n      return {\n        document: domBuilder.fragment,\n        error: error\n      };\n    },\n    // `Slowparse.findError()` just returns any error in the given HTML\n    // string, or `null` if the HTML contains no errors.\n    findError: function(html, errorDetectors) {\n      return this.HTML(document, html, errorDetectors).error;\n    }\n  };\n\n  if (typeof(define) == \"function\") {\n    define(function() { return Slowparse; });\n  } else\n    return Slowparse;\n})();\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/spec/errors.base.html",
    "content": "<!-- HTML ERRORS -->\n<div class=\"error-msg UNEXPECTED_CLOSE_TAG\">\n  <p>The closing <code>&lt;/{{closeTag.name}}&gt;</code> tag \n    <em data-highlight=\"{{closeTag.start}},{{closeTag.end}}\">here</em> \n    doesn't pair with anything, because there are no opening tags that need to\n    be closed.</p>\n</div>\n<div class=\"error-msg MISMATCHED_CLOSE_TAG\">\n  <p>The closing <code>&lt;/{{closeTag.name}}&gt;</code> tag \n    <em data-highlight=\"{{closeTag.start}},{{closeTag.end}}\">here</em> \n    doesn't pair with the opening <code>&lt;{{openTag.name}}&gt;</code> tag\n    <em data-highlight=\"{{openTag.start}},{{openTag.end}}\">here</em>.</p>\n</div>\n<div class=\"error-msg CLOSE_TAG_FOR_VOID_ELEMENT\">\n  <p>The closing <code>&lt;/{{closeTag.name}}&gt;</code> tag \n    <em data-highlight=\"{{closeTag.start}},{{closeTag.end}}\">here</em> \n    is for a void element (that is, an element that doesn't need to be \n    closed).</p>\n</div>\n<div class=\"error-msg SELF_CLOSING_NON_VOID_ELEMENT\">\n  <p>The <code>&lt;{{name}}&gt;</code> tag \n    <em data-highlight=\"{{start}},{{end}}\">here</em> \n    can't be self-closed, because <code>&lt;{{name}}&gt;</code> is not\n    a void element; it must be closed with a separate \n    <code>&lt;/{{name}}&gt;</code> tag.</p>\n</div>\n<div class=\"error-msg UNCLOSED_TAG\">\n  <p>The <code>&lt;{{openTag.name}}&gt;</code> tag \n    <em data-highlight=\"{{openTag.start}},{{openTag.end}}\">here</em> \n    never closes.</p>\n</div>\n<div class=\"error-msg INVALID_TAG_NAME\">\n  <p>The <code>&lt;</code> character\n    <em data-highlight=\"{{openTag.start}},{{openTag.end}}\">here</em> appears\n    to be the beginning of a tag, but is not followed by a valid tag name.</p>\n\n  <p>If you just want a <code>&lt;</code> to appear on your Web\n    page, try using <code>&amp;lt;</code> instead.</p>\n    \n  <p>Or, see a <a href=\"http://www.stresslessweb.com/wp-content/uploads/2010/12/PeriodicTableOfTheElements-JoshDuck1.png\">list of\n    HTML5 tags</a>.</p>\n</div>\n<div class=\"error-msg UNTERMINATED_ATTR_VALUE\">\n  <p>The <code>&lt;{{openTag.name}}&gt;</code> tag's \n    <code>{{attribute.name.value}}</code> attribute has a value\n    <em data-highlight=\"{{attribute.value.start}}\">here</em> that\n    doesn't end with a closing double quote.</p>\n</div>\n<div class=\"error-msg UNQUOTED_ATTR_VALUE\">\n  <p>The Attribute value <em data-highlight=\"{{start}}\">here</em>\n    should start with an opening double quote.</p>\n</div>\n<div class=\"error-msg UNTERMINATED_CLOSE_TAG\">\n  <p>The closing <code>&lt;/{{closeTag.name}}&gt;</code> tag \n    <em data-highlight=\"{{closeTag.start}},{{closeTag.end}}\">here</em>\n    doesn't end with a <code>&gt;</code>.</p>\n</div>\n<div class=\"error-msg UNTERMINATED_OPEN_TAG\">\n  <p>The opening <code>&lt;{{openTag.name}}&gt;</code> tag\n    <em data-highlight=\"{{openTag.start}},{{openTag.end}}\">here</em>\n    doesn't end with a <code>&gt;</code>.</p>\n</div>\n<div class=\"error-msg UNTERMINATED_COMMENT\">\n  <p>The comment <em data-highlight=\"{{start}}\">here</em>\n    doesn't end with a <code>--&gt;</code>.</p>\n</div>\n\n<!-- CSS ERRORS -->\n<div class=\"error-msg INVALID_CSS_DECLARATION\">\n  <p><em data-highlight=\"{{cssDeclaration.start}},{{cssDeclaration.end}}\">This</em>\n    CSS declaration never closes.</p>\n</div>\n<div class=\"error-msg INVALID_CSS_PROPERTY_NAME\">\n  <p>CSS property <em data-highlight=\"{{cssProperty.start}},{{cssProperty.end}}\">{{cssProperty.property}}</em>\n     does not exist. You may want to see a\n     <a href=\"https://developer.mozilla.org/en/CSS/CSS_Reference\">list\n       of CSS properties</a>.</p>\n</div>\n<div class=\"error-msg INVALID_CSS_RULE\">\n  <p><em data-highlight=\"{{cssRule.start}},{{cssRule.end}}\">This</em>\n    CSS rule is not legal CSS.</p>\n</div>\n<div class=\"error-msg MISSING_CSS_SELECTOR\">\n  <p>Missing either a new CSS selector or the &lt;/style&gt; tag <em data-highlight=\"{{cssBlock.start}},{{cssBlock.end}}\">here</em>.\n  </p>\n</div>\n<div class=\"error-msg UNFINISHED_CSS_SELECTOR\">\n  <p>Selector <em data-highlight=\"{{cssSelector.start}},{{cssSelector.end}}\">{{cssSelector.selector}}</em>\n  still needs finalising with {\n  </p>\n</div>\n<div class=\"error-msg INVALID_CSS_PROPERTY_NAME\">\n  <p><em data-highlight=\"{{cssProperty.start}},{{cssProperty.end}}\">{{cssProperty.property}}</em> is not\n  a valid CSS property.</p>\n</div>\n<div class=\"error-msg MISSING_CSS_PROPERTY\">\n  <p>Missing property for <em data-highlight=\"{{cssSelector.start}},{{cssSelector.end}}\">{{cssSelector.selector}}</em>.\n  </p>\n</div>\n<div class=\"error-msg UNFINISHED_CSS_PROPERTY\">\n  <p>Property <em data-highlight=\"{{cssProperty.start}},{{cssProperty.end}}\">{{cssProperty.property}}</em>\n  still needs finalising with :\n  </p>\n</div>\n<div class=\"error-msg MISSING_CSS_VALUE\">\n  <p>Missing value for <em data-highlight=\"{{cssProperty.start}},{{cssProperty.end}}\">{{cssProperty.property}}</em>.\n  </p>\n</div>\n<div class=\"error-msg UNFINISHED_CSS_VALUE\">\n  <p>Value <em data-highlight=\"{{cssValue.start}},{{cssValue.end}}\">{{cssValue.value}}</em>\n  still needs finalising with ;\n  </p>\n</div>\n<div class=\"error-msg MISSING_CSS_BLOCK_OPENER\">\n  <p>Missing block opener after <em data-highlight=\"{{cssSelector.start}},{{cssSelector.end}}\">{{cssSelector.selector}}</em>.\n  </p>\n</div>\n<div class=\"error-msg MISSING_CSS_BLOCK_CLOSER\">\n  <p>Missing block closer or next property:value; pair following <em data-highlight=\"{{cssValue.start}},{{cssValue.end}}\">{{cssValue.value}}</em>.\n  </p>\n</div>\n<div class=\"error-msg UNCAUGHT_CSS_PARSE_ERROR\">\n  <p>A parse error occurred outside expected cases: <em data-highlight=\"{{error.start}},{{error.end}}\">{{error.msg}}</em>\n  </p>\n</div>\n<div class=\"error-msg UNTERMINATED_CSS_COMMENT\">\n  <p>The CSS comment <em data-highlight=\"{{start}}\">here</em>\n    doesn't end with a <code>*/</code>.</p>\n</div>\n<div class=\"error-msg HTML_CODE_IN_CSS_BLOCK\">\n  <p>HTML code was detected in CSS context starting <em data-highlight=\"{{html.start}},{{html.end}}\">here</em>\n</div>\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/spec/errors.forbidjs.html",
    "content": "<!-- FORBIDJS ERRORS -->\n<div class=\"error-msg SCRIPT_ELEMENT_NOT_ALLOWED\">\n  <p>Sorry, but security restrictions on this site prevent you from\n    using <code>&lt;script&gt;</code> tags \n    <em data-highlight=\"{{openTag.start}},{{closeTag.end}}\">here</em>. If you really need to \n    use JavaScript, consider using <a href=\"http://jsbin.com/\">jsbin</a> \n    or <a href=\"http://jsfiddle.net/\">jsfiddle</a>.</p>\n</div>\n<div class=\"error-msg EVENT_HANDLER_ATTR_NOT_ALLOWED\">\n  <p>Sorry, but security restrictions on this site prevent you from\n    using the JavaScript event handler attribute \n    <em data-highlight=\"{{name.start}},{{name.end}}\">here</em>.\n    If you really need to use JavaScript, consider using\n    <a href=\"http://jsbin.com/\">jsbin</a> \n    or <a href=\"http://jsfiddle.net/\">jsfiddle</a>.</p>\n</div>\n<div class=\"error-msg JAVASCRIPT_URL_NOT_ALLOWED\">\n  <p>Sorry, but security restrictions on this site prevent you from\n    using the <code>javascript:</code> URL \n    <em data-highlight=\"{{value.start}},{{value.end}}\">here</em>.\n    If you really need to use JavaScript, consider using\n    <a href=\"http://jsbin.com/\">jsbin</a> \n    or <a href=\"http://jsfiddle.net/\">jsfiddle</a>.</p>\n</div>\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/spec/errors.jquery.js",
    "content": "\"use strict\";\n\n// This jQuery plugin adds functions that make it easy to display\n// friendly tips to a user based on Slowparse errors. For more information\n// on Slowparse errors, see the [error specification][spec].\n//\n// For examples of this plugin in use, consult its [test suite][].\n//\n//  [spec]: spec/\n//  [test suite]: https://github.com/mozilla/slowparse/blob/gh-pages/test/test-errors.jquery.js\n\n(function(jQuery) {\n  var $ = jQuery;\n  \n  // ## jQuery Extensions\n  \n  jQuery.extend({\n    // **jQuery.errorTemplates** is a selection that contains all our error\n    // message templates.\n    \n    errorTemplates: $(),\n    // **jQuery.loadErrors(*basePath*, *names*, *cb*)** loads a set of error\n    // message templates.\n    //\n    // * *basePath* is the relative path containing the error message\n    //   template HTML files.\n    //\n    // * *names* is an array of template files to load. For each `name`\n    //   in this array, the file `errors.name.html` will be loaded from \n    //   *basePath*.\n    //\n    // * *cb* is a function that will be called once all the templates\n    //   are loaded. Its first argument will be null only if no errors\n    //   occurred.\n    loadErrors: function(basePath, names, cb) {\n      var reqs = names.map(function(name) {\n        var url = basePath + \"errors.\" + name + \".html\";\n        return jQuery.get(url);\n      });\n      jQuery.when.apply(jQuery, reqs).then(function() {\n        reqs.forEach(function(req) {\n          var div = $('<div></div>').html(req.responseText);\n          $.errorTemplates = $.errorTemplates.add($(\".error-msg\", div));\n        });\n        cb(null);\n      }, function() {\n        cb(\"ERROR: At least one template file did not load.\");\n      });\n    }\n  });\n  \n  jQuery.fn.extend({\n    // **jQuery.fn.errorHighlightInterval()** returns an object\n    // containing `{start, end}` keys that describe the integral start and\n    // end indexes of a `data-highlight` attribute on the first\n    // element of the current selection.\n    errorHighlightInterval: function() {\n      var interval = $(this).attr(\"data-highlight\").split(\",\");\n      var start = parseInt(interval[0]);\n      var end = interval[1] ? parseInt(interval[1]) : undefined;\n      return {start: start, end: end};\n    },\n    \n    // **jQuery.fn.eachErrorHighlight(*cb*)** calls the given callback on\n    // every element with a `data-highlight` attribute in the current\n    // selection. The callback is passed `(start, end, i)` arguments\n    // which represent the integral start and end of the highlight, and\n    // the array index of the element.\n    eachErrorHighlight: function(cb) {\n      $(\"[data-highlight]\", this).each(function(i) {\n        var interval = $(this).errorHighlightInterval();\n        cb.call(this, interval.start, interval.end, i);\n      });\n      return this;\n    },\n    \n    // **jQuery.fn.fillError(*error* [, *templates*])** fills the current selection with the\n    // friendly error message for the given error object. For more\n    // information on error objects, see the [error specification][spec].\n    //\n    // Optionally, a second argument containing a selection of all\n    // available error templates can be provided. If not present, the\n    // global selection of templates from `jQuery.errorTemplates` will\n    // be used.\n    //\n    //   [spec]: spec/\n    fillError: function(error, templates) {\n      var selector = \".error-msg.\" + error.type;\n      var template = (templates || $.errorTemplates).filter(selector);\n      if (template.length == 0)\n        throw new Error(\"Error template not found for \" + error.type);\n      this.html(_.template(template.html(), error, mustacheSettings)).show();\n      return this;\n    }\n  });\n\n  // ## Underscore.js Templating\n  //\n  // We define a private subset of [underscore.js][] that includes only\n  // `_.escape()` and `_.template()`. This is done to avoid the need for\n  // including underscore as a dependency.\n  //\n  // The `_.template()` function has been stripped of functionality to\n  // interpolate and evaluate, since we don't need that functionality\n  // for our error reporting.\n  //\n  //   [underscore.js]: http://documentcloud.github.com/underscore/  \n  var _ = (function createUnderscoreTemplating() {\n    // Certain characters need to be escaped so that they can be put into a\n    // string literal.\n    var escapes = {\n      '\\\\': '\\\\',\n      \"'\": \"'\",\n      'r': '\\r',\n      'n': '\\n',\n      't': '\\t',\n      'u2028': '\\u2028',\n      'u2029': '\\u2029'\n    };\n\n    for (var p in escapes) escapes[escapes[p]] = p;\n    var escaper = /\\\\|'|\\r|\\n|\\t|\\u2028|\\u2029/g;\n  \n    var _ = {\n      // Escape a string for HTML interpolation.\n      escape: function escape(string) {\n        return (''+string)\n          .replace(/&/g, '&amp;')\n          .replace(/</g, '&lt;')\n          .replace(/>/g, '&gt;')\n          .replace(/\"/g, '&quot;')\n          .replace(/'/g, '&#x27;')\n          .replace(/\\//g,'&#x2F;');\n      },\n  \n      // JavaScript micro-templating, similar to John Resig's implementation.\n      // Underscore templating handles arbitrary delimiters, preserves\n      // whitespace, and correctly escapes quotes within interpolated code.\n      template: function template(text, data, settings) {\n        // Compile the template source, taking care to escape characters that\n        // cannot be included in a string literal and then unescape them in\n        // code blocks.\n        var source = \"__p+='\" + text\n          .replace(escaper, function(match) {\n            return '\\\\' + escapes[match];\n          })\n          .replace(settings.escape || noMatch, function(match, code) {\n            return \"'+\\n((__t=(\" + unescape(code) + \n                   \"))==null?'':_.escape(__t))+\\n'\";\n          }) + \"';\\n\";\n\n        // If a variable is not specified, place data values in local scope.\n        if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n        source = \"var __t,__p='',__j=Array.prototype.join,\" +\n          \"print=function(){__p+=__j.call(arguments,'')};\\n\" +\n          source + \"return __p;\\n\";\n\n        var render = new Function(settings.variable || 'obj', '_', source);\n        if (data) return render(data, _);\n        var template = function(data) {\n          return render.call(this, data, _);\n        };\n\n        // Provide the compiled function source as a convenience for\n        // precompilation.\n        template.source = 'function(' + (settings.variable || 'obj') +\n                          '){\\n' + source + '}';\n\n        return template;\n      }\n    };\n    \n    return _;\n  })();\n  \n  // We want to use \"mustache\"-style templating, e.g. `hello there {{name}}`.\n  var mustacheSettings = {\n    escape: /\\{\\{(.+?)\\}\\}/g\n  };\n})(jQuery);\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/spec/index.html",
    "content": "<!DOCTYPE html>\n<meta charset=\"utf-8\">\n<title>Slowparse Error Reporting Specification</title>\n<style>\nhtml, body {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: small;\n}\n\nbody {\n  width: 800px;\n  margin: 0 auto 1em auto;\n}\n\ndiv.report > h2:before {\n  content: \"ERROR TYPE: \";\n  color: gray;\n}\n\n.test.failed div.report > h2:before {\n  content: 'FATAL ERROR';\n  color: black;\n}\n\npre, div.js {\n  font-family: Menlo, Monaco, \"Lucida Console\", monospace;\n}\n\ndiv.console {\n  background: black;\n  padding: 10px;\n}\n\ndiv.js {\n  color: lightgreen;\n}\n\ndiv.js > div {\n  display: pre;\n}\n\ndiv.js > div:before {\n  content: '> ';\n  color: gray;\n}\n\npre.result {\n  color: lightgray;\n}\n\npre.html {\n  background: #f0f0f0;\n  color: black;\n  padding: 10px;\n}\n\n.color-1 {\n  background: pink;\n}\n\n.color-2 {\n  background: black;\n  color: white;\n}\n\n.error em {\n  font-style: inherit;\n}\n\na {\n  color: inherit;\n}\n\n.test {\n  margin-top: 3em;\n  border-left: 1px solid black;\n  padding-left: 0.5em;\n}\n\n.test.failed, .test.failed .html {\n  background: firebrick;\n}\n\n.test.failed div.console {\n  background: darkred;\n}\n\n.test > div.js, .test > div.bad-html {\n  display: none;\n}\n\nh1.error-category {\n  border-top: 1px dotted gray;\n  border-bottom: 1px dotted gray;\n}\n</style>\n<h1>Slowparse Error Reporting Specification</h1>\n<p>All of the following documentation is generated on-the-fly,\n  in your browser, by <a href=\"../?slowparse.js\">slowparse.js</a> and <a href=\"../?errors.jquery.js\">errors.jquery.js</a>. If something looks amiss, run the actual \n  output against the expected results at the <a href=\"../test/\">test suite</a>;\n  if errors are reported, please feel free to\n  <a href=\"https://github.com/mozilla/slowparse/issues\">file a bug</a>.</p>\n<p>You can also consult the <a href=\"../demo/\">live demo</a> to see this error\n  reporting used in an interactive widget.</p>\n<div id=\"templates\" style=\"display: none\">\n  <div class=\"report\">\n    <h2></h2>\n    <h3>Example</h3>\n    <pre class=\"html\"></pre>\n    <div class=\"error\"></div>\n    <h3>JavaScript Code</h3>\n    <div class=\"console\">\n      <div class=\"js\">\n        <div>Slowparse.findError({{HTML}});</div>\n      </div>\n      <pre class=\"result\"></pre>\n    </div>\n  </div>\n</div>\n<h1 class=\"error-category\">HTML Errors</h1>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hi</i>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNEXPECTED_CLOSE_TAG\",\n    \"closeTag\": {\n      \"name\": \"i\",\n      \"start\": 2,\n      \"end\": 5\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <p>hi</i>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"MISMATCHED_CLOSE_TAG\",\n    \"openTag\": {\n      \"name\": \"p\",\n      \"start\": 0,\n      \"end\": 3\n    },\n    \"closeTag\": {\n      \"name\": \"i\",\n      \"start\": 5,\n      \"end\": 8\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <br>hello</br>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"CLOSE_TAG_FOR_VOID_ELEMENT\",\n    \"closeTag\": {\n      \"name\": \"br\",\n      \"start\": 9,\n      \"end\": 13\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hello<p/>there\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"SELF_CLOSING_NON_VOID_ELEMENT\",\n    \"name\": \"p\",\n    \"start\": 5,\n    \"end\": 9\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hello <em>there\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNCLOSED_TAG\",\n    \"openTag\": {\n      \"name\": \"em\",\n      \"start\": 6,\n      \"end\": 10\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <-lol>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"INVALID_TAG_NAME\",\n    \"openTag\": {\n      \"name\": \"\",\n      \"start\": 0,\n      \"end\": 1\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hello <em>there</em dude.\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNTERMINATED_CLOSE_TAG\",\n    \"closeTag\": {\n      \"name\": \"em\",\n      \"start\": 15,\n      \"end\": 19\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <a class=foo bar>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNQUOTED_ATTR_VALUE\",\n    \"start\": 9\n  }\n  </script>\n  <h3>Notes</h3>\n  <p>The HTML5 specification actually allows unquoted attribute\n    values, so long as they don't have spaces in them. However,\n    this isn't commonly done outside of minifying HTML. Furthermore, by\n    complicating the standard, our predictions about the user's\n    intent also become ambiguous, which results in more cryptic\n    and confusing error messages. By choosing to enforce monotony, we\n    ease the learning process and provide more helpful\n    errors.</p>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hello <em </em>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNTERMINATED_OPEN_TAG\",\n    \"openTag\": {\n      \"start\": 6,\n      \"end\": 10,\n      \"name\": \"em\"\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hello <em class=\"foo>there</em>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNTERMINATED_ATTR_VALUE\",\n    \"openTag\": {\n      \"name\": \"em\",\n      \"start\": 6\n    },\n    \"attribute\": {\n      \"name\": {\n        \"value\": \"class\",\n        \"start\": 10,\n        \"end\": 15\n      },\n      \"value\": {\n        \"start\": 16\n      }\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hello <em class='foo>there</em>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNTERMINATED_ATTR_VALUE\",\n    \"openTag\": {\n      \"name\": \"em\",\n      \"start\": 6\n    },\n    \"attribute\": {\n      \"name\": {\n        \"value\": \"class\",\n        \"start\": 10,\n        \"end\": 15\n      },\n      \"value\": {\n        \"start\": 16\n      }\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hello <em class=\"foo'>there</em>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNTERMINATED_ATTR_VALUE\",\n    \"openTag\": {\n      \"name\": \"em\",\n      \"start\": 6\n    },\n    \"attribute\": {\n      \"name\": {\n        \"value\": \"class\",\n        \"start\": 10,\n        \"end\": 15\n      },\n      \"value\": {\n        \"start\": 16\n      }\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hello <em class='foo\">there</em>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNTERMINATED_ATTR_VALUE\",\n    \"openTag\": {\n      \"name\": \"em\",\n      \"start\": 6\n    },\n    \"attribute\": {\n      \"name\": {\n        \"value\": \"class\",\n        \"start\": 10,\n        \"end\": 15\n      },\n      \"value\": {\n        \"start\": 16\n      }\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    hi<!--blah\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNTERMINATED_COMMENT\",\n    \"start\": 2\n  }\n  </script>\n</div>\n\n<h1 class=\"error-category\">CSS Errors</h1>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNFINISHED_CSS_SELECTOR\",\n    \"cssSelector\": {\n      \"start\": 8,\n      \"end\": 9,\n      \"selector\": \"a\"\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a {\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"MISSING_CSS_PROPERTY\",\n    \"cssSelector\": {\n      \"start\": 8,\n      \"end\": 9,\n      \"selector\": \"a\"\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a { color\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNFINISHED_CSS_PROPERTY\",\n    \"cssProperty\": {\n      \"start\": 12,\n      \"end\": 17,\n      \"property\": \"color\"\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a { color:\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"MISSING_CSS_VALUE\",\n    \"cssProperty\": {\n      \"start\": 12,\n      \"end\": 17,\n      \"property\": \"color\"\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a { colour:\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"INVALID_CSS_PROPERTY_NAME\",\n    \"cssProperty\": {\n      \"start\": 12,\n      \"end\": 18,\n      \"property\": \"colour\"\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a { color: red\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNFINISHED_CSS_VALUE\",\n    \"cssValue\": {\n      \"start\": 19,\n      \"end\": 22,\n      \"value\": \"red\"\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a { color: red;\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"MISSING_CSS_BLOCK_CLOSER\",\n    \"cssValue\": {\n      \"start\": 19,\n      \"end\": 22,\n      \"value\": \"red\"\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a { color: red; }\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"MISSING_CSS_SELECTOR\",\n    \"cssBlock\": {\n      \"start\": 24,\n      \"end\": 25\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> a { li {\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"MISSING_CSS_BLOCK_CLOSER\",\n    \"cssValue\": {\n      \"start\": 8,\n      \"end\": 12,\n      \"value\": \"a\"\n    }\n  }\n  </script>\n</div>\n\n<div class=\"test\">\n  <div class=\"bad-html\">\n    &lt;style&gt;\n      &lt;!-- html comment in CSS block --&gt;\n    &lt;/style&gt;\n  </div>\n  <script type=\"application/json\">\n  {\n    \"type\": \"HTML_CODE_IN_CSS_BLOCK\",\n    \"html\": {\n      \"start\": 13,\n      \"end\": 14\n    }\n  }\n    </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style>\n      <p>html code in CSS block</p>\n    </style>\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"HTML_CODE_IN_CSS_BLOCK\",\n    \"html\": {\n      \"start\": 13,\n      \"end\": 14\n    }\n  }\n  </script>\n</div>\n\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <style> /* unterminated comment\n  </script>\n  <script type=\"application/json\">\n  {\n    \"type\": \"UNTERMINATED_CSS_COMMENT\",\n    \"start\": 8\n  }\n  </script>\n</div>\n\n<h1 class=\"error-category\">FORBIDJS Errors</h1>\n<p>The <code>tree-inspectors.js</code> script must be included to enable these errors.</p>\n<div class=\"test\">\n  <div class=\"bad-html\">\n    hi&lt;script&gt;alert('yo');&lt;/script&gt;\n  </div>\n  <div class=\"js\">Slowparse.findError({{HTML}}, [TreeInspectors.forbidJS]);</div>\n  <script type=\"application/json\">\n  {\n    \"type\": \"SCRIPT_ELEMENT_NOT_ALLOWED\",\n    \"openTag\": {\n      \"start\": 2,\n      \"end\": 10\n    },\n    \"closeTag\": {\n      \"start\": 22,\n      \"end\": 31\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <p onclick=\"alert('yo');\">hi</p>\n  </script>\n  <div class=\"js\">Slowparse.findError({{HTML}}, [TreeInspectors.forbidJS]);</div>\n  <script type=\"application/json\">\n  {\n    \"type\": \"EVENT_HANDLER_ATTR_NOT_ALLOWED\",\n    \"name\": {\n      \"start\": 3,\n      \"end\": 10\n    },\n    \"value\": {\n      \"start\": 11,\n      \"end\": 25\n    }\n  }\n  </script>\n</div>\n<div class=\"test\">\n  <script type=\"text/x-bad-html\">\n    <a href=\"javascript:alert('yo');\">hi</a>\n  </script>\n  <div class=\"js\">Slowparse.findError({{HTML}}, [TreeInspectors.forbidJS]);</div>\n  <script type=\"application/json\">\n  {\n    \"type\": \"JAVASCRIPT_URL_NOT_ALLOWED\",\n    \"name\": {\n      \"start\": 3,\n      \"end\": 7\n    },\n    \"value\": {\n      \"start\": 8,\n      \"end\": 33\n    }\n  }\n  </script>\n</div>\n\n\n<script src=\"../vendor/jquery.min.js\"></script>\n<script src=\"../slowparse.js\"></script>\n<script src=\"../tree-inspectors.js\"></script>\n<script src=\"spec.js\"></script>\n<script src=\"errors.jquery.js\"></script>\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/spec/spec.js",
    "content": "\"use strict\";\n\njQuery.fn.extend({\n  // Take the given element containing plain-text source code and\n  // rewrite it to highlight the spans mentioned in the data-highlight\n  // attributes of elements in the current selection (which is expected to\n  // be a human-readable error message). Also highlight said elements with\n  // the same color, so it's easy for a reader to visually identify what\n  // part of code something in the current selection is referring to.\n  showHighlights: function(source) {\n    function sourceText(interval) {\n      return source.text().slice(interval.start, interval.end);\n    }\n    \n    var newSource = $(\"<div></div>\"),\n        slices = [],\n        i = 0;\n    this.eachErrorHighlight(function(start, end, n) {\n      slices.push({\n        start: start,\n        end: end,\n        linkedNode: this\n      });\n      $(this).attr(\"class\", \"color-\" + (n + 1));\n    });\n    slices.sort(function(a, b) { return a.start - b.start; });\n    jQuery.each(slices, function(n, slice) {\n      var color = $(slice.linkedNode).attr(\"class\"),\n          span = $(\"<span></span>\");\n      if (slice.start > i) {\n        newSource.append(document.createTextNode(sourceText({\n          start: i,\n          end: slice.start\n        })));\n      }\n      span.addClass(color)\n        .text(sourceText(slice))\n        .appendTo(newSource);\n      i = slice.end;\n    });\n    if (i < source.text().length) {\n      newSource.append(document.createTextNode(sourceText({\n        start: i,\n        end: undefined\n      })));\n    }\n    source.html(newSource.html());\n    return this;\n  }\n});\n\n// Because the contents of the page are only fully loaded after the\n// browser has processed the URL fragment, we need to \"simulate\" scrolling\n// to the fragment once we've really finished loading the page.\nfunction refreshAnchor() {\n  var anchor = window.location.hash.slice(1);\n  if (anchor) {\n    var anchoredElement = document.getElementById(anchor);\n    if (anchoredElement)\n      anchoredElement.scrollIntoView();\n  }\n}\n\n// This function is called by a same-origin parent window that is supposedly\n// running a test suite. It delegates the testing of the verification of\n// our spec to this window, and therefore must pass in a number of\n// QUnit globals.\nfunction runTests(module, test, ok, deepEqual, cb) {\n  function safeParse(str) {\n    try {\n      return JSON.parse(str);\n    } catch (e) {\n      return null;\n    }\n  }\n\n  function testSpec() {\n    module(\"Specification correctness\");\n    $('div.test').each(function() {\n      var isFailed = $(this).hasClass(\"failed\");\n      var actualJson = $(\".result\", this).text();\n      var expectedJson = $('script[type=\"application/json\"]', this).text();\n      test($(\"h2\", this).attr(\"id\") + \" error type\", function() {\n        ok(!isFailed, \"error type specification did not fail to execute\");\n        expectedJson = safeParse(expectedJson);\n        ok(expectedJson, \"expectedJson is valid JSON\");\n        actualJson = safeParse(actualJson);\n        ok(actualJson, \"actualJson is valid JSON\");\n        deepEqual(actualJson, expectedJson, \"expectedJson == actualJson\");\n      });\n    });\n  }\n  \n  var interval = setInterval(function() {\n    if ($(\"html\").hasClass(\"done-loading\")) {\n      ok(true, \"<html> has done-loading class\");\n      clearInterval(interval);\n      testSpec();\n      cb();\n    }\n  }, 100);\n}\n\n$(window).ready(function() {\n  jQuery.loadErrors(\"\", [\"base\", \"forbidjs\"], function() {\n    $('div.test').each(function() {\n      var badHtmlElement = $('script[type=\"text/x-bad-html\"]', this);\n\n      if (badHtmlElement.length == 0)\n        badHtmlElement = $('div.bad-html', this);\n      \n      var badHtml = badHtmlElement.text().trim();\n      var t = $(\"#templates .report\").clone();\n      var js = $('div.js', this).text().trim();\n      var expect = $('script[type=\"application/json\"]', this).text();\n      var error, expectedError, expectedErrorType;\n\n      if (expect) {\n        expectedError = JSON.parse(expect);\n        expectedErrorType = expectedError.type;\n      }\n      \n      if (!js)\n        js = $(\".js > div:first-child\", t).text();\n      js = js.replace(\"{{HTML}}\", JSON.stringify(badHtml));\n      $(\".js > div:first-child\", t).text(js);\n      $(\".html\", t).text(badHtml);\n      try {\n        error = eval(js);\n      } catch (e) {\n        $(this).addClass(\"failed\");\n        $(\"h2\", t).text(expectedErrorType || \"UNKNOWN\");\n        $(\".result\", t).text(e.toString());\n        badHtmlElement.replaceWith(t);\n        return;\n      }\n      \n      expectedErrorType = expectedErrorType || error.type;\n      $(\"h2\", t).text(expectedErrorType).attr(\"id\", expectedErrorType);\n\n      var errMsg = $(\".error\", t);\n      try {\n        errMsg.fillError(error);\n      } catch (e) {\n        $(this).addClass(\"failed\");\n        errMsg.text(\"ERROR: \" + e.message);\n      }\n      errMsg.showHighlights($(\".html\", t));\n      badHtmlElement.replaceWith(t);\n      \n      // Set the result last, as this effectively tells the test\n      // suite that this test didn't throw an exception.\n      $(\".result\", t).text(JSON.stringify(error, null, \"  \"));\n    });\n    refreshAnchor();\n    $(\"html\").addClass(\"done-loading\");\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/test/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  </head>\n    <meta charset=\"utf-8\">\n    <title>Slowparse Test Suite</title>\n    <link rel=\"stylesheet\" href=\"qunit.css\">\n  </head>\n\n  <body>\n    <h1  id=\"qunit-header\">Slowparse Test Suite</h1>\n    <h2  id=\"qunit-banner\"></h2>\n    <div id=\"qunit-testrunner-toolbar\"></div>\n    <h2  id=\"qunit-userAgent\"></h2>\n    <ol  id=\"qunit-tests\"></ol>\n    <div id=\"qunit-fixture\"></div>\n  </body>\n\n  <script src=\"qunit.js\"></script>\n  <script src=\"../slowparse.js\"></script>\n  <script src=\"../tree-inspectors.js\"></script>\n  <script src=\"../vendor/jquery.min.js\"></script>\n  <script src=\"../spec/errors.jquery.js\"></script>\n  <script src=\"testing-utils.js\"></script>\n  <script src=\"test-slowparse.js\"></script>\n  <script src=\"test-tree-inspectors.js\"></script>\n  <script src=\"test-spec.js\"></script>\n  <script src=\"test-errors.jquery.js\"></script>\n  \n  <script>\n  if (location.search.match(/externalreporter=1/))\n    document.write('<script src=\"/externalreporter.js\"></' + 'script>');\n  </script>\n</html>\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/test/qunit.css",
    "content": "/**\n * QUnit v1.6.0pre - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n\tfont-family: \"Helvetica Neue Light\", \"HelveticaNeue-Light\", \"Helvetica Neue\", Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n#qunit-tests { font-size: smaller; }\n\n\n/** Resets */\n\n#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n\n/** Header */\n\n#qunit-header {\n\tpadding: 0.5em 0 0.5em 1em;\n\n\tcolor: #8699a4;\n\tbackground-color: #0d3349;\n\n\tfont-size: 1.5em;\n\tline-height: 1em;\n\tfont-weight: normal;\n\n\tborder-radius: 15px 15px 0 0;\n\t-moz-border-radius: 15px 15px 0 0;\n\t-webkit-border-top-right-radius: 15px;\n\t-webkit-border-top-left-radius: 15px;\n}\n\n#qunit-header a {\n\ttext-decoration: none;\n\tcolor: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n\tcolor: #fff;\n}\n\n#qunit-header label {\n\tdisplay: inline-block;\n}\n\n#qunit-banner {\n\theight: 5px;\n}\n\n#qunit-testrunner-toolbar {\n\tpadding: 0.5em 0 0.5em 2em;\n\tcolor: #5E740B;\n\tbackground-color: #eee;\n}\n\n#qunit-userAgent {\n\tpadding: 0.5em 0 0.5em 2.5em;\n\tbackground-color: #2b81af;\n\tcolor: #fff;\n\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n\tlist-style-position: inside;\n}\n\n#qunit-tests li {\n\tpadding: 0.4em 0.5em 0.4em 2.5em;\n\tborder-bottom: 1px solid #fff;\n\tlist-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n\tdisplay: none;\n}\n\n#qunit-tests li strong {\n\tcursor: pointer;\n}\n\n#qunit-tests li a {\n\tpadding: 0.5em;\n\tcolor: #c2ccd1;\n\ttext-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n\tcolor: #000;\n}\n\n#qunit-tests ol {\n\tmargin-top: 0.5em;\n\tpadding: 0.5em;\n\n\tbackground-color: #fff;\n\n\tborder-radius: 15px;\n\t-moz-border-radius: 15px;\n\t-webkit-border-radius: 15px;\n\n\tbox-shadow: inset 0px 2px 13px #999;\n\t-moz-box-shadow: inset 0px 2px 13px #999;\n\t-webkit-box-shadow: inset 0px 2px 13px #999;\n}\n\n#qunit-tests table {\n\tborder-collapse: collapse;\n\tmargin-top: .2em;\n}\n\n#qunit-tests th {\n\ttext-align: right;\n\tvertical-align: top;\n\tpadding: 0 .5em 0 0;\n}\n\n#qunit-tests td {\n\tvertical-align: top;\n}\n\n#qunit-tests pre {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\tword-wrap: break-word;\n}\n\n#qunit-tests del {\n\tbackground-color: #e0f2be;\n\tcolor: #374e0c;\n\ttext-decoration: none;\n}\n\n#qunit-tests ins {\n\tbackground-color: #ffcaca;\n\tcolor: #500;\n\ttext-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts                       { color: black; }\n#qunit-tests b.passed                       { color: #5E740B; }\n#qunit-tests b.failed                       { color: #710909; }\n\n#qunit-tests li li {\n\tmargin: 0.5em;\n\tpadding: 0.4em 0.5em 0.4em 0.5em;\n\tbackground-color: #fff;\n\tborder-bottom: none;\n\tlist-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n\tcolor: #5E740B;\n\tbackground-color: #fff;\n\tborder-left: 26px solid #C6E746;\n}\n\n#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n#qunit-tests .pass .test-name               { color: #366097; }\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected           { color: #999999; }\n\n#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n\tcolor: #710909;\n\tbackground-color: #fff;\n\tborder-left: 26px solid #EE5757;\n\twhite-space: pre;\n}\n\n#qunit-tests > li:last-child {\n\tborder-radius: 0 0 15px 15px;\n\t-moz-border-radius: 0 0 15px 15px;\n\t-webkit-border-bottom-right-radius: 15px;\n\t-webkit-border-bottom-left-radius: 15px;\n}\n\n#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name             { color: #000000; }\n\n#qunit-tests .fail .test-actual             { color: #EE5757; }\n#qunit-tests .fail .test-expected           { color: green;   }\n\n#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n\n\n/** Result */\n\n#qunit-testresult {\n\tpadding: 0.5em 0.5em 0.5em 2.5em;\n\n\tcolor: #2b81af;\n\tbackground-color: #D2E0E6;\n\n\tborder-bottom: 1px solid white;\n}\n#qunit-testresult .module-name {\n\tfont-weight: bold;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n\tposition: absolute;\n\ttop: -10000px;\n\tleft: -10000px;\n\twidth: 1000px;\n\theight: 1000px;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/test/qunit.js",
    "content": "/**\n * QUnit v1.6.0pre - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n(function(window) {\n\nvar defined = {\n\tsetTimeout: typeof window.setTimeout !== \"undefined\",\n\tsessionStorage: (function() {\n\t\tvar x = \"qunit-test-string\";\n\t\ttry {\n\t\t\tsessionStorage.setItem(x, x);\n\t\t\tsessionStorage.removeItem(x);\n\t\t\treturn true;\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t}())\n};\n\nvar\ttestId = 0,\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty;\n\nvar Test = function(name, testName, expected, async, callback) {\n\tthis.name = name;\n\tthis.testName = testName;\n\tthis.expected = expected;\n\tthis.async = async;\n\tthis.callback = callback;\n\tthis.assertions = [];\n};\nTest.prototype = {\n\tinit: function() {\n\t\tvar tests = id(\"qunit-tests\");\n\t\tif (tests) {\n\t\t\tvar b = document.createElement(\"strong\");\n\t\t\t\tb.innerHTML = \"Running \" + this.name;\n\t\t\tvar li = document.createElement(\"li\");\n\t\t\t\tli.appendChild( b );\n\t\t\t\tli.className = \"running\";\n\t\t\t\tli.id = this.id = \"test-output\" + testId++;\n\t\t\ttests.appendChild( li );\n\t\t}\n\t},\n\tsetup: function() {\n\t\tif (this.module != config.previousModule) {\n\t\t\tif ( config.previousModule ) {\n\t\t\t\trunLoggingCallbacks('moduleDone', QUnit, {\n\t\t\t\t\tname: config.previousModule,\n\t\t\t\t\tfailed: config.moduleStats.bad,\n\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\t\t\ttotal: config.moduleStats.all\n\t\t\t\t} );\n\t\t\t}\n\t\t\tconfig.previousModule = this.module;\n\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n\t\t\trunLoggingCallbacks( 'moduleStart', QUnit, {\n\t\t\t\tname: this.module\n\t\t\t} );\n\t\t} else if (config.autorun) {\n\t\t\trunLoggingCallbacks( 'moduleStart', QUnit, {\n\t\t\t\tname: this.module\n\t\t\t} );\n\t\t}\n\n\t\tconfig.current = this;\n\t\tthis.testEnvironment = extend({\n\t\t\tsetup: function() {},\n\t\t\tteardown: function() {}\n\t\t}, this.moduleTestEnvironment);\n\n\t\trunLoggingCallbacks( 'testStart', QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module\n\t\t});\n\n\t\t// allow utility functions to access the current test environment\n\t\t// TODO why??\n\t\tQUnit.current_testEnvironment = this.testEnvironment;\n\n\t\tif ( !config.pollution ) {\n\t\t\tsaveGlobal();\n\t\t}\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.setup.call(this.testEnvironment);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.testEnvironment.setup.call(this.testEnvironment);\n\t\t} catch(e) {\n\t\t\tQUnit.pushFailure( \"Setup failed on \" + this.testName + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t}\n\t},\n\trun: function() {\n\t\tconfig.current = this;\n\n\t\tvar running = id(\"qunit-testresult\");\n\n\t\tif ( running ) {\n\t\t\trunning.innerHTML = \"Running: <br/>\" + this.name;\n\t\t}\n\n\t\tif ( this.async ) {\n\t\t\tQUnit.stop();\n\t\t}\n\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.callback.call(this.testEnvironment);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.callback.call(this.testEnvironment);\n\t\t} catch(e) {\n\t\t\tQUnit.pushFailure( \"Died on test #\" + (this.assertions.length + 1) + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t\t// else next test will carry the responsibility\n\t\t\tsaveGlobal();\n\n\t\t\t// Restart the tests if they're blocking\n\t\t\tif ( config.blocking ) {\n\t\t\t\tQUnit.start();\n\t\t\t}\n\t\t}\n\t},\n\tteardown: function() {\n\t\tconfig.current = this;\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.teardown.call(this.testEnvironment);\n\t\t\treturn;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tthis.testEnvironment.teardown.call(this.testEnvironment);\n\t\t\t} catch(e) {\n\t\t\t\tQUnit.pushFailure( \"Teardown failed on \" + this.testName + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t\t}\n\t\t}\n\t\tcheckPollution();\n\t},\n\tfinish: function() {\n\t\tconfig.current = this;\n\t\tif ( this.expected != null && this.expected != this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected \" + this.expected + \" assertions, but \" + this.assertions.length + \" were run\" );\n\t\t} else if ( this.expected == null && !this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.\" );\n\t\t}\n\n\t\tvar good = 0, bad = 0,\n\t\t\tli, i,\n\t\t\ttests = id(\"qunit-tests\");\n\n\t\tconfig.stats.all += this.assertions.length;\n\t\tconfig.moduleStats.all += this.assertions.length;\n\n\t\tif ( tests ) {\n\t\t\tvar ol = document.createElement(\"ol\");\n\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tvar assertion = this.assertions[i];\n\n\t\t\t\tli = document.createElement(\"li\");\n\t\t\t\tli.className = assertion.result ? \"pass\" : \"fail\";\n\t\t\t\tli.innerHTML = assertion.message || (assertion.result ? \"okay\" : \"failed\");\n\t\t\t\tol.appendChild( li );\n\n\t\t\t\tif ( assertion.result ) {\n\t\t\t\t\tgood++;\n\t\t\t\t} else {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// store result when possible\n\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n\t\t\t\tif (bad) {\n\t\t\t\t\tsessionStorage.setItem(\"qunit-test-\" + this.module + \"-\" + this.testName, bad);\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem(\"qunit-test-\" + this.module + \"-\" + this.testName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bad === 0) {\n\t\t\t\tol.style.display = \"none\";\n\t\t\t}\n\n\t\t\tvar b = document.createElement(\"strong\");\n\t\t\tb.innerHTML = this.name + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + \"</b>, \" + this.assertions.length + \")</b>\";\n\n\t\t\tvar a = document.createElement(\"a\");\n\t\t\ta.innerHTML = \"Rerun\";\n\t\t\ta.href = QUnit.url({ filter: getText([b]).replace(/\\([^)]+\\)$/, \"\").replace(/(^\\s*|\\s*$)/g, \"\") });\n\n\t\t\taddEvent(b, \"click\", function() {\n\t\t\t\tvar next = b.nextSibling.nextSibling,\n\t\t\t\t\tdisplay = next.style.display;\n\t\t\t\tnext.style.display = display === \"none\" ? \"block\" : \"none\";\n\t\t\t});\n\n\t\t\taddEvent(b, \"dblclick\", function(e) {\n\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\t\t\tif ( target.nodeName.toLowerCase() == \"span\" || target.nodeName.toLowerCase() == \"b\" ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\t\t\twindow.location = QUnit.url({ filter: getText([target]).replace(/\\([^)]+\\)$/, \"\").replace(/(^\\s*|\\s*$)/g, \"\") });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tli = id(this.id);\n\t\t\tli.className = bad ? \"fail\" : \"pass\";\n\t\t\tli.removeChild( li.firstChild );\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.appendChild( ol );\n\n\t\t} else {\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tif ( !this.assertions[i].result ) {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tQUnit.reset();\n\n\t\trunLoggingCallbacks( 'testDone', QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module,\n\t\t\tfailed: bad,\n\t\t\tpassed: this.assertions.length - bad,\n\t\t\ttotal: this.assertions.length\n\t\t} );\n\t},\n\n\tqueue: function() {\n\t\tvar test = this;\n\t\tsynchronize(function() {\n\t\t\ttest.init();\n\t\t});\n\t\tfunction run() {\n\t\t\t// each of these can by async\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.setup();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.run();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.teardown();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.finish();\n\t\t\t});\n\t\t}\n\t\t// defer when previous test run passed, if storage is available\n\t\tvar bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem(\"qunit-test-\" + this.module + \"-\" + this.testName);\n\t\tif (bad) {\n\t\t\trun();\n\t\t} else {\n\t\t\tsynchronize(run, true);\n\t\t}\n\t}\n\n};\n\nvar QUnit = {\n\n\t// call on start of module test to prepend name to all tests\n\tmodule: function(name, testEnvironment) {\n\t\tconfig.currentModule = name;\n\t\tconfig.currentModuleTestEnviroment = testEnvironment;\n\t},\n\n\tasyncTest: function(testName, expected, callback) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tQUnit.test(testName, expected, callback, true);\n\t},\n\n\ttest: function(testName, expected, callback, async) {\n\t\tvar name = '<span class=\"test-name\">' + escapeInnerText(testName) + '</span>';\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tif ( config.currentModule ) {\n\t\t\tname = '<span class=\"module-name\">' + config.currentModule + \"</span>: \" + name;\n\t\t}\n\n\t\tif ( !validTest(config.currentModule + \": \" + testName) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar test = new Test(name, testName, expected, async, callback);\n\t\ttest.module = config.currentModule;\n\t\ttest.moduleTestEnvironment = config.currentModuleTestEnviroment;\n\t\ttest.queue();\n\t},\n\n\t// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.\n\texpect: function(asserts) {\n\t\tconfig.current.expected = asserts;\n\t},\n\n\t// Asserts true.\n\t// @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n\tok: function(result, msg) {\n\t\tif (!config.current) {\n\t\t\tthrow new Error(\"ok() assertion outside test context, was \" + sourceFromStacktrace(2));\n\t\t}\n\t\tresult = !!result;\n\t\tvar details = {\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t};\n\t\tmsg = escapeInnerText(msg || (result ? \"okay\" : \"failed\"));\n\t\tif ( !result ) {\n\t\t\tvar source = sourceFromStacktrace(2);\n\t\t\tif (source) {\n\t\t\t\tdetails.source = source;\n\t\t\t\tmsg += '<table><tr class=\"test-source\"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>';\n\t\t\t}\n\t\t}\n\t\trunLoggingCallbacks( 'log', QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t});\n\t},\n\n\t// Checks that the first two arguments are equal, with an optional message. Prints out both actual and expected values.\n\t// @example equal( format(\"Received {0} bytes.\", 2), \"Received 2 bytes.\" );\n\tequal: function(actual, expected, message) {\n\t\tQUnit.push(expected == actual, actual, expected, message);\n\t},\n\n\tnotEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected != actual, actual, expected, message);\n\t},\n\n\tdeepEqual: function(actual, expected, message) {\n\t\tQUnit.push(QUnit.equiv(actual, expected), actual, expected, message);\n\t},\n\n\tnotDeepEqual: function(actual, expected, message) {\n\t\tQUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);\n\t},\n\n\tstrictEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected === actual, actual, expected, message);\n\t},\n\n\tnotStrictEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected !== actual, actual, expected, message);\n\t},\n\n\traises: function(block, expected, message) {\n\t\tvar actual, ok = false;\n\n\t\tif (typeof expected === 'string') {\n\t\t\tmessage = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\ttry {\n\t\t\tblock.call(config.current.testEnvironment);\n\t\t} catch (e) {\n\t\t\tactual = e;\n\t\t}\n\n\t\tif (actual) {\n\t\t\t// we don't want to validate thrown error\n\t\t\tif (!expected) {\n\t\t\t\tok = true;\n\t\t\t// expected is a regexp\n\t\t\t} else if (QUnit.objectType(expected) === \"regexp\") {\n\t\t\t\tok = expected.test(actual);\n\t\t\t// expected is a constructor\n\t\t\t} else if (actual instanceof expected) {\n\t\t\t\tok = true;\n\t\t\t// expected is a validation function which returns true is validation passed\n\t\t\t} else if (expected.call({}, actual) === true) {\n\t\t\t\tok = true;\n\t\t\t}\n\t\t}\n\n\t\tQUnit.ok(ok, message);\n\t},\n\n\tstart: function(count) {\n\t\tconfig.semaphore -= count || 1;\n\t\tif (config.semaphore > 0) {\n\t\t\t// don't start until equal number of stop-calls\n\t\t\treturn;\n\t\t}\n\t\tif (config.semaphore < 0) {\n\t\t\t// ignore if start is called more often then stop\n\t\t\tconfig.semaphore = 0;\n\t\t}\n\t\t// A slight delay, to avoid any current callbacks\n\t\tif ( defined.setTimeout ) {\n\t\t\twindow.setTimeout(function() {\n\t\t\t\tif (config.semaphore > 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( config.timeout ) {\n\t\t\t\t\tclearTimeout(config.timeout);\n\t\t\t\t}\n\n\t\t\t\tconfig.blocking = false;\n\t\t\t\tprocess(true);\n\t\t\t}, 13);\n\t\t} else {\n\t\t\tconfig.blocking = false;\n\t\t\tprocess(true);\n\t\t}\n\t},\n\n\tstop: function(count) {\n\t\tconfig.semaphore += count || 1;\n\t\tconfig.blocking = true;\n\n\t\tif ( config.testTimeout && defined.setTimeout ) {\n\t\t\tclearTimeout(config.timeout);\n\t\t\tconfig.timeout = window.setTimeout(function() {\n\t\t\t\tQUnit.ok( false, \"Test timed out\" );\n\t\t\t\tconfig.semaphore = 1;\n\t\t\t\tQUnit.start();\n\t\t\t}, config.testTimeout);\n\t\t}\n\t}\n};\n\n//We want access to the constructor's prototype\n(function() {\n\tfunction F(){}\n\tF.prototype = QUnit;\n\tQUnit = new F();\n\t//Make F QUnit's constructor so that we can add to the prototype later\n\tQUnit.constructor = F;\n}());\n\n// deprecated; still export them to window to provide clear error messages\n// next step: remove entirely\nQUnit.equals = function() {\n\tQUnit.push(false, false, false, \"QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead\");\n};\nQUnit.same = function() {\n\tQUnit.push(false, false, false, \"QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead\");\n};\n\n// Maintain internal state\nvar config = {\n\t// The queue of tests to run\n\tqueue: [],\n\n\t// block until document ready\n\tblocking: true,\n\n\t// when enabled, show only failing tests\n\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n\thidepassed: false,\n\n\t// by default, run previously failed tests first\n\t// very useful in combination with \"Hide passed tests\" checked\n\treorder: true,\n\n\t// by default, modify document.title when suite is done\n\taltertitle: true,\n\n\turlConfig: ['noglobals', 'notrycatch'],\n\n\t//logging callback queues\n\tbegin: [],\n\tdone: [],\n\tlog: [],\n\ttestStart: [],\n\ttestDone: [],\n\tmoduleStart: [],\n\tmoduleDone: []\n};\n\n// Load paramaters\n(function() {\n\tvar location = window.location || { search: \"\", protocol: \"file:\" },\n\t\tparams = location.search.slice( 1 ).split( \"&\" ),\n\t\tlength = params.length,\n\t\turlParams = {},\n\t\tcurrent;\n\n\tif ( params[ 0 ] ) {\n\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\tcurrent = params[ i ].split( \"=\" );\n\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n\t\t}\n\t}\n\n\tQUnit.urlParams = urlParams;\n\tconfig.filter = urlParams.filter;\n\n\t// Figure out if we're running the tests from a server or not\n\tQUnit.isLocal = location.protocol === 'file:';\n}());\n\n// Expose the API as global variables, unless an 'exports'\n// object exists, in that case we assume we're in CommonJS - export everything at the end\nif ( typeof exports === \"undefined\" || typeof require === \"undefined\" ) {\n\textend(window, QUnit);\n\twindow.QUnit = QUnit;\n}\n\n// define these after exposing globals to keep them in these QUnit namespace only\nextend(QUnit, {\n\tconfig: config,\n\n\t// Initialize the configuration options\n\tinit: function() {\n\t\textend(config, {\n\t\t\tstats: { all: 0, bad: 0 },\n\t\t\tmoduleStats: { all: 0, bad: 0 },\n\t\t\tstarted: +new Date(),\n\t\t\tupdateRate: 1000,\n\t\t\tblocking: false,\n\t\t\tautostart: true,\n\t\t\tautorun: false,\n\t\t\tfilter: \"\",\n\t\t\tqueue: [],\n\t\t\tsemaphore: 0\n\t\t});\n\n\t\tvar qunit = id( \"qunit\" );\n\t\tif ( qunit ) {\n\t\t\tqunit.innerHTML =\n\t\t\t\t'<h1 id=\"qunit-header\">' + escapeInnerText( document.title ) + '</h1>' +\n\t\t\t\t'<h2 id=\"qunit-banner\"></h2>' +\n\t\t\t\t'<div id=\"qunit-testrunner-toolbar\"></div>' +\n\t\t\t\t'<h2 id=\"qunit-userAgent\"></h2>' +\n\t\t\t\t'<ol id=\"qunit-tests\"></ol>';\n\t\t}\n\n\t\tvar tests = id( \"qunit-tests\" ),\n\t\t\tbanner = id( \"qunit-banner\" ),\n\t\t\tresult = id( \"qunit-testresult\" );\n\n\t\tif ( tests ) {\n\t\t\ttests.innerHTML = \"\";\n\t\t}\n\n\t\tif ( banner ) {\n\t\t\tbanner.className = \"\";\n\t\t}\n\n\t\tif ( result ) {\n\t\t\tresult.parentNode.removeChild( result );\n\t\t}\n\n\t\tif ( tests ) {\n\t\t\tresult = document.createElement( \"p\" );\n\t\t\tresult.id = \"qunit-testresult\";\n\t\t\tresult.className = \"result\";\n\t\t\ttests.parentNode.insertBefore( result, tests );\n\t\t\tresult.innerHTML = 'Running...<br/>&nbsp;';\n\t\t}\n\t},\n\n\t// Resets the test setup. Useful for tests that modify the DOM.\n\t// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.\n\treset: function() {\n\t\tif ( window.jQuery ) {\n\t\t\tjQuery( \"#qunit-fixture\" ).html( config.fixture );\n\t\t} else {\n\t\t\tvar main = id( 'qunit-fixture' );\n\t\t\tif ( main ) {\n\t\t\t\tmain.innerHTML = config.fixture;\n\t\t\t}\n\t\t}\n\t},\n\n\t// Trigger an event on an element.\n\t// @example triggerEvent( document.body, \"click\" );\n\ttriggerEvent: function( elem, type, event ) {\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent(\"MouseEvents\");\n\t\t\tevent.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,\n\t\t\t\t0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\t\t\telem.dispatchEvent( event );\n\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent(\"on\"+type);\n\t\t}\n\t},\n\n\t// Safe object type checking\n\tis: function( type, obj ) {\n\t\treturn QUnit.objectType( obj ) == type;\n\t},\n\n\tobjectType: function( obj ) {\n\t\tif (typeof obj === \"undefined\") {\n\t\t\t\treturn \"undefined\";\n\n\t\t// consider: typeof null === object\n\t\t}\n\t\tif (obj === null) {\n\t\t\t\treturn \"null\";\n\t\t}\n\n\t\tvar type = toString.call( obj ).match(/^\\[object\\s(.*)\\]$/)[1] || '';\n\n\t\tswitch (type) {\n\t\t\tcase 'Number':\n\t\t\t\tif (isNaN(obj)) {\n\t\t\t\t\treturn \"nan\";\n\t\t\t\t}\n\t\t\t\treturn \"number\";\n\t\t\tcase 'String':\n\t\t\tcase 'Boolean':\n\t\t\tcase 'Array':\n\t\t\tcase 'Date':\n\t\t\tcase 'RegExp':\n\t\t\tcase 'Function':\n\t\t\t\t\treturn type.toLowerCase();\n\t\t}\n\t\tif (typeof obj === \"object\") {\n\t\t\t\treturn \"object\";\n\t\t}\n\t\treturn undefined;\n\t},\n\n\tpush: function(result, actual, expected, message) {\n\t\tif (!config.current) {\n\t\t\tthrow new Error(\"assertion outside test context, was \" + sourceFromStacktrace());\n\t\t}\n\t\tvar details = {\n\t\t\tresult: result,\n\t\t\tmessage: message,\n\t\t\tactual: actual,\n\t\t\texpected: expected\n\t\t};\n\n\t\tmessage = escapeInnerText(message) || (result ? \"okay\" : \"failed\");\n\t\tmessage = '<span class=\"test-message\">' + message + \"</span>\";\n\t\tvar output = message;\n\t\tif (!result) {\n\t\t\texpected = escapeInnerText(QUnit.jsDump.parse(expected));\n\t\t\tactual = escapeInnerText(QUnit.jsDump.parse(actual));\n\t\t\toutput += '<table><tr class=\"test-expected\"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';\n\t\t\tif (actual != expected) {\n\t\t\t\toutput += '<tr class=\"test-actual\"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';\n\t\t\t\toutput += '<tr class=\"test-diff\"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';\n\t\t\t}\n\t\t\tvar source = sourceFromStacktrace();\n\t\t\tif (source) {\n\t\t\t\tdetails.source = source;\n\t\t\t\toutput += '<tr class=\"test-source\"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr>';\n\t\t\t}\n\t\t\toutput += \"</table>\";\n\t\t}\n\n\t\trunLoggingCallbacks( 'log', QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: !!result,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\tpushFailure: function(message, source) {\n\t\tvar details = {\n\t\t\tresult: false,\n\t\t\tmessage: message\n\t\t};\n\t\tvar output = escapeInnerText(message);\n\t\tif (source) {\n\t\t\tdetails.source = source;\n\t\t\toutput += '<table><tr class=\"test-source\"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>';\n\t\t}\n\t\trunLoggingCallbacks( 'log', QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: false,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\turl: function( params ) {\n\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n\t\tvar querystring = \"?\",\n\t\t\tkey;\n\t\tfor ( key in params ) {\n\t\t\tif ( !hasOwn.call( params, key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tquerystring += encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( params[ key ] ) + \"&\";\n\t\t}\n\t\treturn window.location.pathname + querystring.slice( 0, -1 );\n\t},\n\n\textend: extend,\n\tid: id,\n\taddEvent: addEvent\n});\n\n//QUnit.constructor is set to the empty F() above so that we can add to it's prototype later\n//Doing this allows us to tell if the following methods have been overwritten on the actual\n//QUnit object, which is a deprecated way of using the callbacks.\nextend(QUnit.constructor.prototype, {\n\t// Logging callbacks; all receive a single argument with the listed properties\n\t// run test/logs.html for any related changes\n\tbegin: registerLoggingCallback('begin'),\n\t// done: { failed, passed, total, runtime }\n\tdone: registerLoggingCallback('done'),\n\t// log: { result, actual, expected, message }\n\tlog: registerLoggingCallback('log'),\n\t// testStart: { name }\n\ttestStart: registerLoggingCallback('testStart'),\n\t// testDone: { name, failed, passed, total }\n\ttestDone: registerLoggingCallback('testDone'),\n\t// moduleStart: { name }\n\tmoduleStart: registerLoggingCallback('moduleStart'),\n\t// moduleDone: { name, failed, passed, total }\n\tmoduleDone: registerLoggingCallback('moduleDone')\n});\n\nif ( typeof document === \"undefined\" || document.readyState === \"complete\" ) {\n\tconfig.autorun = true;\n}\n\nQUnit.load = function() {\n\trunLoggingCallbacks( 'begin', QUnit, {} );\n\n\t// Initialize the config, saving the execution queue\n\tvar oldconfig = extend({}, config);\n\tQUnit.init();\n\textend(config, oldconfig);\n\n\tconfig.blocking = false;\n\n\tvar urlConfigHtml = '', len = config.urlConfig.length;\n\tfor ( var i = 0, val; i < len; i++ ) {\n\t\tval = config.urlConfig[i];\n\t\tconfig[val] = QUnit.urlParams[val];\n\t\turlConfigHtml += '<label><input name=\"' + val + '\" type=\"checkbox\"' + ( config[val] ? ' checked=\"checked\"' : '' ) + '>' + val + '</label>';\n\t}\n\n\tvar userAgent = id(\"qunit-userAgent\");\n\tif ( userAgent ) {\n\t\tuserAgent.innerHTML = navigator.userAgent;\n\t}\n\tvar banner = id(\"qunit-header\");\n\tif ( banner ) {\n\t\tbanner.innerHTML = '<a href=\"' + QUnit.url({ filter: undefined }) + '\"> ' + banner.innerHTML + '</a> ' + urlConfigHtml;\n\t\taddEvent( banner, \"change\", function( event ) {\n\t\t\tvar params = {};\n\t\t\tparams[ event.target.name ] = event.target.checked ? true : undefined;\n\t\t\twindow.location = QUnit.url( params );\n\t\t});\n\t}\n\n\tvar toolbar = id(\"qunit-testrunner-toolbar\");\n\tif ( toolbar ) {\n\t\tvar filter = document.createElement(\"input\");\n\t\tfilter.type = \"checkbox\";\n\t\tfilter.id = \"qunit-filter-pass\";\n\t\taddEvent( filter, \"click\", function() {\n\t\t\tvar ol = document.getElementById(\"qunit-tests\");\n\t\t\tif ( filter.checked ) {\n\t\t\t\tol.className = ol.className + \" hidepass\";\n\t\t\t} else {\n\t\t\t\tvar tmp = \" \" + ol.className.replace( /[\\n\\t\\r]/g, \" \" ) + \" \";\n\t\t\t\tol.className = tmp.replace(/ hidepass /, \" \");\n\t\t\t}\n\t\t\tif ( defined.sessionStorage ) {\n\t\t\t\tif (filter.checked) {\n\t\t\t\t\tsessionStorage.setItem(\"qunit-filter-passed-tests\", \"true\");\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem(\"qunit-filter-passed-tests\");\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem(\"qunit-filter-passed-tests\") ) {\n\t\t\tfilter.checked = true;\n\t\t\tvar ol = document.getElementById(\"qunit-tests\");\n\t\t\tol.className = ol.className + \" hidepass\";\n\t\t}\n\t\ttoolbar.appendChild( filter );\n\n\t\tvar label = document.createElement(\"label\");\n\t\tlabel.setAttribute(\"for\", \"qunit-filter-pass\");\n\t\tlabel.innerHTML = \"Hide passed tests\";\n\t\ttoolbar.appendChild( label );\n\t}\n\n\tvar main = id('qunit-fixture');\n\tif ( main ) {\n\t\tconfig.fixture = main.innerHTML;\n\t}\n\n\tif (config.autostart) {\n\t\tQUnit.start();\n\t}\n};\n\naddEvent(window, \"load\", QUnit.load);\n\n// addEvent(window, \"error\") gives us a useless event object\nwindow.onerror = function( message, file, line ) {\n\tif ( QUnit.config.current ) {\n\t\tQUnit.pushFailure( message, file + \":\" + line );\n\t} else {\n\t\tQUnit.test( \"global failure\", function() {\n\t\t\tQUnit.pushFailure( message, file + \":\" + line );\n\t\t});\n\t}\n};\n\nfunction done() {\n\tconfig.autorun = true;\n\n\t// Log the last module results\n\tif ( config.currentModule ) {\n\t\trunLoggingCallbacks( 'moduleDone', QUnit, {\n\t\t\tname: config.currentModule,\n\t\t\tfailed: config.moduleStats.bad,\n\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\ttotal: config.moduleStats.all\n\t\t} );\n\t}\n\n\tvar banner = id(\"qunit-banner\"),\n\t\ttests = id(\"qunit-tests\"),\n\t\truntime = +new Date() - config.started,\n\t\tpassed = config.stats.all - config.stats.bad,\n\t\thtml = [\n\t\t\t'Tests completed in ',\n\t\t\truntime,\n\t\t\t' milliseconds.<br/>',\n\t\t\t'<span class=\"passed\">',\n\t\t\tpassed,\n\t\t\t'</span> tests of <span class=\"total\">',\n\t\t\tconfig.stats.all,\n\t\t\t'</span> passed, <span class=\"failed\">',\n\t\t\tconfig.stats.bad,\n\t\t\t'</span> failed.'\n\t\t].join('');\n\n\tif ( banner ) {\n\t\tbanner.className = (config.stats.bad ? \"qunit-fail\" : \"qunit-pass\");\n\t}\n\n\tif ( tests ) {\n\t\tid( \"qunit-testresult\" ).innerHTML = html;\n\t}\n\n\tif ( config.altertitle && typeof document !== \"undefined\" && document.title ) {\n\t\t// show ✖ for good, ✔ for bad suite result in title\n\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n\t\tdocument.title = [\n\t\t\t(config.stats.bad ? \"\\u2716\" : \"\\u2714\"),\n\t\t\tdocument.title.replace(/^[\\u2714\\u2716] /i, \"\")\n\t\t].join(\" \");\n\t}\n\n\t// clear own sessionStorage items if all tests passed\n\tif ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {\n\t\tvar key;\n\t\tfor ( var i = 0; i < sessionStorage.length; i++ ) {\n\t\t\tkey = sessionStorage.key( i++ );\n\t\t\tif ( key.indexOf(\"qunit-test-\") === 0 ) {\n\t\t\t\tsessionStorage.removeItem( key );\n\t\t\t}\n\t\t}\n\t}\n\n\trunLoggingCallbacks( 'done', QUnit, {\n\t\tfailed: config.stats.bad,\n\t\tpassed: passed,\n\t\ttotal: config.stats.all,\n\t\truntime: runtime\n\t} );\n}\n\nfunction validTest( name ) {\n\tvar filter = config.filter,\n\t\trun = false;\n\n\tif ( !filter ) {\n\t\treturn true;\n\t}\n\n\tvar not = filter.charAt( 0 ) === \"!\";\n\tif ( not ) {\n\t\tfilter = filter.slice( 1 );\n\t}\n\n\tif ( name.indexOf( filter ) !== -1 ) {\n\t\treturn !not;\n\t}\n\n\tif ( not ) {\n\t\trun = true;\n\t}\n\n\treturn run;\n}\n\n// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n// Later Safari and IE10 are supposed to support error.stack as well\n// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\nfunction extractStacktrace( e, offset ) {\n\toffset = offset || 3;\n\tif (e.stacktrace) {\n\t\t// Opera\n\t\treturn e.stacktrace.split(\"\\n\")[offset + 3];\n\t} else if (e.stack) {\n\t\t// Firefox, Chrome\n\t\tvar stack = e.stack.split(\"\\n\");\n\t\tif (/^error$/i.test(stack[0])) {\n\t\t\tstack.shift();\n\t\t}\n\t\treturn stack[offset];\n\t} else if (e.sourceURL) {\n\t\t// Safari, PhantomJS\n\t\t// hopefully one day Safari provides actual stacktraces\n\t\t// exclude useless self-reference for generated Error objects\n\t\tif ( /qunit.js$/.test( e.sourceURL ) ) {\n\t\t\treturn;\n\t\t}\n\t\t// for actual exceptions, this is useful\n\t\treturn e.sourceURL + \":\" + e.line;\n\t}\n}\nfunction sourceFromStacktrace(offset) {\n\ttry {\n\t\tthrow new Error();\n\t} catch ( e ) {\n\t\treturn extractStacktrace( e, offset );\n\t}\n}\n\nfunction escapeInnerText(s) {\n\tif (!s) {\n\t\treturn \"\";\n\t}\n\ts = s + \"\";\n\treturn s.replace(/[\\&<>]/g, function(s) {\n\t\tswitch(s) {\n\t\t\tcase \"&\": return \"&amp;\";\n\t\t\tcase \"<\": return \"&lt;\";\n\t\t\tcase \">\": return \"&gt;\";\n\t\t\tdefault: return s;\n\t\t}\n\t});\n}\n\nfunction synchronize( callback, last ) {\n\tconfig.queue.push( callback );\n\n\tif ( config.autorun && !config.blocking ) {\n\t\tprocess(last);\n\t}\n}\n\nfunction process( last ) {\n\tfunction next() {\n\t\tprocess( last );\n\t}\n\tvar start = new Date().getTime();\n\tconfig.depth = config.depth ? config.depth + 1 : 1;\n\n\twhile ( config.queue.length && !config.blocking ) {\n\t\tif ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {\n\t\t\tconfig.queue.shift()();\n\t\t} else {\n\t\t\twindow.setTimeout( next, 13 );\n\t\t\tbreak;\n\t\t}\n\t}\n\tconfig.depth--;\n\tif ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {\n\t\tdone();\n\t}\n}\n\nfunction saveGlobal() {\n\tconfig.pollution = [];\n\n\tif ( config.noglobals ) {\n\t\tfor ( var key in window ) {\n\t\t\tif ( !hasOwn.call( window, key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconfig.pollution.push( key );\n\t\t}\n\t}\n}\n\nfunction checkPollution( name ) {\n\tvar old = config.pollution;\n\tsaveGlobal();\n\n\tvar newGlobals = diff( config.pollution, old );\n\tif ( newGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Introduced global variable(s): \" + newGlobals.join(\", \") );\n\t}\n\n\tvar deletedGlobals = diff( old, config.pollution );\n\tif ( deletedGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Deleted global variable(s): \" + deletedGlobals.join(\", \") );\n\t}\n}\n\n// returns a new Array with the elements that are in a but not in b\nfunction diff( a, b ) {\n\tvar result = a.slice();\n\tfor ( var i = 0; i < result.length; i++ ) {\n\t\tfor ( var j = 0; j < b.length; j++ ) {\n\t\t\tif ( result[i] === b[j] ) {\n\t\t\t\tresult.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction extend(a, b) {\n\tfor ( var prop in b ) {\n\t\tif ( b[prop] === undefined ) {\n\t\t\tdelete a[prop];\n\n\t\t// Avoid \"Member not found\" error in IE8 caused by setting window.constructor\n\t\t} else if ( prop !== \"constructor\" || a !== window ) {\n\t\t\ta[prop] = b[prop];\n\t\t}\n\t}\n\n\treturn a;\n}\n\nfunction addEvent(elem, type, fn) {\n\tif ( elem.addEventListener ) {\n\t\telem.addEventListener( type, fn, false );\n\t} else if ( elem.attachEvent ) {\n\t\telem.attachEvent( \"on\" + type, fn );\n\t} else {\n\t\tfn();\n\t}\n}\n\nfunction id(name) {\n\treturn !!(typeof document !== \"undefined\" && document && document.getElementById) &&\n\t\tdocument.getElementById( name );\n}\n\nfunction registerLoggingCallback(key){\n\treturn function(callback){\n\t\tconfig[key].push( callback );\n\t};\n}\n\n// Supports deprecated method of completely overwriting logging callbacks\nfunction runLoggingCallbacks(key, scope, args) {\n\t//debugger;\n\tvar callbacks;\n\tif ( QUnit.hasOwnProperty(key) ) {\n\t\tQUnit[key].call(scope, args);\n\t} else {\n\t\tcallbacks = config[key];\n\t\tfor( var i = 0; i < callbacks.length; i++ ) {\n\t\t\tcallbacks[i].call( scope, args );\n\t\t}\n\t}\n}\n\n// Test for equality any JavaScript type.\n// Author: Philippe Rathé <prathe@gmail.com>\nQUnit.equiv = (function() {\n\n\tvar innerEquiv; // the real equiv function\n\tvar callers = []; // stack to decide between skip/abort functions\n\tvar parents = []; // stack to avoiding loops from circular referencing\n\n\t// Call the o related callback with the given arguments.\n\tfunction bindCallbacks(o, callbacks, args) {\n\t\tvar prop = QUnit.objectType(o);\n\t\tif (prop) {\n\t\t\tif (QUnit.objectType(callbacks[prop]) === \"function\") {\n\t\t\t\treturn callbacks[prop].apply(callbacks, args);\n\t\t\t} else {\n\t\t\t\treturn callbacks[prop]; // or undefined\n\t\t\t}\n\t\t}\n\t}\n\n\tvar getProto = Object.getPrototypeOf || function (obj) {\n\t\treturn obj.__proto__;\n\t};\n\n\tvar callbacks = (function () {\n\n\t\t// for string, boolean, number and null\n\t\tfunction useStrictEquality(b, a) {\n\t\t\tif (b instanceof a.constructor || a instanceof b.constructor) {\n\t\t\t\t// to catch short annotaion VS 'new' annotation of a\n\t\t\t\t// declaration\n\t\t\t\t// e.g. var i = 1;\n\t\t\t\t// var j = new Number(1);\n\t\t\t\treturn a == b;\n\t\t\t} else {\n\t\t\t\treturn a === b;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t\"string\" : useStrictEquality,\n\t\t\t\"boolean\" : useStrictEquality,\n\t\t\t\"number\" : useStrictEquality,\n\t\t\t\"null\" : useStrictEquality,\n\t\t\t\"undefined\" : useStrictEquality,\n\n\t\t\t\"nan\" : function(b) {\n\t\t\t\treturn isNaN(b);\n\t\t\t},\n\n\t\t\t\"date\" : function(b, a) {\n\t\t\t\treturn QUnit.objectType(b) === \"date\" && a.valueOf() === b.valueOf();\n\t\t\t},\n\n\t\t\t\"regexp\" : function(b, a) {\n\t\t\t\treturn QUnit.objectType(b) === \"regexp\" &&\n\t\t\t\t\t// the regex itself\n\t\t\t\t\ta.source === b.source &&\n\t\t\t\t\t// and its modifers\n\t\t\t\t\ta.global === b.global &&\n\t\t\t\t\t// (gmi) ...\n\t\t\t\t\ta.ignoreCase === b.ignoreCase &&\n\t\t\t\t\ta.multiline === b.multiline;\n\t\t\t},\n\n\t\t\t// - skip when the property is a method of an instance (OOP)\n\t\t\t// - abort otherwise,\n\t\t\t// initial === would have catch identical references anyway\n\t\t\t\"function\" : function() {\n\t\t\t\tvar caller = callers[callers.length - 1];\n\t\t\t\treturn caller !== Object && typeof caller !== \"undefined\";\n\t\t\t},\n\n\t\t\t\"array\" : function(b, a) {\n\t\t\t\tvar i, j, loop;\n\t\t\t\tvar len;\n\n\t\t\t\t// b could be an object literal here\n\t\t\t\tif (QUnit.objectType(b) !== \"array\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tlen = a.length;\n\t\t\t\tif (len !== b.length) { // safe and faster\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// track reference to avoid circular references\n\t\t\t\tparents.push(a);\n\t\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\t\tloop = false;\n\t\t\t\t\tfor (j = 0; j < parents.length; j++) {\n\t\t\t\t\t\tif (parents[j] === a[i]) {\n\t\t\t\t\t\t\tloop = true;// dont rewalk array\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!loop && !innerEquiv(a[i], b[i])) {\n\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tparents.pop();\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t\"object\" : function(b, a) {\n\t\t\t\tvar i, j, loop;\n\t\t\t\tvar eq = true; // unless we can proove it\n\t\t\t\tvar aProperties = [], bProperties = []; // collection of\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// strings\n\n\t\t\t\t// comparing constructors is more strict than using\n\t\t\t\t// instanceof\n\t\t\t\tif (a.constructor !== b.constructor) {\n\t\t\t\t\t// Allow objects with no prototype to be equivalent to\n\t\t\t\t\t// objects with Object as their constructor.\n\t\t\t\t\tif (!((getProto(a) === null && getProto(b) === Object.prototype) ||\n\t\t\t\t\t\t(getProto(b) === null && getProto(a) === Object.prototype)))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// stack constructor before traversing properties\n\t\t\t\tcallers.push(a.constructor);\n\t\t\t\t// track reference to avoid circular references\n\t\t\t\tparents.push(a);\n\n\t\t\t\tfor (i in a) { // be strict: don't ensures hasOwnProperty\n\t\t\t\t\t\t\t\t// and go deep\n\t\t\t\t\tloop = false;\n\t\t\t\t\tfor (j = 0; j < parents.length; j++) {\n\t\t\t\t\t\tif (parents[j] === a[i]) {\n\t\t\t\t\t\t\t// don't go down the same path twice\n\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\taProperties.push(i); // collect a's properties\n\n\t\t\t\t\tif (!loop && !innerEquiv(a[i], b[i])) {\n\t\t\t\t\t\teq = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallers.pop(); // unstack, we are done\n\t\t\t\tparents.pop();\n\n\t\t\t\tfor (i in b) {\n\t\t\t\t\tbProperties.push(i); // collect b's properties\n\t\t\t\t}\n\n\t\t\t\t// Ensures identical properties name\n\t\t\t\treturn eq && innerEquiv(aProperties.sort(), bProperties.sort());\n\t\t\t}\n\t\t};\n\t}());\n\n\tinnerEquiv = function() { // can take multiple arguments\n\t\tvar args = Array.prototype.slice.apply(arguments);\n\t\tif (args.length < 2) {\n\t\t\treturn true; // end transition\n\t\t}\n\n\t\treturn (function(a, b) {\n\t\t\tif (a === b) {\n\t\t\t\treturn true; // catch the most you can\n\t\t\t} else if (a === null || b === null || typeof a === \"undefined\" ||\n\t\t\t\t\ttypeof b === \"undefined\" ||\n\t\t\t\t\tQUnit.objectType(a) !== QUnit.objectType(b)) {\n\t\t\t\treturn false; // don't lose time with error prone cases\n\t\t\t} else {\n\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n\t\t\t}\n\n\t\t\t// apply transition with (1..n) arguments\n\t\t}(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length - 1)));\n\t};\n\n\treturn innerEquiv;\n\n}());\n\n/**\n * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n * http://flesler.blogspot.com Licensed under BSD\n * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n *\n * @projectDescription Advanced and extensible data dumping for Javascript.\n * @version 1.0.0\n * @author Ariel Flesler\n * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n */\nQUnit.jsDump = (function() {\n\tfunction quote( str ) {\n\t\treturn '\"' + str.toString().replace(/\"/g, '\\\\\"') + '\"';\n\t}\n\tfunction literal( o ) {\n\t\treturn o + '';\n\t}\n\tfunction join( pre, arr, post ) {\n\t\tvar s = jsDump.separator(),\n\t\t\tbase = jsDump.indent(),\n\t\t\tinner = jsDump.indent(1);\n\t\tif ( arr.join ) {\n\t\t\tarr = arr.join( ',' + s + inner );\n\t\t}\n\t\tif ( !arr ) {\n\t\t\treturn pre + post;\n\t\t}\n\t\treturn [ pre, inner + arr, base + post ].join(s);\n\t}\n\tfunction array( arr, stack ) {\n\t\tvar i = arr.length, ret = new Array(i);\n\t\tthis.up();\n\t\twhile ( i-- ) {\n\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n\t\t}\n\t\tthis.down();\n\t\treturn join( '[', ret, ']' );\n\t}\n\n\tvar reName = /^function (\\w+)/;\n\n\tvar jsDump = {\n\t\tparse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance\n\t\t\tstack = stack || [ ];\n\t\t\tvar parser = this.parsers[ type || this.typeOf(obj) ];\n\t\t\ttype = typeof parser;\n\t\t\tvar inStack = inArray(obj, stack);\n\t\t\tif (inStack != -1) {\n\t\t\t\treturn 'recursion('+(inStack - stack.length)+')';\n\t\t\t}\n\t\t\t//else\n\t\t\tif (type == 'function')  {\n\t\t\t\t\tstack.push(obj);\n\t\t\t\t\tvar res = parser.call( this, obj, stack );\n\t\t\t\t\tstack.pop();\n\t\t\t\t\treturn res;\n\t\t\t}\n\t\t\t// else\n\t\t\treturn (type == 'string') ? parser : this.parsers.error;\n\t\t},\n\t\ttypeOf: function( obj ) {\n\t\t\tvar type;\n\t\t\tif ( obj === null ) {\n\t\t\t\ttype = \"null\";\n\t\t\t} else if (typeof obj === \"undefined\") {\n\t\t\t\ttype = \"undefined\";\n\t\t\t} else if (QUnit.is(\"RegExp\", obj)) {\n\t\t\t\ttype = \"regexp\";\n\t\t\t} else if (QUnit.is(\"Date\", obj)) {\n\t\t\t\ttype = \"date\";\n\t\t\t} else if (QUnit.is(\"Function\", obj)) {\n\t\t\t\ttype = \"function\";\n\t\t\t} else if (typeof obj.setInterval !== undefined && typeof obj.document !== \"undefined\" && typeof obj.nodeType === \"undefined\") {\n\t\t\t\ttype = \"window\";\n\t\t\t} else if (obj.nodeType === 9) {\n\t\t\t\ttype = \"document\";\n\t\t\t} else if (obj.nodeType) {\n\t\t\t\ttype = \"node\";\n\t\t\t} else if (\n\t\t\t\t// native arrays\n\t\t\t\ttoString.call( obj ) === \"[object Array]\" ||\n\t\t\t\t// NodeList objects\n\t\t\t\t( typeof obj.length === \"number\" && typeof obj.item !== \"undefined\" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === \"undefined\" ) ) )\n\t\t\t) {\n\t\t\t\ttype = \"array\";\n\t\t\t} else {\n\t\t\t\ttype = typeof obj;\n\t\t\t}\n\t\t\treturn type;\n\t\t},\n\t\tseparator: function() {\n\t\t\treturn this.multiline ?\tthis.HTML ? '<br />' : '\\n' : this.HTML ? '&nbsp;' : ' ';\n\t\t},\n\t\tindent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing\n\t\t\tif ( !this.multiline ) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\tvar chr = this.indentChar;\n\t\t\tif ( this.HTML ) {\n\t\t\t\tchr = chr.replace(/\\t/g,'   ').replace(/ /g,'&nbsp;');\n\t\t\t}\n\t\t\treturn new Array( this._depth_ + (extra||0) ).join(chr);\n\t\t},\n\t\tup: function( a ) {\n\t\t\tthis._depth_ += a || 1;\n\t\t},\n\t\tdown: function( a ) {\n\t\t\tthis._depth_ -= a || 1;\n\t\t},\n\t\tsetParser: function( name, parser ) {\n\t\t\tthis.parsers[name] = parser;\n\t\t},\n\t\t// The next 3 are exposed so you can use them\n\t\tquote: quote,\n\t\tliteral: literal,\n\t\tjoin: join,\n\t\t//\n\t\t_depth_: 1,\n\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n\t\tparsers: {\n\t\t\twindow: '[Window]',\n\t\t\tdocument: '[Document]',\n\t\t\terror: '[ERROR]', //when no parser is found, shouldn't happen\n\t\t\tunknown: '[Unknown]',\n\t\t\t'null': 'null',\n\t\t\t'undefined': 'undefined',\n\t\t\t'function': function( fn ) {\n\t\t\t\tvar ret = 'function',\n\t\t\t\t\tname = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE\n\t\t\t\tif ( name ) {\n\t\t\t\t\tret += ' ' + name;\n\t\t\t\t}\n\t\t\t\tret += '(';\n\n\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');\n\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );\n\t\t\t},\n\t\t\tarray: array,\n\t\t\tnodelist: array,\n\t\t\t'arguments': array,\n\t\t\tobject: function( map, stack ) {\n\t\t\t\tvar ret = [ ], keys, key, val, i;\n\t\t\t\tQUnit.jsDump.up();\n\t\t\t\tif (Object.keys) {\n\t\t\t\t\tkeys = Object.keys( map );\n\t\t\t\t} else {\n\t\t\t\t\tkeys = [];\n\t\t\t\t\tfor (key in map) { keys.push( key ); }\n\t\t\t\t}\n\t\t\t\tkeys.sort();\n\t\t\t\tfor (i = 0; i < keys.length; i++) {\n\t\t\t\t\tkey = keys[ i ];\n\t\t\t\t\tval = map[ key ];\n\t\t\t\t\tret.push( QUnit.jsDump.parse( key, 'key' ) + ': ' + QUnit.jsDump.parse( val, undefined, stack ) );\n\t\t\t\t}\n\t\t\t\tQUnit.jsDump.down();\n\t\t\t\treturn join( '{', ret, '}' );\n\t\t\t},\n\t\t\tnode: function( node ) {\n\t\t\t\tvar open = QUnit.jsDump.HTML ? '&lt;' : '<',\n\t\t\t\t\tclose = QUnit.jsDump.HTML ? '&gt;' : '>';\n\n\t\t\t\tvar tag = node.nodeName.toLowerCase(),\n\t\t\t\t\tret = open + tag;\n\n\t\t\t\tfor ( var a in QUnit.jsDump.DOMAttrs ) {\n\t\t\t\t\tvar val = node[QUnit.jsDump.DOMAttrs[a]];\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\tret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn ret + close + open + '/' + tag + close;\n\t\t\t},\n\t\t\tfunctionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function\n\t\t\t\tvar l = fn.length;\n\t\t\t\tif ( !l ) {\n\t\t\t\t\treturn '';\n\t\t\t\t}\n\n\t\t\t\tvar args = new Array(l);\n\t\t\t\twhile ( l-- ) {\n\t\t\t\t\targs[l] = String.fromCharCode(97+l);//97 is 'a'\n\t\t\t\t}\n\t\t\t\treturn ' ' + args.join(', ') + ' ';\n\t\t\t},\n\t\t\tkey: quote, //object calls it internally, the key part of an item in a map\n\t\t\tfunctionCode: '[code]', //function calls it internally, it's the content of the function\n\t\t\tattribute: quote, //node calls it internally, it's an html attribute value\n\t\t\tstring: quote,\n\t\t\tdate: quote,\n\t\t\tregexp: literal, //regex\n\t\t\tnumber: literal,\n\t\t\t'boolean': literal\n\t\t},\n\t\tDOMAttrs:{//attributes to dump from nodes, name=>realName\n\t\t\tid:'id',\n\t\t\tname:'name',\n\t\t\t'class':'className'\n\t\t},\n\t\tHTML:false,//if true, entities are escaped ( <, >, \\t, space and \\n )\n\t\tindentChar:'  ',//indentation unit\n\t\tmultiline:true //if true, items in a collection, are separated by a \\n, else just a space.\n\t};\n\n\treturn jsDump;\n}());\n\n// from Sizzle.js\nfunction getText( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n}\n\n//from jquery.js\nfunction inArray( elem, array ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( elem );\n\t}\n\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[ i ] === elem ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * Javascript Diff Algorithm\n *  By John Resig (http://ejohn.org/)\n *  Modified by Chu Alan \"sprite\"\n *\n * Released under the MIT license.\n *\n * More Info:\n *  http://ejohn.org/projects/javascript-diff-algorithm/\n *\n * Usage: QUnit.diff(expected, actual)\n *\n * QUnit.diff(\"the quick brown fox jumped over\", \"the quick fox jumps over\") == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n */\nQUnit.diff = (function() {\n\tfunction diff(o, n) {\n\t\tvar ns = {};\n\t\tvar os = {};\n\t\tvar i;\n\n\t\tfor (i = 0; i < n.length; i++) {\n\t\t\tif (ns[n[i]] == null) {\n\t\t\t\tns[n[i]] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\to: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tns[n[i]].rows.push(i);\n\t\t}\n\n\t\tfor (i = 0; i < o.length; i++) {\n\t\t\tif (os[o[i]] == null) {\n\t\t\t\tos[o[i]] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\tn: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tos[o[i]].rows.push(i);\n\t\t}\n\n\t\tfor (i in ns) {\n\t\t\tif ( !hasOwn.call( ns, i ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ns[i].rows.length == 1 && typeof(os[i]) != \"undefined\" && os[i].rows.length == 1) {\n\t\t\t\tn[ns[i].rows[0]] = {\n\t\t\t\t\ttext: n[ns[i].rows[0]],\n\t\t\t\t\trow: os[i].rows[0]\n\t\t\t\t};\n\t\t\t\to[os[i].rows[0]] = {\n\t\t\t\t\ttext: o[os[i].rows[0]],\n\t\t\t\t\trow: ns[i].rows[0]\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor (i = 0; i < n.length - 1; i++) {\n\t\t\tif (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&\n\t\t\tn[i + 1] == o[n[i].row + 1]) {\n\t\t\t\tn[i + 1] = {\n\t\t\t\t\ttext: n[i + 1],\n\t\t\t\t\trow: n[i].row + 1\n\t\t\t\t};\n\t\t\t\to[n[i].row + 1] = {\n\t\t\t\t\ttext: o[n[i].row + 1],\n\t\t\t\t\trow: i + 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor (i = n.length - 1; i > 0; i--) {\n\t\t\tif (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&\n\t\t\tn[i - 1] == o[n[i].row - 1]) {\n\t\t\t\tn[i - 1] = {\n\t\t\t\t\ttext: n[i - 1],\n\t\t\t\t\trow: n[i].row - 1\n\t\t\t\t};\n\t\t\t\to[n[i].row - 1] = {\n\t\t\t\t\ttext: o[n[i].row - 1],\n\t\t\t\t\trow: i - 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\to: o,\n\t\t\tn: n\n\t\t};\n\t}\n\n\treturn function(o, n) {\n\t\to = o.replace(/\\s+$/, '');\n\t\tn = n.replace(/\\s+$/, '');\n\t\tvar out = diff(o === \"\" ? [] : o.split(/\\s+/), n === \"\" ? [] : n.split(/\\s+/));\n\n\t\tvar str = \"\";\n\t\tvar i;\n\n\t\tvar oSpace = o.match(/\\s+/g);\n\t\tif (oSpace == null) {\n\t\t\toSpace = [\" \"];\n\t\t}\n\t\telse {\n\t\t\toSpace.push(\" \");\n\t\t}\n\t\tvar nSpace = n.match(/\\s+/g);\n\t\tif (nSpace == null) {\n\t\t\tnSpace = [\" \"];\n\t\t}\n\t\telse {\n\t\t\tnSpace.push(\" \");\n\t\t}\n\n\t\tif (out.n.length === 0) {\n\t\t\tfor (i = 0; i < out.o.length; i++) {\n\t\t\t\tstr += '<del>' + out.o[i] + oSpace[i] + \"</del>\";\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (out.n[0].text == null) {\n\t\t\t\tfor (n = 0; n < out.o.length && out.o[n].text == null; n++) {\n\t\t\t\t\tstr += '<del>' + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (i = 0; i < out.n.length; i++) {\n\t\t\t\tif (out.n[i].text == null) {\n\t\t\t\t\tstr += '<ins>' + out.n[i] + nSpace[i] + \"</ins>\";\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvar pre = \"\";\n\n\t\t\t\t\tfor (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {\n\t\t\t\t\t\tpre += '<del>' + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t\t}\n\t\t\t\t\tstr += \" \" + out.n[i].text + nSpace[i] + pre;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn str;\n\t};\n}());\n\n// for CommonJS enviroments, export everything\nif ( typeof exports !== \"undefined\" || typeof require !== \"undefined\" ) {\n\textend(exports, QUnit);\n}\n\n// get at whatever the global object is, like window in browsers\n}( (function() {return this;}.call()) ));\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/test/test-errors.jquery.js",
    "content": "module(\"errors.jquery.js\");\n\ntest(\"$.fn.fillError() raises nice err when template not found\", function() {\n  try {\n    var div = $('<div></div>').fillError({type: \"BLARGY\"});\n  } catch (e) {\n    equal(e.message, \"Error template not found for BLARGY\");\n    return;\n  }\n  ok(false, \"Exception not thrown!\");\n});\n\ntest(\"$.fn.fillError() works when template is found\", function() {\n  var templates = $('<div class=\"error-msg BLARGY\">' +\n                    '<p>{{foo.bar}}</p></div>');\n  var div = $('<div></div>').fillError({\n    type: \"BLARGY\",\n    foo: {bar: \"hi\"}\n  }, templates);\n  equal(div.html(), \"<p>hi</p>\");\n});\n\ntest(\"$.fn.errorHighlightInterval() works\", function() {\n  deepEqual($('<div data-highlight=\"1\"></div>').errorHighlightInterval(),\n            {start: 1, end: undefined}, \"works w/ start only\");\n  deepEqual($('<div data-highlight=\"1,2\"></div>').errorHighlightInterval(),\n            {start: 1, end: 2}, \"works w/ number pair\");\n});\n\ntest(\"$.fn.eachErrorHighlight() works\", function() {\n  var args = [];\n  var div = $('<div><div data-highlight=\"1,2\"></div>' + \n               '<em data-highlight=\"3\"></em></div>');\n  div.eachErrorHighlight(function(start, end, i) {\n    args.push({\n      node: this.nodeName,\n      start: start,\n      end: end,\n      i: i\n    });\n  });\n  deepEqual(args, [\n    {\n      \"end\": 2,\n      \"i\": 0,\n      \"node\": \"DIV\",\n      \"start\": 1\n    },\n    {\n      \"end\": undefined,\n      \"i\": 1,\n      \"node\": \"EM\",\n      \"start\": 3\n    }\n  ]);\n});\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/test/test-slowparse.js",
    "content": "module(\"Slowparse\");\n\ntest(\"Stream.match()\", function() {\n  var stream = new Slowparse.Stream(\"blArgle\");\n  ok(stream.match(\"blArgle\"));\n  equal(stream.pos, 0);\n  ok(!stream.match(\"blargle\"));\n  equal(stream.pos, 0);\n  ok(stream.match(\"blargle\", false, true));\n  equal(stream.pos, 0);\n  ok(stream.match(\"bla\", true, true));\n  equal(stream.pos, 3);\n  ok(stream.match(\"rgle\", true));\n  equal(stream.pos, 7);\n});\n\ntest(\"Stream.eat() works at EOF\", function() {\n  var stream = new Slowparse.Stream(\"\");\n  ok(!stream.eat(/blah/));\n});\n\ntest(\"parsing of valid DOCTYPE\", function() {\n  var html = '<!DOCTYPE html><p>hi</p>';\n  var doc = parseWithoutErrors(html);\n  assertParseIntervals(html, doc, \"document\", {\n    'parseInfo.doctype': '<!DOCTYPE html>'\n  });\n});\n\ntest(\"parsing of misplaced DOCTYPE\", function() {\n  var html = '<p>hi</p><!DOCTYPE html>';\n  var result = Slowparse.HTML(document, html);\n  deepEqual(result.error, {\n    \"openTag\": {\n      \"end\": 10,\n      \"name\": \"\",\n      \"start\": 9\n    },\n    \"type\": \"INVALID_TAG_NAME\"\n  });\n});\n\ntest(\"parsing of HTML comments\", function() {\n  var html = 'hi<!--testing-->there';\n  var doc = parseWithoutErrors(html);\n  assertParseIntervals(html, doc.childNodes[1], \"comment\", {\n    'parseInfo': '<!--testing-->'\n  });\n});\n\ntest(\"UNQUOTED_ATTR_VALUE in <h2><span start=</h2>\", function() {\n  // https://github.com/mozilla/slowparse/issues/6\n  var err = Slowparse.HTML(document, '<h2><span start=</h2>').error;\n  equal(err.type, \"UNQUOTED_ATTR_VALUE\");\n});\n\ntest(\"parsing of elements with boolean attributes\", function() {\n  var html = '<a href></a>';\n  var doc = parseWithoutErrors(html);\n  var attr = doc.childNodes[0].attributes[0];\n  equal(attr.nodeName, 'href');\n  equal(attr.nodeValue, '');\n  assertParseIntervals(html, attr, \"attr\", {\n    'parseInfo.name': 'href'\n  });\n  \n  var error = Slowparse.HTML(document, '<a href+></a>').error;\n  equal(error.type, 'UNTERMINATED_OPEN_TAG');\n\n  html = '<a href class=\"foo\"></a>';\n  doc = parseWithoutErrors(html);\n  var attr1 = doc.childNodes[0].attributes[0];\n  var attr2 = doc.childNodes[0].attributes[1];\n  \n  // Apparently NamedNodeMap entries are not in any particular order:\n  // https://developer.mozilla.org/en/DOM/NamedNodeMap\n  // \n  // So, we'll swap these values if they're not in the order we expect\n  // them to be in, which is the case in IE9, at the very least.\n  if (attr1.nodeName == 'class') {\n    var temp = attr1;\n    attr1 = attr2;\n    attr2 = temp;\n  }\n  \n  equal(attr1.nodeName, 'href');\n  equal(attr1.nodeValue, '');\n  equal(attr2.nodeName, 'class');\n  equal(attr2.nodeValue, 'foo');\n  assertParseIntervals(html, attr1, \"attr1\", {\n    'parseInfo.name': 'href'\n  });\n  ok(attr1.parseInfo.value === undefined);\n  assertParseIntervals(html, attr2, \"attr2\", {\n    'parseInfo.name': 'class',\n    'parseInfo.value': '\"foo\"'\n  });\n});\n\ntest(\"parsing of <script> tags\", function() {\n  var html = '<script>x < 3;</script>';\n  var doc = parseWithoutErrors(html);\n  equal(doc.childNodes.length, 1, \"document has one child\");\n  \n  var script = doc.childNodes[0];\n  equal(script.nodeName, \"SCRIPT\",\n        \"first child of generated DOM is <script>\");\n  equal(script.childNodes.length, 1, \"<script> has one child\");\n  var textNode = script.childNodes[0];\n\n  equal(textNode.nodeType, textNode.TEXT_NODE,\n        \"<script>'s child is a text node.\");\n  assertParseIntervals(html, textNode, \"textNode\", {\n    'parseInfo': 'x < 3;',\n  });\n  equal(documentFragmentHTML(doc), html,\n        \"serialization of generated DOM matches original HTML\");\n});\n\ntest(\"parsing of valid HTML\", function() {\n  var html = '<p class=\"foo\">hello there</p>';\n  var doc = parseWithoutErrors(html);\n  \n  equal(doc.childNodes.length, 1, \"document has one child\");\n  \n  var p = doc.childNodes[0];\n\n  equal(p.nodeName, \"P\", \"first child of generated DOM is <p>\");\n  assertParseIntervals(html, p, \"p\", {\n    'parseInfo.openTag': '<p class=\"foo\">',\n    'parseInfo.closeTag': '</p>'\n  });\n  equal(p.childNodes.length, 1, \"<p> has one child\");\n  equal(p.attributes.length, 1, \"<p> has one attribute\");\n\n  var textNode = p.childNodes[0];\n\n  equal(textNode.nodeType, textNode.TEXT_NODE, \"<p>'s child is a text node.\");\n  assertParseIntervals(html, textNode, \"textNode\", {\n    'parseInfo': 'hello there',\n  });\n  assertParseIntervals(html, p.attributes[0], \"attr\", {\n    'parseInfo.name': 'class',\n    'parseInfo.value': '\"foo\"'\n  });\n\n  equal(documentFragmentHTML(doc), html,\n        \"serialization of generated DOM matches original HTML\");\n});\n\ntest(\"parsing of HTML comments with '--' in them\", function() {\n  var html = '<!-- allow\\n--\\nin comments plz -->';\n  var doc = parseWithoutErrors(html);\n  equal(documentFragmentHTML(doc), html,\n        \"serialization of generated DOM matches original HTML\");\n});\n\ntest(\"parsing of CDATA in <textarea> elements\", function() {\n  var text = \"\\nThis is CDATA with <p>, <i> and\" +\n             \" <script> in it.\\nThis should not trigger errors.\";\n  var html = \"<textarea>\" + text + \"</textarea>\";\n  var doc = parseWithoutErrors(html);\n\n  equal(doc.childNodes.length, 1, \"doc has one child node\");\n  equal(doc.childNodes[0].nodeName, \"TEXTAREA\", \"child node is <textarea>\");\n  equal(doc.childNodes[0].childNodes.length, 1, \"textarea has one child\");\n  equal(doc.childNodes[0].childNodes[0].nodeValue, text,\n        \"textarea contents are ok\");\n});\n\ntestManySnippets(\"parsing of HTML is case-insensitive\", [\n  '<P CLASS=\"FOO\">hi</P>',\n  '<P class=\"FOO\">hi</P>',\n  '<p class=\"FOO\">hi</P>',\n  '<P class=\"FOO\">hi</p>'\n], function(html, doc) {\n  equal(doc.childNodes[0].nodeName, 'P');\n  equal(doc.childNodes[0].getAttribute('class'), 'FOO');\n});\n\ntest(\"DOMBuilder is called with lowercased element/attrs\", function() {\n  var elements = [];\n  var attributes = [];\n  var fakeBuilder = {\n    currentNode: {},\n    pushElement: function(tagName, parseInfo) {\n      this.currentNode.parseInfo = parseInfo;\n      this.currentNode.nodeName = tagName.toUpperCase();\n      elements.push(tagName);\n    },\n    popElement: function() {},\n    attribute: function(name, value) {\n      attributes.push(name);\n    }\n  };\n  fakeBuilder.fragment = fakeBuilder.currentNode;\n  var result = Slowparse.HTML(fakeBuilder, '<P CLASS=\"FOO\"></P>');\n  equal(result.error, null);\n  deepEqual(elements, ['p'], \"tag names are lowercased\");\n  deepEqual(attributes, ['class'], \"attribute names are lowercased\");\n});\n\ntest(\"parsing of SVG elements\", function() {\n  var d = \"M 0 0 L 100 0 L 100 100 L 0 100 Z\";\n  var html = \"<svg width='100' height='100' viewbox='0 0 100 100'><path d='\"+d+\"'/></svg>\";\n  var doc = parseWithoutErrors(html);\n\n  equal(doc.childNodes.length, 1, \"doc has one child node\");\n  equal(doc.childNodes[0].nodeName, \"svg\", \"child node is <svg>\");\n  equal(doc.childNodes[0].childNodes.length, 1, \"svg element has one child\");\n  equal(doc.childNodes[0].childNodes[0].nodeName, \"path\", \"svg child node is <path>\");\n  equal(doc.childNodes[0].childNodes[0].getAttribute('d'), d, \"path outline data is correct\");\n});\n\ntest(\"verifying SVG namespace\", function() {\n  var d = \"M 0 0 L 100 0 100 100 0 100 Z\";\n  var html = \"<html><body><p>test</p><svg width='100' height='100' viewbox='0 0 100 100'><path d='\"+d+\"'/></svg><p>test</p></body></html>\";\n  var doc = parseWithoutErrors(html);\n  \n  var htmlns = \"http://www.w3.org/1999/xhtml\",\n      svgns = \"http://www.w3.org/2000/svg\";\n\n  equal(doc.childNodes.length, 1, \"doc has one child node\");\n  equal(doc.childNodes[0].nodeName, \"HTML\", \"top element is <html>\");\n  equal(doc.childNodes[0].childNodes[0].nodeName, \"BODY\", \"contained element is <body>\");\n  equal(doc.childNodes[0].childNodes[0].childNodes[0].nodeName, \"P\", \"first content node is <p>\");\n  equal(doc.childNodes[0].childNodes[0].childNodes[0].namespaceURI.toLowerCase(), htmlns, \"p element uses the correct namespace\");\n  equal(doc.childNodes[0].childNodes[0].childNodes[1].nodeName, \"svg\", \"second content node is <svg>\");\n  equal(doc.childNodes[0].childNodes[0].childNodes[1].namespaceURI.toLowerCase(), svgns, \"svg element uses the correct namespace\");\n  equal(doc.childNodes[0].childNodes[0].childNodes[2].nodeName, \"P\", \"third content node is <p>\");\n  equal(doc.childNodes[0].childNodes[0].childNodes[2].namespaceURI.toLowerCase(), htmlns, \"p element uses the correct namespace\");\n});\n\ntest(\"verifying out-of-svg error\", function() {\n  var html = \"<html><body><svg><rect/></svg><path>error</path></body></html>\";\n  var error = Slowparse.HTML(document, html).error;\n  equal(error.type, \"INVALID_TAG_NAME\");\n});\n\ntestManySnippets(\"parsing of HTML with void elements:\", [\n  '<br>',\n  '<img src=\"http://www.mozilla.org/favicon.ico\">'\n], function(html, doc) {\n  equal(documentFragmentHTML(doc), html);\n});\n\ntestManySnippets(\"parsing of text content w/ newlines\", [\n  '<p>hello\\nthere</p>',\n  '<p>\\n  hello there</p>'\n], function(html, doc) {\n  equal(documentFragmentHTML(doc), html);\n});\n\ntestManySnippets(\"parsing of valid HTML w/ whitespace\", [\n  '<p class = \"foo\">hello there</p><p>u</p>',\n  '<p class=\"foo\"  >hello there</p><p>u</p>',\n  '<p \\nclass=\"foo\">hello there</p><p>u</p>',\n  '<p class=\"foo\">hello there</p ><p>u</p>'\n], function(html, doc) {\n  var canonicalHTML = '<p class=\"foo\">hello there</p><p>u</p>';\n  var p = doc.childNodes[0];\n  assertParseIntervals(html, p.childNodes[0], \"textNode\", {\n    'parseInfo': 'hello there'\n  });\n  assertParseIntervals(html, p.attributes[0], \"attr\", {\n    'parseInfo.name': 'class',\n    'parseInfo.value': '\"foo\"'\n  });\n\n  equal(documentFragmentHTML(doc), canonicalHTML,\n        \"Document fragment is correct.\");\n});\n\ntestStyleSheet(\"parsing of CSS rule w/ one decl, no semicolon\",\n               \"body { color: pink }\",\n               function(html, css, styleContents) {\n    equal(styleContents.parseInfo.rules.length, 1);\n    equal(styleContents.parseInfo.rules[0].declarations.properties.length, 1);\n    \n    assertParseIntervals(html, styleContents, \"style\", {\n      'parseInfo': 'body { color: pink }',\n      'parseInfo.rules[0].selector': 'body',\n      'parseInfo.rules[0].declarations': '{ color: pink }',\n      'parseInfo.rules[0].declarations.properties[0].name': 'color',\n      'parseInfo.rules[0].declarations.properties[0].value': 'pink'\n    });\n});\n\ntestStyleSheet(\"parsing of CSS rule w/ one decl and semicolon\",\n               \"body { color: pink; }\",\n               function(html, css, styleContents) {\n    equal(styleContents.parseInfo.rules.length, 1);\n    equal(styleContents.parseInfo.rules[0].declarations.properties.length, 1);\n    assertParseIntervals(html, styleContents, \"style\", {\n      'parseInfo': 'body { color: pink; }',\n      'parseInfo.rules[0].selector': 'body',\n      'parseInfo.rules[0].declarations': '{ color: pink; }',\n      'parseInfo.rules[0].declarations.properties[0].name': 'color',\n      'parseInfo.rules[0].declarations.properties[0].value': 'pink'\n    });\n});\n\ntestStyleSheet(\"parsing of empty CSS rule\",\n               \"body {}\",\n               function(html, css, styleContents) {\n   equal(styleContents.parseInfo.rules.length, 1);\n   equal(styleContents.parseInfo.rules[0].declarations.properties.length, 0);\n    assertParseIntervals(html, styleContents, \"style\", {\n      'parseInfo': 'body {}',\n      'parseInfo.rules[0].selector': 'body',\n      'parseInfo.rules[0].declarations': '{}'\n    });\n});\n\ntestStyleSheet(\"parsing of CSS rule w/ funky whitespace\",\n               [\"body\\n { color: pink; }\",\n                \"body\\n {\\n color: pink; }\",\n                \"body\\n {\\n color: \\npink; }\",\n                \"body\\n {\\n color: \\npink\\n\\n }\",\n                \"body\\n {\\n color : \\npink\\n\\n }\",\n                \"body\\n {\\n color: \\npink \\n; }\",\n                \"body\\n {\\n color: \\npink; }\\n\"],\n               function(html, css, styleContents) {\n    equal(styleContents.parseInfo.rules.length, 1);\n    equal(styleContents.parseInfo.rules[0].declarations.properties.length, 1);\n    assertParseIntervals(html, styleContents, \"style\", {\n      'parseInfo.rules[0].selector': 'body',\n      'parseInfo.rules[0].declarations.properties[0].name': 'color',\n      'parseInfo.rules[0].declarations.properties[0].value': 'pink'\n    });\n});\n\ntestStyleSheet(\"parsing of empty CSS sheet w/ comment\",\n               \"/* nothing to see here. */\",\n               function(html, css, styleContents) {\n    equal(styleContents.parseInfo.rules.length, 0);\n});\n\ntestStyleSheet(\"parsing of empty CSS rule w/ comment\",\n               \"p { /* nothing to see here. */ }\",\n               function(html, css, styleContents) {\n    equal(styleContents.parseInfo.rules.length, 1);\n});\n\ntestStyleSheet(\"parsing of CSS rule w/ comments\",\n               \"/** comment 1 **/ bo/* comment 2 */dy /*comment 3*/{ /* c4 */ co/*c5*/lor/*c6*/: /*c7*/pi/*c8*/nk/*c9****** c9 *****/}\",\n               function(html, css, styleContents) {\n    equal(styleContents.parseInfo.rules.length, 1);\n    equal(styleContents.parseInfo.rules[0].declarations.properties.length, 1);\n    assertParseIntervals(html, styleContents, \"style\", {\n      'parseInfo': '/** comment 1 **/ bo/* comment 2 */dy /*comment 3*/{ /* c4 */ co/*c5*/lor/*c6*/: /*c7*/pi/*c8*/nk/*c9****** c9 *****/}',\n      'parseInfo.rules[0].selector': 'bo/* comment 2 */dy',\n      'parseInfo.rules[0].declarations': '{ /* c4 */ co/*c5*/lor/*c6*/: /*c7*/pi/*c8*/nk/*c9****** c9 *****/}',\n      'parseInfo.rules[0].declarations.properties[0].name': 'co/*c5*/lor',\n      'parseInfo.rules[0].declarations.properties[0].value': 'pi/*c8*/nk',\n    });\n    \n    equal(styleContents.parseInfo.rules[0].selector.value, \"body\");\n    equal(styleContents.parseInfo.rules[0].declarations.properties[0].name.value, \"color\");\n    equal(styleContents.parseInfo.rules[0].declarations.properties[0].value.value, \"pink\");\n\n    equal(styleContents.parseInfo.comments.length, 9);\n    assertParseIntervals(html, styleContents, \"style\", {\n      'parseInfo.comments[0]': '/** comment 1 **/',\n      'parseInfo.comments[1]': '/* comment 2 */',\n      'parseInfo.comments[2]': '/*comment 3*/',\n      'parseInfo.comments[3]': '/* c4 */',\n      'parseInfo.comments[4]': '/*c5*/',\n      'parseInfo.comments[5]': '/*c6*/',\n      'parseInfo.comments[6]': '/*c7*/',\n      'parseInfo.comments[7]': '/*c8*/',\n      'parseInfo.comments[8]': '/*c9****** c9 *****/'\n    });\n});\n\ntestStyleSheet(\"parsing of CSS rule w/ vendor prefixes\",\n               \".vendors { -o-border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; -ms-border-radius: 5px; border-radius: 5px; }\",\n               function(html, css, styleContents) {\n    equal(styleContents.parseInfo.rules.length, 1);\n    equal(styleContents.parseInfo.rules[0].declarations.properties.length, 5);\n    assertParseIntervals(html, styleContents, \"style\", {\n      'parseInfo': '.vendors { -o-border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; -ms-border-radius: 5px; border-radius: 5px; }',\n      'parseInfo.rules[0].selector': '.vendors',\n      'parseInfo.rules[0].declarations': '{ -o-border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; -ms-border-radius: 5px; border-radius: 5px; }',\n      'parseInfo.rules[0].declarations.properties[0].name': '-o-border-radius',\n      'parseInfo.rules[0].declarations.properties[0].value': '5px',\n      'parseInfo.rules[0].declarations.properties[1].name': '-moz-border-radius',\n      'parseInfo.rules[0].declarations.properties[1].value': '5px',\n      'parseInfo.rules[0].declarations.properties[2].name': '-webkit-border-radius',\n      'parseInfo.rules[0].declarations.properties[2].value': '5px',\n      'parseInfo.rules[0].declarations.properties[3].name': '-ms-border-radius',\n      'parseInfo.rules[0].declarations.properties[3].value': '5px',\n      'parseInfo.rules[0].declarations.properties[4].name': 'border-radius',\n      'parseInfo.rules[0].declarations.properties[4].value': '5px',\n    });\n});\n\ntest(\"replaceEntityRefs\", function() {\n  [\n    [\"&lt;\", \"<\"],\n    [\"&gt;\", \">\"],\n    [\"&amp;\", \"&\"],\n    [\"&quot;\", '\"'],\n    [\"&QUOT;\", '\"', \"matches are case-insensitive\"],\n    [\"&lt;p&gt; tag\", \"<p> tag\", \"multiple refs are replaced\"],\n    [\"hello &garbage;\", \"hello &garbage;\", \"replacer is forgiving\"]\n  ].forEach(function(arg) {\n    equal(Slowparse.replaceEntityRefs(arg[0]), arg[1],\n          \"replaceEntityRefs(\" + JSON.stringify(arg[0]) + \") == \" +\n          JSON.stringify(arg[1]) + (arg[2] ? \" (\" + arg[2] + \")\" : \"\"));\n  });\n});\n\ntest(\"parsing of self-closing void elements works\", function() {\n  var html = 'hello<br/>';\n  var doc = parseWithoutErrors(html);\n  assertParseIntervals(html, doc.childNodes[1], \"brNode\", {\n    'parseInfo.openTag': '<br/>',\n  });\n});\n\ntest(\"parsing of self-closing void elements w/ spaces works\", function() {\n  var html = 'hello<br />';\n  var doc = parseWithoutErrors(html);\n  assertParseIntervals(html, doc.childNodes[1], \"brNode\", {\n    'parseInfo.openTag': '<br />',\n  });\n});\n\ntest(\"parsing of text content w/ HTML entities\", function() {\n  var html = '<p>&lt;p&gt;</p>';\n  var doc = parseWithoutErrors(html);\n  var textNode = doc.childNodes[0].childNodes[0];\n  equal(textNode.nodeValue, '<p>');\n  assertParseIntervals(html, textNode, \"textNode\", {\n    'parseInfo': '&lt;p&gt;',\n  });\n});\n\nasyncTest(\"parsing of <script> tags doesn't execute the code\", function() {\n  var html = '<script>alert(\"PWNED\"); window.PWNED = true;</script>';\n  var doc = parseWithoutErrors(html);\n  setTimeout(function() {\n    equal(window.PWNED, undefined);\n    start();\n  }, 100);\n});\n\ntest(\"parsing of attr content w/ HTML entities\", function() {\n  var html = '<p class=\"1 &lt; 2 &LT; 3\"></p>';\n  var doc = parseWithoutErrors(html);\n  var attrNode = doc.childNodes[0].attributes[0];\n  equal(attrNode.nodeValue, '1 < 2 < 3');\n  assertParseIntervals(html, attrNode, \"attr\", {\n    'parseInfo.value': '\"1 &lt; 2 &LT; 3\"',\n  });\n});\n\ntest(\"INVALID_TAG_NAME raised by < at EOF\", function() {\n  var error = Slowparse.HTML(document, '<').error;\n  equal(error.type, \"INVALID_TAG_NAME\");\n});\n\ntest(\"MISSING_CSS_SELECTOR works after comment\", function() {\n  var html = '<style>/* hello */ {</style>';\n  var error = Slowparse.HTML(document, html).error;\n  equal(error.type, \"MISSING_CSS_SELECTOR\");\n});\n\ntest(\"UNTERMINATED_ATTR_VALUE works at end of stream\", function() {\n  var html = '<a href=\"';\n  var error = Slowparse.HTML(document, html).error;\n  equal(error.type, \"UNTERMINATED_ATTR_VALUE\");\n  equal(error.attribute.value.start, html.length-1);\n});\n\ntest(\"UNQUOTED_ATTR_VALUE works at end of stream\", function() {\n  var html = '<a href=';\n  var error = Slowparse.HTML(document, html).error;\n  equal(error.type, \"UNQUOTED_ATTR_VALUE\");\n  equal(error.start, html.length);\n});\n\ntest(\"UNTERMINATED_CLOSE_TAG works at end of stream\", function() {\n  var html = \"<span>test</span\";\n  var error = Slowparse.HTML(document, html).error;\n  equal(error.type, \"UNTERMINATED_CLOSE_TAG\");\n  equal(error.closeTag.end, html.length);\n});\n\ntest(\"Slowparse.HTML_ELEMENT_NAMES\", function() {\n  ok(Slowparse.HTML_ELEMENT_NAMES.indexOf(\"p\") != -1);\n});\n\ntest(\"Slowparse.CSS_PROPERTY_NAMES\", function() {\n  ok(Slowparse.CSS_PROPERTY_NAMES.indexOf(\"color\") != -1);\n});\n\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/test/test-spec.js",
    "content": "module(\"Specification loading\");\n\nasyncTest(\"frame loads\", function() {\n  var iframe = document.createElement(\"iframe\");\n  iframe.setAttribute(\"src\", \"../spec/index.html\");\n  document.body.appendChild(iframe);\n  iframe.style.display = \"none\";\n  iframe.addEventListener(\"load\", function() {\n    ok(true, \"load event is triggered\");\n    iframe.contentWindow.runTests(module, test, ok, deepEqual, start);\n  }, false);\n});\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/test/test-tree-inspectors.js",
    "content": "module(\"TreeInspectors.forbidJS()\");\n\ntest(\"works on script-less HTML\", function() {\n  var html = '<p class=\"hi\">hello</p><!-- hi -->';\n  var result = Slowparse.HTML(document, html, [TreeInspectors.forbidJS]);\n  equal(result.error, null);\n  equal(documentFragmentHTML(result.document), html);\n});\n\n(function() {\n  module(\"TreeInspectors.findJS()\");\n  \n  function findJS(html) {\n    var doc = Slowparse.HTML(document, html).document;\n    return TreeInspectors.findJS(doc);\n  }\n  \n  test(\"works on script-less HTML\", function() {\n    deepEqual(findJS('<p class=\"hi\">hello</p><!-- hi -->'), []);\n  });\n\n  test(\"SCRIPT_ELEMENT is reported\", function() {\n    var html = '<script>alert(\"yo\");</script>';\n    var js = findJS(html);\n    equal(js.length, 1);\n    equal(js[0].type, \"SCRIPT_ELEMENT\");\n    assertParseIntervals(html, js[0].node, \"elementNode\", {\n      'parseInfo.openTag': '<script>'\n    });\n  });\n  \n  test(\"EVENT_HANDLER_ATTR is reported\", function() {\n    var html = '<p onclick=\"alert(\\'yo\\');\">hi</p>';\n    var js = findJS(html);\n    equal(js.length, 1);\n    equal(js[0].type, \"EVENT_HANDLER_ATTR\");\n    assertParseIntervals(html, js[0].node, \"attributeNode\", {\n      'parseInfo.name': 'onclick',\n      'parseInfo.value': '\"alert(\\'yo\\');\"'\n    });\n  });\n  \n  test(\"JAVASCRIPT_URL is reported\", function() {\n    var html = '<a href=\"javascript:alert(\\'yo\\');\">hi</a>';\n    var js = findJS(html);\n    equal(js.length, 1);\n    equal(js[0].type, \"JAVASCRIPT_URL\");\n    assertParseIntervals(html, js[0].node, \"attributeNode\", {\n      'parseInfo.name': 'href',\n      'parseInfo.value': '\"javascript:alert(\\'yo\\');\"'\n    });\n  });\n})();\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/test/testing-utils.js",
    "content": "// Get the innerHTML of a document fragment.\nfunction documentFragmentHTML(doc) {\n  var div = document.createElement(\"div\");\n  for (var i = 0; i < doc.childNodes.length; i++) {\n    div.appendChild(doc.childNodes[i].cloneNode(true));\n  }\n  return div.innerHTML;\n}\n\n// Ensure that an object containing {start,end} keys correspond\n// to a particular substring of HTML source code.\nfunction assertParseIntervals(html, node, name, map) {\n  function getDottedProperty(obj, property) {\n    var parts = property.split('.');\n    parts.forEach(function(part) {\n      var arrayIndexMatch = part.match(/^(.+)\\[(\\d+)\\]$/);\n      if (arrayIndexMatch)\n        part = arrayIndexMatch[1];\n      if (!(part in obj))\n        return null;\n      obj = obj[part];\n      if (arrayIndexMatch)\n        obj = obj[parseInt(arrayIndexMatch[2])];\n    });\n    return obj;\n  }\n\n  for (var dottedName in map) {\n    var baseName = name + \".\" + dottedName;\n    var interval = getDottedProperty(node, dottedName);\n    ok(interval, baseName + \" exists\");\n    if (interval) {\n      equal(html.slice(interval.start, interval.end), map[dottedName],\n            baseName + \" start/end positions are correct\");\n    }\n  }\n}\n\n// Parse the given HTML, ensure it has no errors, and return the\n// parsed document.\nfunction parseWithoutErrors(html) {\n  var result = Slowparse.HTML(document, html);\n  \n  ok(result.document, \"document is returned\");\n  equal(result.error, null, \"no errors are reported\");\n  \n  return result.document;\n}\n\n// Test many snippets of valid HTML, passing the HTML and its document\n// to a callback function that does the actual testing. Useful for \n// testing that many different inputs result in the same output.\nfunction testManySnippets(name, htmlStrings, cb) {\n  htmlStrings.forEach(function(html) {\n    test(name + \": \" + JSON.stringify(html), function() {\n      cb(html, parseWithoutErrors(html));\n    });\n  });\n}\n\n// Test one or more snippets of CSS.\nfunction testStyleSheet(name, cssList, cb) {\n  if (typeof(cssList) == \"string\")\n    cssList = [cssList];\n  \n  cssList.forEach(function(css) {\n    test(name + \": \" + JSON.stringify(css), function() {\n      var html = '<style>' + css + '</style>';\n      var doc = parseWithoutErrors(html);\n      var styleContents = doc.childNodes[0].childNodes[0];\n      equal(styleContents.nodeValue, css);\n      cb(html, css, styleContents);\n    });\n  });\n}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/tree-inspectors.js",
    "content": "\"use strict\";\n\n// `TreeInspectors` contains functions that inspect a document\n// fragment and report interesting things about it.\n//\n// This library has no required dependencies, though optional Slowparse\n// integration is included.\n//\n// If [RequireJS] is detected, this file is defined as a module via\n// `define()`. Otherwise, a global called `TreeInspectors` is exposed.\n//\n//   [RequireJS]: http://requirejs.org/\nvar TreeInspectors = (function() {\n  // ## Utility Functions\n  var utils = {\n    // This function calls the given function for every element\n    // that matches the given selector.\n    each: function each(doc, selector, fn) {\n      var all = doc.querySelectorAll(selector);\n      for (var i = 0; i < all.length; i++)\n        fn(all[i]);\n    },\n    // This function calls the given function for every attribute\n    // in the given DOM node, as well as for every attribute in all\n    // its children.\n    eachAttr: function eachAttr(node, fn) {\n      var i;\n      if (node.attributes)\n        for (i = 0; i < node.attributes.length; i++)\n          fn(node.attributes[i]);\n      for (i = 0; i < node.childNodes.length; i++)\n        if (node.childNodes[i].nodeType == node.ELEMENT_NODE)\n          eachAttr(node.childNodes[i], fn);\n    }\n  };\n  \n  var TreeInspectors = {\n    // We export our utility functions in case any other scripts want\n    // to extend the `TreeInspectors` object with more inspectors.\n    utils: utils,\n    // ## Finding JavaScript Usage\n    //\n    // Given a document fragment, this function finds all occurrences\n    // of the most common kinds of JavaScript use in it and returns\n    // an array containing `{type, node}` objects that describe each\n    // use of JavaScript.\n    findJS: function(doc) {\n      var js = [];\n      \n      // We want to find `script` elements.\n      utils.each(doc, \"script\", function(script) {\n        js.push({type: \"SCRIPT_ELEMENT\", node: script});\n      });\n      \n      utils.eachAttr(doc, function(attr) {\n        // If the attribute name begins with `on`, we can safely assume\n        // it's an event handler attribute. We can change this in the\n        // future if there are valid non-event-handler attributes that\n        // start with `on`.\n        if (attr.nodeName.match(/^on/i))\n          js.push({type: \"EVENT_HANDLER_ATTR\", node: attr});\n          \n        // If the attribute value starts with `javascript:`, regardless\n        // of the attribute name, raise an error. We can change this in\n        // the future if we only want to make this check on specific\n        // attributes.\n        if (attr.nodeValue.match(/^javascript:/i))\n          js.push({type: \"JAVASCRIPT_URL\", node: attr});\n      });\n      \n      return js;\n    },\n    // This is a Slowparse error detector that returns an error object\n    // if the given document fragment contains any JS.\n    forbidJS: function(html, doc) {\n      var js = TreeInspectors.findJS(doc);\n      if (!js.length)\n        return null;\n      var error = JSON.parse(JSON.stringify(js[0].node.parseInfo));\n      error.type = js[0].type + \"_NOT_ALLOWED\";\n      return error;\n    }\n  };\n  \n  if (typeof(define) == \"function\") {\n    define(function() { return TreeInspectors; });\n  } else\n    return TreeInspectors;\n})();\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/brocco.js",
    "content": "\"use strict\";\n\n// This is a simple port of [Docco][] to the browser, which potentially\n// relieves developers of needing a build/deploy step for their\n// documentation. This makes it a bit like Docco combined with\n// [Code Illuminated][].\n//\n// The [source for Brocco][source] is available on GitHub, and released under\n// the MIT license.\n//\n// ## Dependencies\n//\n// The only required dependencies are `brocco.js`, `docco.css`, and\n// `showdown.js`.\n//\n// Optional syntax highlighting requires [CodeMirror][]. Simply\n// include `codemirror.js` and the modes for any\n// languages you're documenting, and Brocco will take care of\n// the rest.\n//\n// ## Usage\n//\n// After including the requisite scripts and CSS file in a webpage,\n// you can render basic documentation like this:\n//\n//     Brocco.document(\"myfile.js\");\n//\n// This will insert the generated documentation into the page's\n// `<body>` element. Alternatively, if you want to be passed the\n// generated HTML, you can do this:\n//\n//     Brocco.document(\"myfile.js\", function(html) {\n//       document.getElementById(\"mydocs\").innerHTML = html;\n//     });\n//\n// By default, Brocco will try to fetch the source file over XHR. If\n// you have it on hand, though, you can do this:\n//\n//     Brocco.document(\"myfile.js\", {\n//       code: \"console.log('hello world.');\"\n//     });\n//\n//   [source]: https://github.com/toolness/brocco\n//   [Docco]: http://jashkenas.github.com/docco/\n//   [Code Illuminated]: http://www.toolness.com/wp/?p=441\n//   [CodeMirror]: http://codemirror.net/\n\nvar Brocco = (function() {\n  var version = \"0.1.0\";\n  \n  // ## Main Documentation Generation Functions\n  \n  // Generate the documentation for a source file by (optionally) reading it\n  // in, splitting it up into comment/code sections, highlighting them for\n  // the appropriate language, and merging them into an HTML template.\n  function generateDocumentation(source, config, callback) {\n    var code;\n\n    var parseAndHighlight = function() {\n      var sections = parse(source, code);\n      return highlight(source, sections, config, function() {\n        callback(generateHtml(source, sections, config));\n      });\n    };\n\n    if (typeof(config) != \"object\") {\n      callback = config;\n      config = {};\n    }\n\n    code = config.code;\n    if (!config.template)\n      config.template = defaultTemplate;\n    \n    if (!callback)\n      callback = insertHtmlIntoBody;\n\n    if (typeof(code) == \"undefined\") {\n      getSourceFile(source, function(contents) {\n        code = contents;\n        parseAndHighlight();\n      });\n    } else\n      parseAndHighlight();\n  }\n\n  // Given a string of source code, parse out each comment and the code that\n  // follows it, and create an individual **section** for it.\n  // Sections take the form:\n  //\n  //     {\n  //       docsText: ...\n  //       docsHtml: ...\n  //       codeText: ...\n  //       codeHtml: ...\n  //     }\n  function parse(source, code) {\n    var codeText, docsText, hasCode, language, line, lines, save, \n        sections, _i, _len;\n    lines = code.split('\\n');\n    sections = [];\n    language = getLanguage(source);\n    hasCode = docsText = codeText = '';\n    save = function(docsText, codeText) {\n      return sections.push({\n        docsText: docsText,\n        codeText: codeText\n      });\n    };\n    for (_i = 0, _len = lines.length; _i < _len; _i++) {\n      line = lines[_i];\n      if (line.match(language.commentMatcher) &&\n          !line.match(language.commentFilter)) {\n        if (hasCode) {\n          save(docsText, codeText);\n          hasCode = docsText = codeText = '';\n        }\n        docsText += line.replace(language.commentMatcher, '') + '\\n';\n      } else {\n        hasCode = true;\n        codeText += line + '\\n';\n      }\n    }\n    save(docsText, codeText);\n    return sections;\n  };\n  \n  // Highlights parsed sections of code. Runs the text of\n  // their corresponding comments through **Markdown**, using\n  // [Showdown][]. If no syntax highlighter is present, output the\n  // code in plain text.\n  //\n  //   [Showdown]: http://attacklab.net/showdown/\n  function highlight(source, sections, config, callback) {\n    var section;\n    var language = getLanguage(source);\n    var text = (function() {\n      var _i, _len, _results;\n      _results = [];\n      for (_i = 0, _len = sections.length; _i < _len; _i++) {\n        section = sections[_i];\n        _results.push(section.codeText);\n      }\n      return _results;\n    })();\n    var highlighter = config.highlighter || codeMirrorHighlighter;\n    var showdown = config.showdown || new Showdown.converter();\n    highlighter(language, text, function(fragments) {\n      var fragments, i, section, _i, _len;\n      for (i = _i = 0, _len = sections.length; _i < _len; i = ++_i) {\n        section = sections[i];\n        section.codeHtml = fragments[i];\n        section.docsHtml = showdown.makeHtml(section.docsText);\n      }\n      return callback();\n    });\n  }\n  \n  function generateHtml(source, sections, config) {\n    var title = path.basename(source);\n    return config.template({\n      title: title,\n      sections: sections\n    });\n  };\n\n  // ## Helpers & Setup\n  \n  // Mappings between CodeMirror styles and the Pygments styles\n  // defined in `docco.css`.\n  var codeMirrorStyleMap = {\n    \"keyword\": \"k\",\n    \"atom\": \"kc\",\n    \"number\": \"m\",\n    \"comment\": \"c\",\n    \"string\": \"s2\",\n    \"string-2\": \"s2\",\n  };\n  \n  // Each item maps the file extension to the name of the CodeMirror mode\n  // and the symbol that indicates a comment.\n  //\n  // In Docco, this was in a separate JSON file, but we're including\n  // it inline for simplicity.\n  var languages = {\n    \".coffee\" :\n      {\"name\" : \"coffeescript\", \"symbol\" : \"#\"},\n    \".rb\":\n      {\"name\" : \"ruby\", \"symbol\" : \"#\"},\n    \".py\":\n      {\"name\": \"python\", \"symbol\" : \"#\"},\n    \".yaml\":\n      {\"name\" : \"yaml\", \"symbol\" : \"#\"},\n    \".js\":\n      {\"name\" : \"javascript\", \"symbol\" : \"//\"},\n    \".c\":\n      {\"name\" : \"clike\", \"symbol\" : \"//\"},\n    \".h\":\n      {\"name\" : \"clike\", \"symbol\" : \"//\"},\n    \".cpp\":\n      {\"name\" : \"clike\", \"symbol\" : \"//\"},\n    \".php\":\n      {\"name\" : \"php\", \"symbol\" : \"//\"},\n    \".hs\":\n      {\"name\" : \"haskell\", \"symbol\" : \"--\"},\n    \".erl\":\n      {\"name\" : \"erlang\", \"symbol\" : \"%\"},\n    \".hrl\":\n      {\"name\" : \"erlang\", \"symbol\" : \"%\"}\n  };\n  \n  // This is a stand-in for node's <code>[path][]</code> module.\n  //\n  //   [path]: http://nodejs.org/api/path.html\n  var path = {\n    basename: function(p, ext) {\n      var lastPart = p.split('/').slice(-1)[0];\n      if (ext)\n        lastPart = lastPart.slice(0, -(ext.length));\n      return lastPart;\n    },\n    extname: function(filename) {\n      return '.' + filename.split('.').slice(-1)[0];\n    }\n  };\n  \n  // This is a modified version of CodeMirror's [runmode][],\n  // used to leverage CodeMirror's code editing modes for\n  // syntax highlighting.\n  //\n  // If CodeMirror isn't detected or support for the current\n  // language isn't available, this function falls back to\n  // no highlighting.\n  //\n  //   [runmode]: http://codemirror.net/demo/runmode.html\n  function codeMirrorHighlighter(language, fragments, cb) {\n    if (typeof(CodeMirror) == \"undefined\")\n      return nullHighlighter(language, fragments, cb);\n\n    var mode = CodeMirror.getMode(CodeMirror.defaults, {\n      name: language.name\n    });\n    if (mode.name == \"null\")\n      return nullHighlighter(language, fragments, cb);\n      \n    var esc = htmlEscape;\n    var string = fragments.join(\"\\n\" + language.symbol + \"DIVIDER\\n\");\n    var tabSize = CodeMirror.defaults.tabSize;\n    var accum = [], col = 0;\n    var onText = function(text, style) {\n      if (text == \"\\n\") {\n        accum.push(\"\\n\");\n        col = 0;\n        return;\n      }\n      var escaped = \"\";\n      // HTML-escape and replace tabs.\n      for (var pos = 0;;) {\n        var idx = text.indexOf(\"\\t\", pos);\n        if (idx == -1) {\n          escaped += esc(text.slice(pos));\n          col += text.length - pos;\n          break;\n        } else {\n          col += idx - pos;\n          escaped += esc(text.slice(pos, idx));\n          var size = tabSize - col % tabSize;\n          col += size;\n          for (var i = 0; i < size; ++i) escaped += \" \";\n          pos = idx + 1;\n        }\n      }\n\n      if (style) {\n        if (codeMirrorStyleMap[style])\n          style = codeMirrorStyleMap[style] + \" cm-\" + style;\n        else\n          style = \"cm-\" + style;\n        accum.push(\"<span class=\\\"\" + esc(style) +\n                   \"\\\">\" + escaped + \"</span>\");\n      } else\n        accum.push(escaped);\n    };\n    \n    var lines = CodeMirror.splitLines(string),\n        state = CodeMirror.startState(mode);\n    for (var i = 0, e = lines.length; i < e; ++i) {\n      if (i) onText(\"\\n\");\n      var stream = new CodeMirror.StringStream(lines[i]);\n      while (!stream.eol()) {\n        var style = mode.token(stream, state);\n        onText(stream.current(), style, i, stream.start);\n        stream.start = stream.pos;\n      }\n    }\n    \n    fragments = accum.join(\"\")\n      .split('\\n<span class=\"c cm-comment\">' +\n             language.symbol + 'DIVIDER</span>\\n');\n    cb(fragments.map(function(code) { return '<pre>' + code + '</pre>'; }));\n  }\n  \n  // This null syntax highlighter doesn't do any syntax highlighting at\n  // all; it just plops the plain-text source code in a `<pre>` element.\n  function nullHighlighter(language, fragments, cb) {\n    cb(fragments.map(function(code) {\n      return '<pre>' + htmlEscape(code) + '</pre>';\n    }));\n  }\n  \n  // This default template produces an identical DOM to the \n  // <code>[docco.jst][]</code> template used by Docco for single-source\n  // files. It's just easier to inline it than grab it via XHR because it\n  // complicates the use and deployment of this browser-side script.\n  //\n  //   [docco.jst]: https://github.com/jashkenas/docco/blob/master/resources/docco.jst\n  function defaultTemplate(context) {\n    function el(name, attrs, children) {\n      var element = document.createElement(name);\n      Object.keys(attrs).forEach(function(attr) {\n        element.setAttribute(attr, attrs[attr]);\n      });\n      (children || []).forEach(function(child) {\n        if (typeof(child) == \"string\") {\n          var temp = document.createElement(\"div\");\n          temp.innerHTML = child;\n          for (var i = 0; i < temp.childNodes.length; i++)\n            element.appendChild(temp.childNodes[i]);\n        } else\n          element.appendChild(child);\n      });\n      return element;\n    }\n\n    return el(\"div\", {}, [\n      el(\"div\", {id: \"container\"}, [\n        el(\"div\", {id: \"background\"}),\n        el(\"table\", {cellpadding: 0, cellspacing: 0}, [\n          el(\"thead\", {}, [\n            el(\"tr\", {}, [\n              el(\"th\", {\"class\": \"docs\"}, [el(\"h1\", {}, [context.title])]),\n              el(\"th\", {\"class\": \"code\"})\n            ])\n          ]),\n          el(\"tbody\", {}, context.sections.map(function(section, i) {\n            return el(\"tr\", {id: \"section-\" + (i+1)}, [\n              el(\"td\", {\"class\": \"docs\"}, [\n                el(\"div\", {\"class\": \"pilwrap\"}, [\n                  el(\"a\", {\n                    \"class\": \"pilcrow\",\n                    \"href\": \"#section-\" + (i+1)\n                  }, [\"&#182;\"])\n                ]),\n                section.docsHtml\n              ]),\n              el(\"td\", {\"class\": \"code\"}, [section.codeHtml])\n            ]);\n          }))\n        ])\n      ])\n    ]).innerHTML;\n  }\n\n  // This helper inserts the given HTML into the `<body>` element\n  // of the page. It also does a bit of hackery to ensure that\n  // named anchors are automatically navigated to.\n  function insertHtmlIntoBody(html) {\n    document.body.innerHTML = html;\n    // Some browsers, like Firefox and Opera, will automatically\n    // move the page to its old location when the user refreshes\n    // it. We'll give the browser time to do this, and only\n    // scroll the page ourselves if it doesn't.\n    setTimeout(function() {\n      if (location.hash.length > 1 && window.scrollY == 0) {\n        var el = document.getElementById(location.hash.slice(1));\n        if (el)\n          el.scrollIntoView();\n      }\n    }, 0);\n  }\n  \n  // Leverage the DOM to do HTML escaping for us.\n  function htmlEscape(text) {\n    var div = document.createElement('div');\n    div.appendChild(document.createTextNode(text));\n    return div.innerHTML;\n  }\n  \n  // Retrieve the given source file over XHR. If an error occurs\n  // and we're on a `file:` URL, there's a good chance it's\n  // due to browser security restrictions, so provide content\n  // that provides advice.\n  function getSourceFile(filename, cb) {\n    var req = new XMLHttpRequest();\n    req.open(\"GET\", filename);\n    req.onerror = function() {\n      var language = languages[path.extname(filename)];\n      var lines = [\"Couldn't get the source file at `\" + filename + \"`.\"];\n      if (location.protocol == \"file:\")\n        lines = lines.concat([\n          \"\", \"This may be due to browser security restrictions. You may \",\n          \"want to consider opening this file with another browser, or \" +\n          \"using a simple Web server such as `python -m SimpleHTTPServer`.\"\n        ]);\n      cb(language.symbol + lines.join('\\n' + language.symbol));\n    };\n    req.onload = function() { cb(req.responseText); };\n    req.send(null);\n  }\n  \n  // Get the current language we're documenting, based on the extension.\n  function getLanguage(source) {\n    return languages[path.extname(source)];\n  };\n  \n  // Build out the appropriate matchers and delimiters for each language.\n  function processLanguages(languages) {\n    for (var ext in languages) {\n      var l = languages[ext];\n      // Does the line begin with a comment?\n      l.commentMatcher = RegExp(\"^\\\\s*\" + l.symbol + \"\\\\s?\");\n      \n      // Ignore [hashbangs][] and interpolations...\n      //\n      //   [hashbangs]: http://en.wikipedia.org/wiki/Shebang_(Unix\\)\n      l.commentFilter = /(^#![/]|^\\s*#\\{)/;\n    }\n  }\n  \n  processLanguages(languages);\n  \n  // ## Exports\n  //\n  // Information about Brocco, and functions for programmatic usage.\n  return {\n    version: version,\n    document: generateDocumentation,\n    nullHighlighter: nullHighlighter,\n    codeMirrorHighlighter: codeMirrorHighlighter,\n    path: path,\n    languages: languages\n  };\n})();\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/codemirror2/lib/codemirror.css",
    "content": ".CodeMirror {\n  line-height: 1em;\n  font-family: monospace;\n}\n\n.CodeMirror-scroll {\n  overflow: auto;\n  height: 300px;\n  /* This is needed to prevent an IE[67] bug where the scrolled content\n     is visible outside of the scrolling box. */\n  position: relative;\n}\n\n.CodeMirror-gutter {\n  position: absolute; left: 0; top: 0;\n  z-index: 10;\n  background-color: #f7f7f7;\n  border-right: 1px solid #eee;\n  min-width: 2em;\n  height: 100%;\n}\n.CodeMirror-gutter-text {\n  color: #aaa;\n  text-align: right;\n  padding: .4em .2em .4em .4em;\n  white-space: pre !important;\n}\n.CodeMirror-lines {\n  padding: .4em;\n}\n\n.CodeMirror pre {\n  -moz-border-radius: 0;\n  -webkit-border-radius: 0;\n  -o-border-radius: 0;\n  border-radius: 0;\n  border-width: 0; margin: 0; padding: 0; background: transparent;\n  font-family: inherit;\n  font-size: inherit;\n  padding: 0; margin: 0;\n  white-space: pre;\n  word-wrap: normal;\n}\n\n.CodeMirror-wrap pre {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n}\n.CodeMirror-wrap .CodeMirror-scroll {\n  overflow-x: hidden;\n}\n\n.CodeMirror textarea {\n  font-family: inherit !important;\n  font-size: inherit !important;\n}\n\n.CodeMirror-cursor {\n  z-index: 10;\n  position: absolute;\n  visibility: hidden;\n  border-left: 1px solid black !important;\n}\n.CodeMirror-focused .CodeMirror-cursor {\n  visibility: visible;\n}\n\nspan.CodeMirror-selected {\n  background: #ccc !important;\n  color: HighlightText !important;\n}\n.CodeMirror-focused span.CodeMirror-selected {\n  background: Highlight !important;\n}\n\n.CodeMirror-matchingbracket {color: #0f0 !important;}\n.CodeMirror-nonmatchingbracket {color: #f22 !important;}\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/codemirror2/lib/codemirror.js",
    "content": "// CodeMirror v2.18\n\n// All functions that need access to the editor's state live inside\n// the CodeMirror function. Below that, at the bottom of the file,\n// some utilities are defined.\n\n// CodeMirror is the only global var we claim\nvar CodeMirror = (function() {\n  // This is the function that produces an editor instance. It's\n  // closure is used to store the editor state.\n  function CodeMirror(place, givenOptions) {\n    // Determine effective options based on given values and defaults.\n    var options = {}, defaults = CodeMirror.defaults;\n    for (var opt in defaults)\n      if (defaults.hasOwnProperty(opt))\n        options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];\n\n    var targetDocument = options[\"document\"];\n    // The element in which the editor lives.\n    var wrapper = targetDocument.createElement(\"div\");\n    wrapper.className = \"CodeMirror\" + (options.lineWrapping ? \" CodeMirror-wrap\" : \"\");\n    // This mess creates the base DOM structure for the editor.\n    wrapper.innerHTML =\n      '<div style=\"overflow: hidden; position: relative; width: 1px; height: 0px;\">' + // Wraps and hides input textarea\n        '<textarea style=\"position: absolute; width: 10000px;\" wrap=\"off\" ' +\n          'autocorrect=\"off\" autocapitalize=\"off\"></textarea></div>' +\n      '<div class=\"CodeMirror-scroll cm-s-' + options.theme + '\">' +\n        '<div style=\"position: relative\">' + // Set to the height of the text, causes scrolling\n          '<div style=\"position: relative\">' + // Moved around its parent to cover visible view\n            '<div class=\"CodeMirror-gutter\"><div class=\"CodeMirror-gutter-text\"></div></div>' +\n            // Provides positioning relative to (visible) text origin\n            '<div class=\"CodeMirror-lines\"><div style=\"position: relative\">' +\n              '<div style=\"position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden\"></div>' +\n              '<pre class=\"CodeMirror-cursor\">&#160;</pre>' + // Absolutely positioned blinky cursor\n              '<div></div>' + // This DIV contains the actual code\n            '</div></div></div></div></div>';\n    if (place.appendChild) place.appendChild(wrapper); else place(wrapper);\n    // I've never seen more elegant code in my life.\n    var inputDiv = wrapper.firstChild, input = inputDiv.firstChild,\n        scroller = wrapper.lastChild, code = scroller.firstChild,\n        mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,\n        lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,\n        cursor = measure.nextSibling, lineDiv = cursor.nextSibling;\n    if (!webkit) lineSpace.draggable = true;\n    if (options.tabindex != null) input.tabindex = options.tabindex;\n    if (!options.gutter && !options.lineNumbers) gutter.style.display = \"none\";\n\n    // Check for problem with IE innerHTML not working when we have a\n    // P (or similar) parent node.\n    try { stringWidth(\"x\"); }\n    catch (e) {\n      if (e.message.match(/unknown runtime/i))\n        e = new Error(\"A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)\");\n      throw e;\n    }\n\n    // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.\n    var poll = new Delayed(), highlight = new Delayed(), blinker;\n\n    // mode holds a mode API object. doc is the tree of Line objects,\n    // work an array of lines that should be parsed, and history the\n    // undo history (instance of History constructor).\n    var mode, doc = new BranchChunk([new LeafChunk([new Line(\"\")])]), work, focused;\n    loadMode();\n    // The selection. These are always maintained to point at valid\n    // positions. Inverted is used to remember that the user is\n    // selecting bottom-to-top.\n    var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};\n    // Selection-related flags. shiftSelecting obviously tracks\n    // whether the user is holding shift. reducedSelection is a hack\n    // to get around the fact that we can't create inverted\n    // selections. See below.\n    var shiftSelecting, reducedSelection, lastClick, lastDoubleClick, draggingText;\n    // Variables used by startOperation/endOperation to track what\n    // happened during the operation.\n    var updateInput, changes, textChanged, selectionChanged, leaveInputAlone, gutterDirty;\n    // Current visible range (may be bigger than the view window).\n    var displayOffset = 0, showingFrom = 0, showingTo = 0, lastHeight = 0, curKeyId = null;\n    // editing will hold an object describing the things we put in the\n    // textarea, to help figure out whether something changed.\n    // bracketHighlighted is used to remember that a backet has been\n    // marked.\n    var editing, bracketHighlighted;\n    // Tracks the maximum line length so that the horizontal scrollbar\n    // can be kept static when scrolling.\n    var maxLine = \"\", maxWidth;\n\n    // Initialize the content.\n    operation(function(){setValue(options.value || \"\"); updateInput = false;})();\n    var history = new History();\n\n    var slowPollInterval = 2000;\n    // Gecko and Opera Linux do not reliably fire any event when starting an IME compose\n    var alwaysPollForIME = (!win && !mac) && (gecko || window.opera);\n    if (options.pollForIME && alwaysPollForIME) slowPollInterval = 50;\n    function keyMightStartIME(keyCode) {\n      return (win && ((gecko && keyCode == 229) || (window.opera && keyCode == 197))) || (mac && gecko);\n    }\n\n    // Register our event handlers.\n    connect(scroller, \"mousedown\", operation(onMouseDown));\n    connect(scroller, \"dblclick\", operation(onDoubleClick));\n    connect(lineSpace, \"dragstart\", onDragStart);\n    connect(lineSpace, \"selectstart\", e_preventDefault);\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 (!gecko) connect(scroller, \"contextmenu\", onContextMenu);\n    connect(scroller, \"scroll\", function() {\n      updateDisplay([]);\n      if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + \"px\";\n      if (options.onScroll) options.onScroll(instance);\n    });\n    connect(window, \"resize\", function() {updateDisplay(true);});\n    connect(input, \"keyup\", operation(onKeyUp));\n    connect(input, \"input\", function() {fastPoll(curKeyId);});\n    connect(input, \"keydown\", operation(onKeyDown));\n    connect(input, \"keypress\", operation(onKeyPress));\n    connect(input, \"focus\", onFocus);\n    connect(input, \"blur\", onBlur);\n\n    connect(scroller, \"dragenter\", e_stop);\n    connect(scroller, \"dragover\", e_stop);\n    connect(scroller, \"drop\", operation(onDrop));\n    connect(scroller, \"paste\", function(){focusInput(); fastPoll();});\n    connect(input, \"paste\", function(){fastPoll();});\n    connect(input, \"cut\", function(){fastPoll();});\n\n    // IE throws unspecified error in certain cases, when\n    // trying to access activeElement before onload\n    var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { }\n    if (hasFocus) setTimeout(onFocus, 20);\n    else onBlur();\n\n    function isLine(l) {return l >= 0 && l < doc.size;}\n    // The instance object that we'll return. Mostly calls out to\n    // local functions in the CodeMirror function. Some do some extra\n    // range checking and/or clipping. operation is used to wrap the\n    // call so that changes it makes are tracked, and the display is\n    // updated afterwards.\n    var instance = wrapper.CodeMirror = {\n      getValue: getValue,\n      setValue: operation(setValue),\n      getSelection: getSelection,\n      replaceSelection: operation(replaceSelection),\n      focus: function(){focusInput(); onFocus(); fastPoll();},\n      setOption: function(option, value) {\n        var oldVal = options[option];\n        options[option] = value;\n        if (option == \"mode\" || option == \"indentUnit\") loadMode();\n        else if (option == \"readOnly\" && value == \"nocursor\") input.blur();\n        else if (option == \"theme\") scroller.className = scroller.className.replace(/cm-s-\\w+/, \"cm-s-\" + value);\n        else if (option == \"lineWrapping\" && oldVal != value) operation(wrappingChanged)();\n        else if (option == \"pollForIME\" && alwaysPollForIME) slowPollInterval = value ? 50 : 2000;\n        if (option == \"lineNumbers\" || option == \"gutter\" || option == \"firstLineNumber\" || option == \"theme\")\n          operation(gutterChanged)();\n      },\n      getOption: function(option) {return options[option];},\n      undo: operation(undo),\n      redo: operation(redo),\n      indentLine: operation(function(n, dir) {\n        if (isLine(n)) indentLine(n, dir == null ? \"smart\" : dir ? \"add\" : \"subtract\");\n      }),\n      historySize: function() {return {undo: history.done.length, redo: history.undone.length};},\n      clearHistory: function() {history = new History();},\n      matchBrackets: operation(function(){matchBrackets(true);}),\n      getTokenAt: operation(function(pos) {\n        pos = clipPos(pos);\n        return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch);\n      }),\n      getStateAfter: function(line) {\n        line = clipLine(line == null ? doc.size - 1: line);\n        return getStateBefore(line + 1);\n      },\n      cursorCoords: function(start){\n        if (start == null) start = sel.inverted;\n        return pageCoords(start ? sel.from : sel.to);\n      },\n      charCoords: function(pos){return pageCoords(clipPos(pos));},\n      coordsChar: function(coords) {\n        var off = eltOffset(lineSpace);\n        return coordsChar(coords.x - off.left, coords.y - off.top);\n      },\n      getSearchCursor: function(query, pos, caseFold) {return new SearchCursor(query, pos, caseFold);},\n      markText: operation(markText),\n      setBookmark: setBookmark,\n      setMarker: operation(addGutterMarker),\n      clearMarker: operation(removeGutterMarker),\n      setLineClass: operation(setLineClass),\n      hideLine: operation(function(h) {return setLineHidden(h, true);}),\n      showLine: operation(function(h) {return setLineHidden(h, false);}),\n      lineInfo: lineInfo,\n      addWidget: function(pos, node, scroll, vert, horiz) {\n        pos = localCoords(clipPos(pos));\n        var top = pos.yBot, left = pos.x;\n        node.style.position = \"absolute\";\n        code.appendChild(node);\n        if (vert == \"over\") top = pos.y;\n        else if (vert == \"near\") {\n          var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),\n              hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();\n          if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)\n            top = pos.y - node.offsetHeight;\n          if (left + node.offsetWidth > hspace)\n            left = hspace - node.offsetWidth;\n        }\n        node.style.top = (top + paddingTop()) + \"px\";\n        node.style.left = node.style.right = \"\";\n        if (horiz == \"right\") {\n          left = code.clientWidth - node.offsetWidth;\n          node.style.right = \"0px\";\n        } else {\n          if (horiz == \"left\") left = 0;\n          else if (horiz == \"middle\") left = (code.clientWidth - node.offsetWidth) / 2;\n          node.style.left = (left + paddingLeft()) + \"px\";\n        }\n        if (scroll)\n          scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);\n      },\n\n      lineCount: function() {return doc.size;},\n      getCursor: function(start) {\n        if (start == null) start = sel.inverted;\n        return copyPos(start ? sel.from : sel.to);\n      },\n      somethingSelected: function() {return !posEq(sel.from, sel.to);},\n      setCursor: operation(function(line, ch) {\n        if (ch == null && typeof line.line == \"number\") setCursor(line.line, line.ch);\n        else setCursor(line, ch);\n      }),\n      setSelection: operation(function(from, to) {setSelection(clipPos(from), clipPos(to || from));}),\n      getLine: function(line) {if (isLine(line)) return getLine(line).text;},\n      setLine: operation(function(line, text) {\n        if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length});\n      }),\n      removeLine: operation(function(line) {\n        if (isLine(line)) replaceRange(\"\", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));\n      }),\n      replaceRange: operation(replaceRange),\n      getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},\n\n      coordsFromIndex: function(off) {        \n        var lineNo = 0, ch;\n        doc.iter(0, doc.size, 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({line: lineNo, ch: ch});\n      },\n\n      operation: function(f){return operation(f)();},\n      refresh: function(){updateDisplay(true);},\n      getInputField: function(){return input;},\n      getWrapperElement: function(){return wrapper;},\n      getScrollerElement: function(){return scroller;},\n      getGutterElement: function(){return gutter;}\n    };\n\n    function getLine(n) { return getLineAt(doc, n); }\n    function updateLineHeight(line, height) {\n      gutterDirty = true;\n      var diff = height - line.height;\n      for (var n = line; n; n = n.parent) n.height += diff;\n    }\n\n    function setValue(code) {\n      var top = {line: 0, ch: 0};\n      updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length},\n                  splitLines(code), top, top);\n      updateInput = true;\n    }\n    function getValue(code) {\n      var text = [];\n      doc.iter(0, doc.size, function(line) { text.push(line.text); });\n      return text.join(\"\\n\");\n    }\n\n    function onMouseDown(e) {\n      // Check whether this is a click in a widget\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == code && n != mover) return;\n\n      // See if this is a click in the gutter\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == gutterText) {\n          if (options.onGutterClick)\n            options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e);\n          return e_preventDefault(e);\n        }\n\n      var start = posFromMouse(e);\n\n      switch (e_button(e)) {\n      case 3:\n        if (gecko && !mac) onContextMenu(e);\n        return;\n      case 2:\n        if (start) setCursor(start.line, start.ch, true);\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) == scroller) e_preventDefault(e); return;}\n\n      if (!focused) onFocus();\n\n      var now = +new Date;\n      if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {\n        e_preventDefault(e);\n        setTimeout(focusInput, 20);\n        return selectLine(start.line);\n      } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {\n        lastDoubleClick = {time: now, pos: start};\n        e_preventDefault(e);\n        return selectWordAt(start);\n      } else { lastClick = {time: now, pos: start}; }\n\n      var last = start, going;\n      if (dragAndDrop && !posEq(sel.from, sel.to) &&\n          !posLess(start, sel.from) && !posLess(sel.to, start)) {\n        // Let the drag handler handle this.\n        if (webkit) lineSpace.draggable = true;\n        var up = connect(targetDocument, \"mouseup\", operation(function(e2) {\n          if (webkit) lineSpace.draggable = false;\n          draggingText = false;\n          up();\n          if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {\n            e_preventDefault(e2);\n            setCursor(start.line, start.ch, true);\n            focusInput();\n          }\n        }), true);\n        draggingText = true;\n        return;\n      }\n      e_preventDefault(e);\n      setCursor(start.line, start.ch, true);\n\n      function extend(e) {\n        var cur = posFromMouse(e, true);\n        if (cur && !posEq(cur, last)) {\n          if (!focused) onFocus();\n          last = cur;\n          setSelectionUser(start, cur);\n          updateInput = false;\n          var visible = visibleLines();\n          if (cur.line >= visible.to || cur.line < visible.from)\n            going = setTimeout(operation(function(){extend(e);}), 150);\n        }\n      }\n\n      var move = connect(targetDocument, \"mousemove\", operation(function(e) {\n        clearTimeout(going);\n        e_preventDefault(e);\n        extend(e);\n      }), true);\n      var up = connect(targetDocument, \"mouseup\", operation(function(e) {\n        clearTimeout(going);\n        var cur = posFromMouse(e);\n        if (cur) setSelectionUser(start, cur);\n        e_preventDefault(e);\n        focusInput();\n        updateInput = true;\n        move(); up();\n      }), true);\n    }\n    function onDoubleClick(e) {\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == gutterText) return e_preventDefault(e);\n      var start = posFromMouse(e);\n      if (!start) return;\n      lastDoubleClick = {time: +new Date, pos: start};\n      e_preventDefault(e);\n      selectWordAt(start);\n    }\n    function onDrop(e) {\n      e.preventDefault();\n      var pos = posFromMouse(e, true), files = e.dataTransfer.files;\n      if (!pos || options.readOnly) return;\n      if (files && files.length && window.FileReader && window.File) {\n        function loadFile(file, i) {\n          var reader = new FileReader;\n          reader.onload = function() {\n            text[i] = reader.result;\n            if (++read == n) {\n\t      pos = clipPos(pos);\n\t      operation(function() {\n                var end = replaceRange(text.join(\"\"), pos, pos);\n                setSelectionUser(pos, end);\n              })();\n\t    }\n          };\n          reader.readAsText(file);\n        }\n        var n = files.length, text = Array(n), read = 0;\n        for (var i = 0; i < n; ++i) loadFile(files[i], i);\n      }\n      else {\n        try {\n          var text = e.dataTransfer.getData(\"Text\");\n          if (text) {\n\t    var end = replaceRange(text, pos, pos);\n\t    var curFrom = sel.from, curTo = sel.to;\n\t    setSelectionUser(pos, end);\n            if (draggingText) replaceRange(\"\", curFrom, curTo);\n\t    focusInput();\n\t  }\n        }\n        catch(e){}\n      }\n    }\n    function onDragStart(e) {\n      var txt = getSelection();\n      // This will reset escapeElement\n      htmlEscape(txt);\n      e.dataTransfer.setDragImage(escapeElement, 0, 0);\n      e.dataTransfer.setData(\"Text\", txt);\n    }\n    function onKeyDown(e) {\n      if (!focused) onFocus();\n\n      var code = e.keyCode;\n      // IE does strange things with escape.\n      if (ie && code == 27) { e.returnValue = false; }\n      // Tries to detect ctrl on non-mac, cmd on mac.\n      var mod = (mac ? e.metaKey : e.ctrlKey) && !e.altKey, anyMod = e.ctrlKey || e.altKey || e.metaKey;\n      if (code == 16 || e.shiftKey) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);\n      else shiftSelecting = null;\n      // First give onKeyEvent option a chance to handle this.\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n\n      if (code == 33 || code == 34) {scrollPage(code == 34); return e_preventDefault(e);} // page up/down\n      if (mod && ((code == 36 || code == 35) || // ctrl-home/end\n                  mac && (code == 38 || code == 40))) { // cmd-up/down\n        scrollEnd(code == 36 || code == 38); return e_preventDefault(e);\n      }\n      if (mod && code == 65) {selectAll(); return e_preventDefault(e);} // ctrl-a\n      if (!options.readOnly) {\n        if (!anyMod && code == 13) {return;} // enter\n        if (!anyMod && code == 9 && handleTab(e.shiftKey)) return e_preventDefault(e); // tab\n        if (mod && code == 90) {undo(); return e_preventDefault(e);} // ctrl-z\n        if (mod && ((e.shiftKey && code == 90) || code == 89)) {redo(); return e_preventDefault(e);} // ctrl-shift-z, ctrl-y\n      }\n      if (code == 36) { if (options.smartHome) { smartHome(); return e_preventDefault(e); } }\n\n      // Key id to use in the movementKeys map. We also pass it to\n      // fastPoll in order to 'self learn'. We need this because\n      // reducedSelection, the hack where we collapse the selection to\n      // its start when it is inverted and a movement key is pressed\n      // (and later restore it again), shouldn't be used for\n      // non-movement keys.\n      curKeyId = (mod ? \"c\" : \"\") + (e.altKey ? \"a\" : \"\") + code;\n      if (sel.inverted && movementKeys[curKeyId] === true) {\n        var range = selRange(input);\n        if (range) {\n          reducedSelection = {anchor: range.start};\n          setSelRange(input, range.start, range.start);\n        }\n      }\n      // Don't save the key as a movementkey unless it had a modifier\n      if (!mod && !e.altKey) curKeyId = null;\n      fastPoll(curKeyId);\n\n      if (options.pollForIME && keyMightStartIME(code)) slowPollInterval = 50;\n    }\n    function onKeyUp(e) {\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n      if (reducedSelection) {\n        reducedSelection = null;\n        updateInput = true;\n      }\n      if (e.keyCode == 16) shiftSelecting = null;\n\n      if (slowPollInterval < 2000 && !alwaysPollForIME) slowPollInterval = 2000;\n    }\n    function onKeyPress(e) {\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n      if (options.electricChars && mode.electricChars) {\n        var ch = String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode);\n        if (mode.electricChars.indexOf(ch) > -1)\n          setTimeout(operation(function() {indentLine(sel.to.line, \"smart\");}), 50);\n      }\n      var code = e.keyCode;\n      // Re-stop tab and enter. Necessary on some browsers.\n      if (code == 13) {if (!options.readOnly) handleEnter(); e_preventDefault(e);}\n      else if (!e.ctrlKey && !e.altKey && !e.metaKey && code == 9 && options.tabMode != \"default\") e_preventDefault(e);\n      else fastPoll(curKeyId);\n    }\n\n    function onFocus() {\n      if (options.readOnly == \"nocursor\") return;\n      if (!focused) {\n        if (options.onFocus) options.onFocus(instance);\n        focused = true;\n        if (wrapper.className.search(/\\bCodeMirror-focused\\b/) == -1)\n          wrapper.className += \" CodeMirror-focused\";\n        if (!leaveInputAlone) prepareInput();\n      }\n      slowPoll();\n      restartBlink();\n    }\n    function onBlur() {\n      if (focused) {\n        if (options.onBlur) options.onBlur(instance);\n        focused = false;\n        wrapper.className = wrapper.className.replace(\" CodeMirror-focused\", \"\");\n      }\n      clearInterval(blinker);\n      setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);\n    }\n\n    // Replace the range from from to to by the strings in newText.\n    // Afterwards, set the selection to selFrom, selTo.\n    function updateLines(from, to, newText, selFrom, selTo) {\n      if (history) {\n        var old = [];\n        doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); });\n        history.addChange(from.line, newText.length, old);\n        while (history.done.length > options.undoDepth) history.done.shift();\n      }\n      updateLinesNoUndo(from, to, newText, selFrom, selTo);\n    }\n    function unredoHelper(from, to) {\n      var change = from.pop();\n      if (change) {\n        var replaced = [], end = change.start + change.added;\n        doc.iter(change.start, end, function(line) { replaced.push(line.text); });\n        to.push({start: change.start, added: change.old.length, old: replaced});\n        var pos = clipPos({line: change.start + change.old.length - 1,\n                           ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});\n        updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);\n        updateInput = true;\n      }\n    }\n    function undo() {unredoHelper(history.done, history.undone);}\n    function redo() {unredoHelper(history.undone, history.done);}\n\n    function updateLinesNoUndo(from, to, newText, selFrom, selTo) {\n      var recomputeMaxLength = false, maxLineLength = maxLine.length;\n      if (!options.lineWrapping)\n        doc.iter(from.line, to.line, function(line) {\n          if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}\n        });\n\n      var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line);\n      // First adjust the line structure, taking some care to leave highlighting intact.\n      if (firstLine == lastLine) {\n        if (newText.length == 1)\n          firstLine.replace(from.ch, to.ch, newText[0]);\n        else {\n          lastLine = firstLine.split(to.ch, newText[newText.length-1]);\n          firstLine.replace(from.ch, null, newText[0]);\n          firstLine.fixMarkEnds(lastLine);\n          var added = [];\n          for (var i = 1, e = newText.length - 1; i < e; ++i)\n            added.push(Line.inheritMarks(newText[i], firstLine));\n          added.push(lastLine);\n          doc.insert(from.line + 1, added);\n        }\n      }\n      else if (newText.length == 1) {\n        firstLine.replace(from.ch, null, newText[0]);\n        lastLine.replace(null, to.ch, \"\");\n        firstLine.append(lastLine);\n        doc.remove(from.line + 1, nlines);\n      }\n      else {\n        var added = [];\n        firstLine.replace(from.ch, null, newText[0]);\n        lastLine.replace(null, to.ch, newText[newText.length-1]);\n        firstLine.fixMarkEnds(lastLine);\n        for (var i = 1, e = newText.length - 1; i < e; ++i)\n          added.push(Line.inheritMarks(newText[i], firstLine));\n        if (nlines > 1) doc.remove(from.line + 1, nlines - 1);\n        doc.insert(from.line + 1, added);\n      }\n      if (options.lineWrapping) {\n        var perLine = scroller.clientWidth / charWidth() - 3;\n        doc.iter(from.line, from.line + newText.length, function(line) {\n          if (line.hidden) return;\n          var guess = Math.ceil(line.text.length / perLine) || 1;\n          if (guess != line.height) updateLineHeight(line, guess);\n        });\n      } else {\n        doc.iter(from.line, i + newText.length, function(line) {\n          var l = line.text;\n          if (l.length > maxLineLength) {\n            maxLine = l; maxLineLength = l.length; maxWidth = null;\n            recomputeMaxLength = false;\n          }\n        });\n        if (recomputeMaxLength) {\n          maxLineLength = 0; maxLine = \"\"; maxWidth = null;\n          doc.iter(0, doc.size, function(line) {\n            var l = line.text;\n            if (l.length > maxLineLength) {\n              maxLineLength = l.length; maxLine = l;\n            }\n          });\n        }\n      }\n\n      // Add these lines to the work array, so that they will be\n      // highlighted. Adjust work lines if lines were added/removed.\n      var newWork = [], lendiff = newText.length - nlines - 1;\n      for (var i = 0, l = work.length; i < l; ++i) {\n        var task = work[i];\n        if (task < from.line) newWork.push(task);\n        else if (task > to.line) newWork.push(task + lendiff);\n      }\n      var hlEnd = from.line + Math.min(newText.length, 500);\n      highlightLines(from.line, hlEnd);\n      newWork.push(hlEnd);\n      work = newWork;\n      startWorker(100);\n      // Remember that these lines changed, for updating the display\n      changes.push({from: from.line, to: to.line + 1, diff: lendiff});\n      textChanged = {from: from, to: to, text: newText};\n\n      // Update the selection\n      function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}\n      setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line));\n\n      // Make sure the scroll-size div has the correct height.\n      code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + \"px\";\n    }\n\n    function replaceRange(code, from, to) {\n      from = clipPos(from);\n      if (!to) to = from; else to = clipPos(to);\n      code = splitLines(code);\n      function adjustPos(pos) {\n        if (posLess(pos, from)) return pos;\n        if (!posLess(to, pos)) return end;\n        var line = pos.line + code.length - (to.line - from.line) - 1;\n        var ch = pos.ch;\n        if (pos.line == to.line)\n          ch += code[code.length-1].length - (to.ch - (to.line == from.line ? from.ch : 0));\n        return {line: line, ch: ch};\n      }\n      var end;\n      replaceRange1(code, from, to, function(end1) {\n        end = end1;\n        return {from: adjustPos(sel.from), to: adjustPos(sel.to)};\n      });\n      return end;\n    }\n    function replaceSelection(code, collapse) {\n      replaceRange1(splitLines(code), sel.from, sel.to, function(end) {\n        if (collapse == \"end\") return {from: end, to: end};\n        else if (collapse == \"start\") return {from: sel.from, to: sel.from};\n        else return {from: sel.from, to: end};\n      });\n    }\n    function replaceRange1(code, from, to, computeSel) {\n      var endch = code.length == 1 ? code[0].length + from.ch : code[code.length-1].length;\n      var newSel = computeSel({line: from.line + code.length - 1, ch: endch});\n      updateLines(from, to, code, newSel.from, newSel.to);\n    }\n\n    function getRange(from, to) {\n      var l1 = from.line, l2 = to.line;\n      if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);\n      var code = [getLine(l1).text.slice(from.ch)];\n      doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });\n      code.push(getLine(l2).text.slice(0, to.ch));\n      return code.join(\"\\n\");\n    }\n    function getSelection() {\n      return getRange(sel.from, sel.to);\n    }\n\n    var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll\n    function slowPoll() {\n      if (pollingFast) return;\n      poll.set(slowPollInterval, function() {\n        startOperation();\n        readInput();\n        if (focused) slowPoll();\n        endOperation();\n      });\n    }\n    function fastPoll(keyId) {\n      var missed = false;\n      pollingFast = true;\n      function p() {\n        startOperation();\n        var changed = readInput();\n        if (changed && keyId) {\n          if (changed == \"moved\" && movementKeys[keyId] == null) movementKeys[keyId] = true;\n          if (changed == \"changed\") movementKeys[keyId] = false;\n        }\n        if (!changed && !missed) {missed = true; poll.set(80, p);}\n        else {pollingFast = false; slowPoll();}\n        endOperation();\n      }\n      poll.set(20, p);\n    }\n\n    // Inspects the textarea, compares its state (content, selection)\n    // to the data in the editing variable, and updates the editor\n    // content or cursor if something changed.\n    function readInput() {\n      if (leaveInputAlone || !focused) return;\n      var changed = false, text = input.value, sr = selRange(input);\n      if (!sr) return false;\n      var changed = editing.text != text, rs = reducedSelection;\n      var moved = changed || sr.start != editing.start || sr.end != (rs ? editing.start : editing.end);\n      if (!moved && !rs) return false;\n      if (changed) {\n        shiftSelecting = reducedSelection = null;\n        if (options.readOnly) {updateInput = true; return \"changed\";}\n      }\n\n      // Compute selection start and end based on start/end offsets in textarea\n      function computeOffset(n, startLine) {\n        var pos = 0;\n        for (;;) {\n          var found = text.indexOf(\"\\n\", pos);\n          if (found == -1 || (text.charAt(found-1) == \"\\r\" ? found - 1 : found) >= n)\n            return {line: startLine, ch: n - pos};\n          ++startLine;\n          pos = found + 1;\n        }\n      }\n      var from = computeOffset(sr.start, editing.from),\n          to = computeOffset(sr.end, editing.from);\n      // Here we have to take the reducedSelection hack into account,\n      // so that you can, for example, press shift-up at the start of\n      // your selection and have the right thing happen.\n      if (rs) {\n        var head = sr.start == rs.anchor ? to : from;\n        var tail = shiftSelecting ? sel.to : sr.start == rs.anchor ? from : to;\n        if (sel.inverted = posLess(head, tail)) { from = head; to = tail; }\n        else { reducedSelection = null; from = tail; to = head; }\n      }\n\n      // In some cases (cursor on same line as before), we don't have\n      // to update the textarea content at all.\n      if (from.line == to.line && from.line == sel.from.line && from.line == sel.to.line && !shiftSelecting)\n        updateInput = false;\n\n      // Magic mess to extract precise edited range from the changed\n      // string.\n      if (changed) {\n        var start = 0, end = text.length, len = Math.min(end, editing.text.length);\n        var c, line = editing.from, nl = -1;\n        while (start < len && (c = text.charAt(start)) == editing.text.charAt(start)) {\n          ++start;\n          if (c == \"\\n\") {line++; nl = start;}\n        }\n        var ch = nl > -1 ? start - nl : start, endline = editing.to - 1, edend = editing.text.length;\n        for (;;) {\n          c = editing.text.charAt(edend);\n          if (text.charAt(end) != c) {++end; ++edend; break;}\n          if (c == \"\\n\") endline--;\n          if (edend <= start || end <= start) break;\n          --end; --edend;\n        }\n        var nl = editing.text.lastIndexOf(\"\\n\", edend - 1), endch = nl == -1 ? edend : edend - nl - 1;\n        updateLines({line: line, ch: ch}, {line: endline, ch: endch}, splitLines(text.slice(start, end)), from, to);\n        if (line != endline || from.line != line) updateInput = true;\n      }\n      else setSelection(from, to);\n\n      editing.text = text; editing.start = sr.start; editing.end = sr.end;\n      return changed ? \"changed\" : moved ? \"moved\" : false;\n    }\n\n    // Set the textarea content and selection range to match the\n    // editor state.\n    function prepareInput() {\n      var text = [];\n      var from = Math.max(0, sel.from.line - 1), to = Math.min(doc.size, sel.to.line + 2);\n      doc.iter(from, to, function(line) { text.push(line.text); });\n      text = input.value = text.join(lineSep);\n      var startch = sel.from.ch, endch = sel.to.ch;\n      doc.iter(from, sel.from.line, function(line) {\n        startch += lineSep.length + line.text.length;\n      });\n      doc.iter(from, sel.to.line, function(line) {\n        endch += lineSep.length + line.text.length;\n      });\n      editing = {text: text, from: from, to: to, start: startch, end: endch};\n      setSelRange(input, startch, reducedSelection ? startch : endch);\n    }\n    function focusInput() {\n      if (options.readOnly != \"nocursor\") input.focus();\n    }\n\n    function scrollEditorIntoView() {\n      if (!cursor.getBoundingClientRect) return;\n      var rect = cursor.getBoundingClientRect();\n      var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);\n      if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView();\n    }\n    function scrollCursorIntoView() {\n      var cursor = localCoords(sel.inverted ? sel.from : sel.to);\n      var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;\n      return scrollIntoView(x, cursor.y, x, cursor.yBot);\n    }\n    function scrollIntoView(x1, y1, x2, y2) {\n      var pl = paddingLeft(), pt = paddingTop(), lh = textHeight();\n      y1 += pt; y2 += pt; x1 += pl; x2 += pl;\n      var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true;\n      if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1 - 2*lh); scrolled = true;}\n      else if (y2 > screentop + screen) {scroller.scrollTop = y2 + lh - screen; scrolled = true;}\n\n      var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;\n      var gutterw = options.fixedGutter ? gutter.clientWidth : 0;\n      if (x1 < screenleft + gutterw) {\n        if (x1 < 50) x1 = 0;\n        scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);\n        scrolled = true;\n      }\n      else if (x2 > screenw + screenleft) {\n        scroller.scrollLeft = x2 + 10 - screenw;\n        scrolled = true;\n        if (x2 > code.clientWidth) result = false;\n      }\n      if (scrolled && options.onScroll) options.onScroll(instance);\n      return result;\n    }\n\n    function visibleLines() {\n      var lh = textHeight(), top = scroller.scrollTop - paddingTop();\n      var from_height = Math.max(0, Math.floor(top / lh));\n      var to_height = Math.ceil((top + scroller.clientHeight) / lh);\n      return {from: lineAtHeight(doc, from_height),\n              to: lineAtHeight(doc, to_height)};\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 updateDisplay(changes) {\n      if (!scroller.clientWidth) {\n        showingFrom = showingTo = displayOffset = 0;\n        return;\n      }\n      // Compute the new visible window\n      var visible = visibleLines();\n      // Bail out if the visible area is already rendered and nothing changed.\n      if (changes !== true && changes.length == 0 && visible.from >= showingFrom && visible.to <= showingTo) return;\n      var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);\n      if (showingFrom < from && from - showingFrom < 20) from = showingFrom;\n      if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);\n\n      // Create a range of theoretically intact lines, and punch holes\n      // in that using the change info.\n      var intact = changes === true ? [] :\n        computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes);\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.domStart += (from - range.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 (intactLines == to - from) return;\n      intact.sort(function(a, b) {return a.domStart - b.domStart;});\n\n      var th = textHeight(), gutterDisplay = gutter.style.display;\n      lineDiv.style.display = gutter.style.display = \"none\";\n      patchDisplay(from, to, intact);\n      lineDiv.style.display = \"\";\n\n      // Position the mover div to align with the lines it's supposed\n      // to be showing (which will cover the visible display)\n      var different = from != showingFrom || to != showingTo || lastHeight != scroller.clientHeight;\n      if (different) lastHeight = scroller.clientHeight;\n      showingFrom = from; showingTo = to;\n      displayOffset = heightAtLine(doc, from);\n      mover.style.top = (displayOffset * th) + \"px\";\n      code.style.height = (doc.height * th + 2 * paddingTop()) + \"px\";\n\n      // Since this is all rather error prone, it is honoured with the\n      // only assertion in the whole file.\n      if (lineDiv.childNodes.length != showingTo - showingFrom)\n        throw new Error(\"BAD PATCH! \" + JSON.stringify(intact) + \" size=\" + (showingTo - showingFrom) +\n                        \" nodes=\" + lineDiv.childNodes.length);\n\n      if (options.lineWrapping) {\n        maxWidth = scroller.clientWidth;\n        var curNode = lineDiv.firstChild;\n        doc.iter(showingFrom, showingTo, function(line) {\n          if (!line.hidden) {\n            var height = Math.round(curNode.offsetHeight / th) || 1;\n            if (line.height != height) {updateLineHeight(line, height); gutterDirty = true;}\n          }\n          curNode = curNode.nextSibling;\n        });\n      } else {\n        if (maxWidth == null) maxWidth = stringWidth(maxLine);\n        if (maxWidth > scroller.clientWidth) {\n          lineSpace.style.width = maxWidth + \"px\";\n          // Needed to prevent odd wrapping/hiding of widgets placed in here.\n          code.style.width = \"\";\n          code.style.width = scroller.scrollWidth + \"px\";\n        } else {\n          lineSpace.style.width = code.style.width = \"\";\n        }\n      }\n      gutter.style.display = gutterDisplay;\n      if (different || gutterDirty) updateGutter();\n      updateCursor();\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                          domStart: range.domStart});\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, domStart: range.domStart});\n            if (change.to < range.to)\n              intact2.push({from: change.to + diff, to: range.to + diff,\n                            domStart: range.domStart + (change.to - range.from)});\n          }\n        }\n        intact = intact2;\n      }\n      return intact;\n    }\n\n    function patchDisplay(from, to, intact) {\n      // The first pass removes the DOM nodes that aren't intact.\n      if (!intact.length) lineDiv.innerHTML = \"\";\n      else {\n        function killNode(node) {\n          var tmp = node.nextSibling;\n          node.parentNode.removeChild(node);\n          return tmp;\n        }\n        var domPos = 0, curNode = lineDiv.firstChild, n;\n        for (var i = 0; i < intact.length; ++i) {\n          var cur = intact[i];\n          while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;}\n          for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;}\n        }\n        while (curNode) curNode = killNode(curNode);\n      }\n      // This pass fills in the lines that actually changed.\n      var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;\n      var sfrom = sel.from.line, sto = sel.to.line, inSel = sfrom < from && sto >= from;\n      var scratch = targetDocument.createElement(\"div\"), newElt;\n      doc.iter(from, to, function(line) {\n        var ch1 = null, ch2 = null;\n        if (inSel) {\n          ch1 = 0;\n          if (sto == j) {inSel = false; ch2 = sel.to.ch;}\n        } else if (sfrom == j) {\n          if (sto == j) {ch1 = sel.from.ch; ch2 = sel.to.ch;}\n          else {inSel = true; ch1 = sel.from.ch;}\n        }\n        if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();\n        if (!nextIntact || nextIntact.from > j) {\n          if (line.hidden) scratch.innerHTML = \"<pre></pre>\";\n          else scratch.innerHTML = line.getHTML(ch1, ch2, true);\n          lineDiv.insertBefore(scratch.firstChild, curNode);\n        } else {\n          curNode = curNode.nextSibling;\n        }\n        ++j;\n      });\n    }\n\n    function updateGutter() {\n      if (!options.gutter && !options.lineNumbers) return;\n      var hText = mover.offsetHeight, hEditor = scroller.clientHeight;\n      gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + \"px\";\n      var html = [], i = showingFrom;\n      doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {\n        if (line.hidden) {\n          html.push(\"<pre></pre>\");\n        } else {\n          var marker = line.gutterMarker;\n          var text = options.lineNumbers ? i + options.firstLineNumber : null;\n          if (marker && marker.text)\n            text = marker.text.replace(\"%N%\", text != null ? text : \"\");\n          else if (text == null)\n            text = \"\\u00a0\";\n          html.push((marker && marker.style ? '<pre class=\"' + marker.style + '\">' : \"<pre>\"), text);\n          for (var j = 1; j < line.height; ++j) html.push(\"<br>&nbsp;\");\n          html.push(\"</pre>\");\n        }\n        ++i;\n      });\n      gutter.style.display = \"none\";\n      gutterText.innerHTML = html.join(\"\");\n      var minwidth = String(doc.size).length, firstNode = gutterText.firstChild, val = eltText(firstNode), pad = \"\";\n      while (val.length + pad.length < minwidth) pad += \"\\u00a0\";\n      if (pad) firstNode.insertBefore(targetDocument.createTextNode(pad), firstNode.firstChild);\n      gutter.style.display = \"\";\n      lineSpace.style.marginLeft = gutter.offsetWidth + \"px\";\n      gutterDirty = false;\n    }\n    function updateCursor() {\n      var head = sel.inverted ? sel.from : sel.to, lh = textHeight();\n      var pos = localCoords(head, true);\n      var globalY = pos.y + displayOffset * textHeight();\n      inputDiv.style.top = Math.max(Math.min(globalY, scroller.offsetHeight), 0) + \"px\";\n      inputDiv.style.left = (pos.x - scroller.scrollLeft) + \"px\";\n      if (posEq(sel.from, sel.to)) {\n        cursor.style.top = pos.y + \"px\";\n        cursor.style.left = (options.lineWrapping ? Math.min(pos.x, lineSpace.offsetWidth) : pos.x) + \"px\";\n        cursor.style.display = \"\";\n      }\n      else cursor.style.display = \"none\";\n    }\n\n    function setSelectionUser(from, to) {\n      var sh = shiftSelecting && clipPos(shiftSelecting);\n      if (sh) {\n        if (posLess(sh, from)) from = sh;\n        else if (posLess(to, sh)) to = sh;\n      }\n      setSelection(from, to);\n    }\n    // Update the selection. Last two args are only used by\n    // updateLines, since they have to be expressed in the line\n    // numbers before the update.\n    function setSelection(from, to, oldFrom, oldTo) {\n      if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;}\n      if (posEq(sel.from, from) && posEq(sel.to, to)) return;\n      if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}\n\n      // Skip over hidden lines.\n      if (from.line != oldFrom) from = skipHidden(from, oldFrom, sel.from.ch);\n      if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);\n\n      if (posEq(from, to)) sel.inverted = false;\n      else if (posEq(from, sel.to)) sel.inverted = false;\n      else if (posEq(to, sel.from)) sel.inverted = true;\n\n      // Some ugly logic used to only mark the lines that actually did\n      // see a change in selection as changed, rather than the whole\n      // selected range.\n      if (posEq(from, to)) {\n        if (!posEq(sel.from, sel.to))\n          changes.push({from: oldFrom, to: oldTo + 1});\n      }\n      else if (posEq(sel.from, sel.to)) {\n        changes.push({from: from.line, to: to.line + 1});\n      }\n      else {\n        if (!posEq(from, sel.from)) {\n          if (from.line < oldFrom)\n            changes.push({from: from.line, to: Math.min(to.line, oldFrom) + 1});\n          else\n            changes.push({from: oldFrom, to: Math.min(oldTo, from.line) + 1});\n        }\n        if (!posEq(to, sel.to)) {\n          if (to.line < oldTo)\n            changes.push({from: Math.max(oldFrom, from.line), to: oldTo + 1});\n          else\n            changes.push({from: Math.max(from.line, oldTo), to: to.line + 1});\n        }\n      }\n      sel.from = from; sel.to = to;\n      selectionChanged = true;\n    }\n    function skipHidden(pos, oldLine, oldCh) {\n      function getNonHidden(dir) {\n        var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1;\n        while (lNo != end) {\n          var line = getLine(lNo);\n          if (!line.hidden) {\n            var ch = pos.ch;\n            if (ch > oldCh || ch > line.text.length) ch = line.text.length;\n            return {line: lNo, ch: ch};\n          }\n          lNo += dir;\n        }\n      }\n      var line = getLine(pos.line);\n      if (!line.hidden) return pos;\n      if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);\n      else return getNonHidden(-1) || getNonHidden(1);\n    }\n    function setCursor(line, ch, user) {\n      var pos = clipPos({line: line, ch: ch || 0});\n      (user ? setSelectionUser : setSelection)(pos, pos);\n    }\n\n    function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));}\n    function clipPos(pos) {\n      if (pos.line < 0) return {line: 0, ch: 0};\n      if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length};\n      var ch = pos.ch, linelen = getLine(pos.line).text.length;\n      if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};\n      else if (ch < 0) return {line: pos.line, ch: 0};\n      else return pos;\n    }\n\n    function scrollPage(down) {\n      var linesPerPage = Math.floor(scroller.clientHeight / textHeight()), head = sel.inverted ? sel.from : sel.to;\n      var target = heightAtLine(doc, head.line) + (Math.max(linesPerPage - 1, 1) * (down ? 1 : -1));\n      setCursor(lineAtHeight(doc, target), head.ch, true);\n    }\n    function scrollEnd(top) {\n      var pos = top ? {line: 0, ch: 0} : {line: doc.size - 1, ch: getLine(doc.size-1).text.length};\n      setSelectionUser(pos, pos);\n    }\n    function selectAll() {\n      var endLine = doc.size - 1;\n      setSelection({line: 0, ch: 0}, {line: endLine, ch: getLine(endLine).text.length});\n    }\n    function selectWordAt(pos) {\n      var line = getLine(pos.line).text;\n      var start = pos.ch, end = pos.ch;\n      while (start > 0 && /\\w/.test(line.charAt(start - 1))) --start;\n      while (end < line.length && /\\w/.test(line.charAt(end))) ++end;\n      setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});\n    }\n    function selectLine(line) {\n      setSelectionUser({line: line, ch: 0}, {line: line, ch: getLine(line).text.length});\n    }\n    function handleEnter() {\n      replaceSelection(\"\\n\", \"end\");\n      if (options.enterMode != \"flat\")\n        indentLine(sel.from.line, options.enterMode == \"keep\" ? \"prev\" : \"smart\");\n    }\n    function handleTab(shift) {\n      function indentSelected(mode) {\n        if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);\n        var e = sel.to.line - (sel.to.ch ? 0 : 1);\n        for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);\n      }\n      shiftSelecting = null;\n      switch (options.tabMode) {\n      case \"default\":\n        return false;\n      case \"indent\":\n        indentSelected(\"smart\");\n        break;\n      case \"classic\":\n        if (posEq(sel.from, sel.to)) {\n          if (shift) indentLine(sel.from.line, \"smart\");\n          else replaceSelection(\"\\t\", \"end\");\n          break;\n        }\n      case \"shift\":\n        indentSelected(shift ? \"subtract\" : \"add\");\n        break;\n      }\n      return true;\n    }\n    function smartHome() {\n      var firstNonWS = Math.max(0, getLine(sel.from.line).text.search(/\\S/));\n      setCursor(sel.from.line, sel.from.ch <= firstNonWS && sel.from.ch ? 0 : firstNonWS, true);\n    }\n\n    function indentLine(n, how) {\n      if (how == \"smart\") {\n        if (!mode.indent) how = \"prev\";\n        else var state = getStateBefore(n);\n      }\n\n      var line = getLine(n), curSpace = line.indentation(), curSpaceString = line.text.match(/^\\s*/)[0], indentation;\n      if (how == \"prev\") {\n        if (n) indentation = getLine(n-1).indentation();\n        else indentation = 0;\n      }\n      else if (how == \"smart\") indentation = mode.indent(state, line.text.slice(curSpaceString.length));\n      else if (how == \"add\") indentation = curSpace + options.indentUnit;\n      else if (how == \"subtract\") indentation = curSpace - options.indentUnit;\n      indentation = Math.max(0, indentation);\n      var diff = indentation - curSpace;\n\n      if (!diff) {\n        if (sel.from.line != n && sel.to.line != n) return;\n        var indentString = curSpaceString;\n      }\n      else {\n        var indentString = \"\", pos = 0;\n        if (options.indentWithTabs)\n          for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += \"\\t\";}\n        while (pos < indentation) {++pos; indentString += \" \";}\n      }\n\n      replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});\n    }\n\n    function loadMode() {\n      mode = CodeMirror.getMode(options, options.mode);\n      doc.iter(0, doc.size, function(line) { line.stateAfter = null; });\n      work = [0];\n      startWorker();\n    }\n    function gutterChanged() {\n      var visible = options.gutter || options.lineNumbers;\n      gutter.style.display = visible ? \"\" : \"none\";\n      if (visible) gutterDirty = true;\n      else lineDiv.parentNode.style.marginLeft = 0;\n    }\n    function wrappingChanged(from, to) {\n      if (options.lineWrapping) {\n        wrapper.className += \" CodeMirror-wrap\";\n        var perLine = scroller.clientWidth / charWidth() - 3;\n        doc.iter(0, doc.size, function(line) {\n          if (line.hidden) return;\n          var guess = Math.ceil(line.text.length / perLine) || 1;\n          if (guess != 1) updateLineHeight(line, guess);\n        });\n        lineSpace.style.width = code.style.width = \"\";\n      } else {\n        wrapper.className = wrapper.className.replace(\" CodeMirror-wrap\", \"\");\n        maxWidth = null; maxLine = \"\";\n        doc.iter(0, doc.size, function(line) {\n          if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);\n          if (line.text.length > maxLine.length) maxLine = line.text;\n        });\n      }\n      changes.push({from: 0, to: doc.size});\n    }\n\n    function TextMarker() { this.set = []; }\n    TextMarker.prototype.clear = operation(function() {\n      for (var i = 0, e = this.set.length; i < e; ++i) {\n        var mk = this.set[i].marked;\n        if (!mk) continue;\n        for (var j = 0; j < mk.length; ++j)\n          if (mk[j].set == this.set) mk.splice(j--, 1);\n      }\n      // We don't know the exact lines that changed. Refreshing is\n      // cheaper than finding them.\n      changes.push({from: 0, to: doc.size});\n    });\n    TextMarker.prototype.find = function() {\n      var from, to;\n      for (var i = 0, e = this.set.length; i < e; ++i) {\n        var line = this.set[i], mk = line.marked;\n        for (var j = 0; j < mk.length; ++j) {\n          var mark = mk[j];\n          if (mark.set == this.set) {\n            if (mark.from != null || mark.to != null) {\n              var found = lineNo(line);\n              if (found != null) {\n                if (mark.from != null) from = {line: found, ch: mark.from};\n                if (mark.to != null) to = {line: found, ch: mark.to};\n              }\n            }\n          }\n        }\n      }\n      return {from: from, to: to};\n    };\n\n    function markText(from, to, className) {\n      from = clipPos(from); to = clipPos(to);\n      var tm = new TextMarker();\n      function add(line, from, to, className) {\n        mark = getLine(line).addMark(new MarkedText(from, to, className, tm.set));\n      }\n      if (from.line == to.line) add(from.line, from.ch, to.ch, className);\n      else {\n        add(from.line, from.ch, null, className);\n        for (var i = from.line + 1, e = to.line; i < e; ++i)\n          add(i, null, null, className);\n        add(to.line, null, to.ch, className);\n      }\n      changes.push({from: from.line, to: to.line + 1});\n      return tm;\n    }\n\n    function setBookmark(pos) {\n      pos = clipPos(pos);\n      var bm = new Bookmark(pos.ch);\n      getLine(pos.line).addMark(bm);\n      return bm;\n    }\n\n    function addGutterMarker(line, text, className) {\n      if (typeof line == \"number\") line = getLine(clipLine(line));\n      line.gutterMarker = {text: text, style: className};\n      gutterDirty = true;\n      return line;\n    }\n    function removeGutterMarker(line) {\n      if (typeof line == \"number\") line = getLine(clipLine(line));\n      line.gutterMarker = null;\n      gutterDirty = true;\n    }\n\n    function changeLine(handle, op) {\n      var no = handle, line = handle;\n      if (typeof handle == \"number\") line = getLine(clipLine(handle));\n      else no = lineNo(handle);\n      if (no == null) return null;\n      if (op(line, no)) changes.push({from: no, to: no + 1});\n      return line;\n    }\n    function setLineClass(handle, className) {\n      return changeLine(handle, function(line) {\n        if (line.className != className) {\n          line.className = className;\n          return true;\n        }\n      });\n    }\n    function setLineHidden(handle, hidden) {\n      return changeLine(handle, function(line, no) {\n        if (line.hidden != hidden) {\n          line.hidden = hidden;\n          updateLineHeight(line, hidden ? 0 : 1);\n          if (hidden && (sel.from.line == no || sel.to.line == no))\n            setSelection(skipHidden(sel.from, sel.from.line, sel.from.ch),\n                         skipHidden(sel.to, sel.to.line, sel.to.ch));\n          return (gutterDirty = true);\n        }\n      });\n    }\n\n    function lineInfo(line) {\n      if (typeof line == \"number\") {\n        if (!isLine(line)) return null;\n        var n = line;\n        line = getLine(line);\n        if (!line) return null;\n      }\n      else {\n        var n = lineNo(line);\n        if (n == null) return null;\n      }\n      var marker = line.gutterMarker;\n      return {line: n, handle: line, text: line.text, markerText: marker && marker.text,\n              markerClass: marker && marker.style, lineClass: line.className};\n    }\n\n    function stringWidth(str) {\n      measure.innerHTML = \"<pre><span>x</span></pre>\";\n      measure.firstChild.firstChild.firstChild.nodeValue = str;\n      return measure.firstChild.firstChild.offsetWidth || 10;\n    }\n    // These are used to go from pixel positions to character\n    // positions, taking varying character widths into account.\n    function charFromX(line, x) {\n      if (x <= 0) return 0;\n      var lineObj = getLine(line), text = lineObj.text;\n      function getX(len) {\n        measure.innerHTML = \"<pre><span>\" + lineObj.getHTML(null, null, false, len) + \"</span></pre>\";\n        return measure.firstChild.firstChild.offsetWidth;\n      }\n      var from = 0, fromX = 0, to = text.length, toX;\n      // Guess a suitable upper bound for our search.\n      var estimated = Math.min(to, Math.ceil(x / charWidth()));\n      for (;;) {\n        var estX = getX(estimated);\n        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));\n        else {toX = estX; to = estimated; break;}\n      }\n      if (x > toX) return to;\n      // Try to guess a suitable lower bound as well.\n      estimated = Math.floor(to * 0.8); estX = getX(estimated);\n      if (estX < x) {from = estimated; fromX = estX;}\n      // Do a binary search between these bounds.\n      for (;;) {\n        if (to - from <= 1) return (toX - x > x - fromX) ? from : to;\n        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);\n        if (middleX > x) {to = middle; toX = middleX;}\n        else {from = middle; fromX = middleX;}\n      }\n    }\n\n    var tempId = Math.floor(Math.random() * 0xffffff).toString(16);\n    function measureLine(line, ch) {\n      var extra = \"\";\n      // Include extra text at the end to make sure the measured line is wrapped in the right way.\n      if (options.lineWrapping) {\n        var end = line.text.indexOf(\" \", ch + 2);\n        extra = line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0));\n      }\n      measure.innerHTML = \"<pre>\" + line.getHTML(null, null, false, ch) +\n        '<span id=\"CodeMirror-temp-' + tempId + '\">' + (line.text.charAt(ch) || \" \") + \"</span>\" +\n        extra + \"</pre>\";\n      var elt = document.getElementById(\"CodeMirror-temp-\" + tempId);\n      var top = elt.offsetTop, left = elt.offsetLeft;\n      // Older IEs report zero offsets for spans directly after a wrap\n      if (ie && ch && top == 0 && left == 0) {\n        var backup = document.createElement(\"span\");\n        backup.innerHTML = \"x\";\n        elt.parentNode.insertBefore(backup, elt.nextSibling);\n        top = backup.offsetTop;\n      }\n      return {top: top, left: left};\n    }\n    function localCoords(pos, inLineWrap) {\n      var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0));\n      if (pos.ch == 0) x = 0;\n      else {\n        var sp = measureLine(getLine(pos.line), pos.ch);\n        x = sp.left;\n        if (options.lineWrapping) y += Math.max(0, sp.top);\n      }\n      return {x: x, y: y, yBot: y + lh};\n    }\n    // Coords must be lineSpace-local\n    function coordsChar(x, y) {\n      if (y < 0) y = 0;\n      var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th);\n      var lineNo = lineAtHeight(doc, heightPos);\n      if (lineNo >= doc.size) return {line: doc.size - 1, ch: 0};\n      var lineObj = getLine(lineNo), text = lineObj.text;\n      var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0;\n      if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0};\n      function getX(len) {\n        var sp = measureLine(lineObj, len);\n        if (tw) {\n          var off = Math.round(sp.top / th);\n          return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth);\n        }\n        return sp.left;\n      }\n      var from = 0, fromX = 0, to = text.length, toX;\n      // Guess a suitable upper bound for our search.\n      var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw));\n      for (;;) {\n        var estX = getX(estimated);\n        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));\n        else {toX = estX; to = estimated; break;}\n      }\n      if (x > toX) return {line: lineNo, ch: to};\n      // Try to guess a suitable lower bound as well.\n      estimated = Math.floor(to * 0.8); estX = getX(estimated);\n      if (estX < x) {from = estimated; fromX = estX;}\n      // Do a binary search between these bounds.\n      for (;;) {\n        if (to - from <= 1) return {line: lineNo, ch: (toX - x > x - fromX) ? from : to};\n        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);\n        if (middleX > x) {to = middle; toX = middleX;}\n        else {from = middle; fromX = middleX;}\n      }\n    }\n    function pageCoords(pos) {\n      var local = localCoords(pos, true), off = eltOffset(lineSpace);\n      return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};\n    }\n\n    var cachedHeight, cachedFor;\n    function textHeight() {\n      var offsetHeight = lineDiv.offsetHeight;\n      if (offsetHeight == cachedFor) return cachedHeight;\n      cachedFor = offsetHeight;\n      measure.innerHTML = \"<pre>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x<br>x</pre>\";\n      return (cachedHeight = measure.firstChild.offsetHeight / 10 || 1);\n    }\n    var cachedWidth, cachedFor = 0;\n    function charWidth() {\n      if (scroller.clientWidth == cachedFor) return cachedWidth;\n      cachedFor = scroller.clientWidth;\n      return (cachedWidth = stringWidth(\"x\"));\n    }\n    function paddingTop() {return lineSpace.offsetTop;}\n    function paddingLeft() {return lineSpace.offsetLeft;}\n\n    function posFromMouse(e, liberal) {\n      var offW = eltOffset(scroller, true), x, y;\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      // This is a mess of a heuristic to try and determine whether a\n      // scroll-bar was clicked or not, and to return null if one was\n      // (and !liberal).\n      if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight))\n        return null;\n      var offL = eltOffset(lineSpace, true);\n      return coordsChar(x - offL.left, y - offL.top);\n    }\n    function onContextMenu(e) {\n      var pos = posFromMouse(e);\n      if (!pos || window.opera) return; // Opera is difficult.\n      if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))\n        operation(setCursor)(pos.line, pos.ch);\n\n      var oldCSS = input.style.cssText;\n      inputDiv.style.position = \"absolute\";\n      input.style.cssText = \"position: fixed; width: 30px; height: 30px; top: \" + (e.clientY - 5) +\n        \"px; left: \" + (e.clientX - 5) + \"px; z-index: 1000; background: white; \" +\n        \"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);\";\n      leaveInputAlone = true;\n      var val = input.value = getSelection();\n      focusInput();\n      setSelRange(input, 0, input.value.length);\n      function rehide() {\n        var newVal = splitLines(input.value).join(\"\\n\");\n        if (newVal != val) operation(replaceSelection)(newVal, \"end\");\n        inputDiv.style.position = \"relative\";\n        input.style.cssText = oldCSS;\n        leaveInputAlone = false;\n        prepareInput();\n        slowPoll();\n      }\n\n      if (gecko) {\n        e_stop(e);\n        var mouseup = connect(window, \"mouseup\", function() {\n          mouseup();\n          setTimeout(rehide, 20);\n        }, true);\n      }\n      else {\n        setTimeout(rehide, 50);\n      }\n    }\n\n    // Cursor-blinking\n    function restartBlink() {\n      clearInterval(blinker);\n      var on = true;\n      cursor.style.visibility = \"\";\n      blinker = setInterval(function() {\n        cursor.style.visibility = (on = !on) ? \"\" : \"hidden\";\n      }, 650);\n    }\n\n    var matching = {\"(\": \")>\", \")\": \"(<\", \"[\": \"]>\", \"]\": \"[<\", \"{\": \"}>\", \"}\": \"{<\"};\n    function matchBrackets(autoclear) {\n      var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1;\n      var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];\n      if (!match) return;\n      var ch = match.charAt(0), forward = match.charAt(1) == \">\", d = forward ? 1 : -1, st = line.styles;\n      for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2)\n        if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;}\n\n      var stack = [line.text.charAt(pos)], re = /[(){}[\\]]/;\n      function scan(line, from, to) {\n        if (!line.text) return;\n        var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;\n        for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {\n          var text = st[i];\n          if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;}\n          for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {\n            if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {\n              var match = matching[cur];\n              if (match.charAt(1) == \">\" == forward) stack.push(cur);\n              else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};\n              else if (!stack.length) return {pos: pos, match: true};\n            }\n          }\n        }\n      }\n      for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) {\n        var line = getLine(i), first = i == head.line;\n        var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);\n        if (found) break;\n      }\n      if (!found) found = {pos: null, match: false};\n      var style = found.match ? \"CodeMirror-matchingbracket\" : \"CodeMirror-nonmatchingbracket\";\n      var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),\n          two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);\n      var clear = operation(function(){one.clear(); two && two.clear();});\n      if (autoclear) setTimeout(clear, 800);\n      else bracketHighlighted = clear;\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(n) {\n      var minindent, minline;\n      for (var search = n, lim = n - 40; search > lim; --search) {\n        if (search == 0) return 0;\n        var line = getLine(search-1);\n        if (line.stateAfter) return search;\n        var indented = line.indentation();\n        if (minline == null || minindent > indented) {\n          minline = search - 1;\n          minindent = indented;\n        }\n      }\n      return minline;\n    }\n    function getStateBefore(n) {\n      var start = findStartLine(n), state = start && getLine(start-1).stateAfter;\n      if (!state) state = startState(mode);\n      else state = copyState(mode, state);\n      doc.iter(start, n, function(line) {\n        line.highlight(mode, state);\n        line.stateAfter = copyState(mode, state);\n      });\n      if (start < n) changes.push({from: start, to: n});\n      if (n < doc.size && !getLine(n).stateAfter) work.push(n);\n      return state;\n    }\n    function highlightLines(start, end) {\n      var state = getStateBefore(start);\n      doc.iter(start, end, function(line) {\n        line.highlight(mode, state);\n        line.stateAfter = copyState(mode, state);\n      });\n    }\n    function highlightWorker() {\n      var end = +new Date + options.workTime;\n      var foundWork = work.length;\n      while (work.length) {\n        if (!getLine(showingFrom).stateAfter) var task = showingFrom;\n        else var task = work.pop();\n        if (task >= doc.size) continue;\n        var start = findStartLine(task), state = start && getLine(start-1).stateAfter;\n        if (state) state = copyState(mode, state);\n        else state = startState(mode);\n\n        var unchanged = 0, compare = mode.compareStates, realChange = false,\n            i = start, bail = false;\n        doc.iter(i, doc.size, function(line) {\n          var hadState = line.stateAfter;\n          if (+new Date > end) {\n            work.push(i);\n            startWorker(options.workDelay);\n            if (realChange) changes.push({from: task, to: i + 1});\n            return (bail = true);\n          }\n          var changed = line.highlight(mode, state);\n          if (changed) realChange = true;\n          line.stateAfter = copyState(mode, state);\n          if (compare) {\n            if (hadState && compare(hadState, state)) return true;\n          } else {\n            if (changed !== false || !hadState) unchanged = 0;\n            else if (++unchanged > 3) return true;\n          }\n          ++i;\n        });\n        if (bail) return;\n        if (realChange) changes.push({from: task, to: i + 1});\n      }\n      if (foundWork && options.onHighlightComplete)\n        options.onHighlightComplete(instance);\n    }\n    function startWorker(time) {\n      if (!work.length) return;\n      highlight.set(time, operation(highlightWorker));\n    }\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    function startOperation() {\n      updateInput = null; changes = []; textChanged = selectionChanged = false;\n    }\n    function endOperation() {\n      var reScroll = false;\n      if (selectionChanged) reScroll = !scrollCursorIntoView();\n      if (changes.length) updateDisplay(changes);\n      else {\n        if (selectionChanged) updateCursor();\n        if (gutterDirty) updateGutter();\n      }\n      if (reScroll) scrollCursorIntoView();\n      if (selectionChanged) {scrollEditorIntoView(); restartBlink();}\n\n      // updateInput can be set to a boolean value to force/prevent an\n      // update.\n      if (focused && !leaveInputAlone &&\n          (updateInput === true || (updateInput !== false && selectionChanged)))\n        prepareInput();\n\n      if (selectionChanged && options.matchBrackets)\n        setTimeout(operation(function() {\n          if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}\n          matchBrackets(false);\n        }), 20);\n      var tc = textChanged; // textChanged can be reset by cursoractivity callback\n      if (selectionChanged && options.onCursorActivity)\n        options.onCursorActivity(instance);\n      if (tc && options.onChange && instance)\n        options.onChange(instance, tc);\n    }\n    var nestedOperation = 0;\n    function operation(f) {\n      return function() {\n        if (!nestedOperation++) startOperation();\n        try {var result = f.apply(this, arguments);}\n        finally {if (!--nestedOperation) endOperation();}\n        return result;\n      };\n    }\n\n    function SearchCursor(query, pos, caseFold) {\n      this.atOccurrence = false;\n      if (caseFold == null) caseFold = typeof query == \"string\" && query == query.toLowerCase();\n\n      if (pos && typeof pos == \"object\") pos = clipPos(pos);\n      else pos = {line: 0, ch: 0};\n      this.pos = {from: pos, to: pos};\n\n      // The matches method is filled in based on the type of query.\n      // It takes a position and a direction, and returns an object\n      // describing the next occurrence of the query, or null if no\n      // more matches were found.\n      if (typeof query != \"string\") // Regexp match\n        this.matches = function(reverse, pos) {\n          if (reverse) {\n            var line = getLine(pos.line).text.slice(0, pos.ch), match = line.match(query), start = 0;\n            while (match) {\n              var ind = line.indexOf(match[0]);\n              start += ind;\n              line = line.slice(ind + 1);\n              var newmatch = line.match(query);\n              if (newmatch) match = newmatch;\n              else break;\n              start++;\n            }\n          }\n          else {\n            var line = getLine(pos.line).text.slice(pos.ch), match = line.match(query),\n                start = match && pos.ch + line.indexOf(match[0]);\n          }\n          if (match)\n            return {from: {line: pos.line, ch: start},\n                    to: {line: pos.line, ch: start + match[0].length},\n                    match: match};\n        };\n      else { // String query\n        if (caseFold) query = query.toLowerCase();\n        var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};\n        var target = query.split(\"\\n\");\n        // Different methods for single-line and multi-line queries\n        if (target.length == 1)\n          this.matches = function(reverse, pos) {\n            var line = fold(getLine(pos.line).text), len = query.length, match;\n            if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)\n                        : (match = line.indexOf(query, pos.ch)) != -1)\n              return {from: {line: pos.line, ch: match},\n                      to: {line: pos.line, ch: match + len}};\n          };\n        else\n          this.matches = function(reverse, pos) {\n            var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(getLine(ln).text);\n            var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));\n            if (reverse ? offsetA >= pos.ch || offsetA != match.length\n                        : offsetA <= pos.ch || offsetA != line.length - match.length)\n              return;\n            for (;;) {\n              if (reverse ? !ln : ln == doc.size - 1) return;\n              line = fold(getLine(ln += reverse ? -1 : 1).text);\n              match = target[reverse ? --idx : ++idx];\n              if (idx > 0 && idx < target.length - 1) {\n                if (line != match) return;\n                else continue;\n              }\n              var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);\n              if (reverse ? offsetB != line.length - match.length : offsetB != match.length)\n                return;\n              var start = {line: pos.line, ch: offsetA}, end = {line: ln, ch: offsetB};\n              return {from: reverse ? end : start, to: reverse ? start : end};\n            }\n          };\n      }\n    }\n\n    SearchCursor.prototype = {\n      findNext: function() {return this.find(false);},\n      findPrevious: function() {return this.find(true);},\n\n      find: function(reverse) {\n        var self = this, pos = clipPos(reverse ? this.pos.from : this.pos.to);\n        function savePosAndFail(line) {\n          var pos = {line: line, ch: 0};\n          self.pos = {from: pos, to: pos};\n          self.atOccurrence = false;\n          return false;\n        }\n\n        for (;;) {\n          if (this.pos = this.matches(reverse, pos)) {\n            this.atOccurrence = true;\n            return this.pos.match || true;\n          }\n          if (reverse) {\n            if (!pos.line) return savePosAndFail(0);\n            pos = {line: pos.line-1, ch: getLine(pos.line-1).text.length};\n          }\n          else {\n            if (pos.line == doc.size - 1) return savePosAndFail(doc.size);\n            pos = {line: pos.line+1, ch: 0};\n          }\n        }\n      },\n\n      from: function() {if (this.atOccurrence) return copyPos(this.pos.from);},\n      to: function() {if (this.atOccurrence) return copyPos(this.pos.to);},\n\n      replace: function(newText) {\n        var self = this;\n        if (this.atOccurrence)\n          operation(function() {\n            self.pos.to = replaceRange(newText, self.pos.from, self.pos.to);\n          })();\n      }\n    };\n\n    for (var ext in extensions)\n      if (extensions.propertyIsEnumerable(ext) &&\n          !instance.propertyIsEnumerable(ext))\n        instance[ext] = extensions[ext];\n    return instance;\n  } // (end of function CodeMirror)\n\n  // The default configuration options.\n  CodeMirror.defaults = {\n    value: \"\",\n    mode: null,\n    theme: \"default\",\n    indentUnit: 2,\n    indentWithTabs: false,\n    tabMode: \"classic\",\n    enterMode: \"indent\",\n    electricChars: true,\n    onKeyEvent: null,\n    lineWrapping: false,\n    lineNumbers: false,\n    gutter: false,\n    fixedGutter: false,\n    firstLineNumber: 1,\n    readOnly: false,\n    smartHome: true,\n    onChange: null,\n    onCursorActivity: null,\n    onGutterClick: null,\n    onHighlightComplete: null,\n    onFocus: null, onBlur: null, onScroll: null,\n    matchBrackets: false,\n    workTime: 100,\n    workDelay: 200,\n    undoDepth: 40,\n    tabindex: null,\n    pollForIME: false,\n    document: window.document\n  };\n\n  // Known modes, by name and by MIME\n  var modes = {}, mimeModes = {};\n  CodeMirror.defineMode = function(name, mode) {\n    if (!CodeMirror.defaults.mode && name != \"null\") CodeMirror.defaults.mode = name;\n    modes[name] = mode;\n  };\n  CodeMirror.defineMIME = function(mime, spec) {\n    mimeModes[mime] = spec;\n  };\n  CodeMirror.getMode = function(options, spec) {\n    if (typeof spec == \"string\" && mimeModes.hasOwnProperty(spec))\n      spec = mimeModes[spec];\n    if (typeof spec == \"string\")\n      var mname = spec, config = {};\n    else if (spec != null)\n      var mname = spec.name, config = spec;\n    var mfactory = modes[mname];\n    if (!mfactory) {\n      if (window.console) console.warn(\"No mode \" + mname + \" found, falling back to plain text.\");\n      return CodeMirror.getMode(options, \"text/plain\");\n    }\n    return mfactory(options, config || {});\n  };\n  CodeMirror.listModes = function() {\n    var list = [];\n    for (var m in modes)\n      if (modes.propertyIsEnumerable(m)) list.push(m);\n    return list;\n  };\n  CodeMirror.listMIMEs = function() {\n    var list = [];\n    for (var m in mimeModes)\n      if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]});\n    return list;\n  };\n\n  var extensions = {};\n  CodeMirror.defineExtension = function(name, func) {\n    extensions[name] = func;\n  };\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\n    function save() {textarea.value = instance.getValue();}\n    if (textarea.form) {\n      // Deplorable hack to make the submit method do the right thing.\n      var rmSubmit = connect(textarea.form, \"submit\", save, true);\n      if (typeof textarea.form.submit == \"function\") {\n        var realSubmit = textarea.form.submit;\n        function wrappedSubmit() {\n          save();\n          textarea.form.submit = realSubmit;\n          textarea.form.submit();\n          textarea.form.submit = wrappedSubmit;\n        }\n        textarea.form.submit = wrappedSubmit;\n      }\n    }\n\n    textarea.style.display = \"none\";\n    var instance = CodeMirror(function(node) {\n      textarea.parentNode.insertBefore(node, textarea.nextSibling);\n    }, options);\n    instance.save = save;\n    instance.toTextArea = function() {\n      save();\n      textarea.parentNode.removeChild(instance.getWrapperElement());\n      textarea.style.display = \"\";\n      if (textarea.form) {\n        rmSubmit();\n        if (typeof textarea.form.submit == \"function\")\n          textarea.form.submit = realSubmit;\n      }\n    };\n    return instance;\n  };\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  function startState(mode, a1, a2) {\n    return mode.startState ? mode.startState(a1, a2) : true;\n  }\n  CodeMirror.startState = startState;\n\n  // The character stream used by a mode's parser.\n  function StringStream(string) {\n    this.pos = this.start = 0;\n    this.string = string;\n  }\n  StringStream.prototype = {\n    eol: function() {return this.pos >= this.string.length;},\n    sol: function() {return this.pos == 0;},\n    peek: function() {return this.string.charAt(this.pos);},\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() {return countColumn(this.string, this.start);},\n    indentation: function() {return countColumn(this.string);},\n    match: function(pattern, consume, caseInsensitive) {\n      if (typeof pattern == \"string\") {\n        function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}\n        if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {\n          if (consume !== false) this.pos += pattern.length;\n          return true;\n        }\n      }\n      else {\n        var match = this.string.slice(this.pos).match(pattern);\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  };\n  CodeMirror.StringStream = StringStream;\n\n  function MarkedText(from, to, className, set) {\n    this.from = from; this.to = to; this.style = className; this.set = set;\n  }\n  MarkedText.prototype = {\n    attach: function(line) { this.set.push(line); },\n    detach: function(line) {\n      var ix = indexOf(this.set, line);\n      if (ix > -1) this.set.splice(ix, 1);\n    },\n    split: function(pos, lenBefore) {\n      if (this.to <= pos && this.to != null) return null;\n      var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;\n      var to = this.to == null ? null : this.to - pos + lenBefore;\n      return new MarkedText(from, to, this.style, this.set); \n    },\n    dup: function() { return new MarkedText(null, null, this.style, this.set); },\n    clipTo: function(fromOpen, from, toOpen, to, diff) {\n      if (this.from != null && this.from >= from)\n        this.from = Math.max(to, this.from) + diff;\n      if (this.to != null && this.to > from)\n        this.to = to < this.to ? this.to + diff : from;\n      if (fromOpen && to > this.from && (to < this.to || this.to == null))\n        this.from = null;\n      if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))\n        this.to = null;\n    },\n    isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },\n    sameSet: function(x) { return this.set == x.set; }\n  };\n\n  function Bookmark(pos) {\n    this.from = pos; this.to = pos; this.line = null;\n  }\n  Bookmark.prototype = {\n    attach: function(line) { this.line = line; },\n    detach: function(line) { if (this.line == line) this.line = null; },\n    split: function(pos, lenBefore) {\n      if (pos < this.from) {\n        this.from = this.to = (this.from - pos) + lenBefore;\n        return this;\n      }\n    },\n    isDead: function() { return this.from > this.to; },\n    clipTo: function(fromOpen, from, toOpen, to, diff) {\n      if ((fromOpen || from < this.from) && (toOpen || to > this.to)) {\n        this.from = 0; this.to = -1;\n      } else if (this.from > from) {\n        this.from = this.to = Math.max(to, this.from) + diff;\n      }\n    },\n    sameSet: function(x) { return false; },\n    find: function() {\n      if (!this.line || !this.line.parent) return null;\n      return {line: lineNo(this.line), ch: this.from};\n    },\n    clear: function() {\n      if (this.line) {\n        var found = indexOf(this.line.marked, this);\n        if (found != -1) this.line.marked.splice(found, 1);\n        this.line = null;\n      }\n    }\n  };\n\n  // Line objects. These hold state related to a line, including\n  // highlighting info (the styles array).\n  function Line(text, styles) {\n    this.styles = styles || [text, null];\n    this.text = text;\n    this.height = 1;\n    this.marked = this.gutterMarker = this.className = null;\n    this.stateAfter = this.parent = this.hidden = null;\n  }\n  Line.inheritMarks = function(text, orig) {\n    var ln = new Line(text), mk = orig.marked;\n    if (mk) {\n      for (var i = 0; i < mk.length; ++i) {\n        if (mk[i].to == null && mk[i].style) {\n          var newmk = ln.marked || (ln.marked = []), mark = mk[i];\n          var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln);\n        }\n      }\n    }\n    return ln;\n  }\n  Line.prototype = {\n    // Replace a piece of a line, keeping the styles around it intact.\n    replace: function(from, to_, text) {\n      // Reset line class if the whole text was replaced.\n      if (!from && (to_ == null || to_ == this.text.length))\n        this.className = this.gutterMarker = null;\n      var st = [], mk = this.marked, to = to_ == null ? this.text.length : to_;\n      copyStyles(0, from, this.styles, st);\n      if (text) st.push(text, null);\n      copyStyles(to, this.text.length, this.styles, st);\n      this.styles = st;\n      this.text = this.text.slice(0, from) + text + this.text.slice(to);\n      this.stateAfter = null;\n      if (mk) {\n        var diff = text.length - (to - from);\n        for (var i = 0, mark = mk[i]; i < mk.length; ++i) {\n          mark.clipTo(from == null, from || 0, to_ == null, to, diff);\n          if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);}\n        }\n      }\n    },\n    // Split a part off a line, keeping styles and markers intact.\n    split: function(pos, textBefore) {\n      var st = [textBefore, null], mk = this.marked;\n      copyStyles(pos, this.text.length, this.styles, st);\n      var taken = new Line(textBefore + this.text.slice(pos), st);\n      if (mk) {\n        for (var i = 0; i < mk.length; ++i) {\n          var mark = mk[i];\n          var newmark = mark.split(pos, textBefore.length);\n          if (newmark) {\n            if (!taken.marked) taken.marked = [];\n            taken.marked.push(newmark); newmark.attach(taken);\n          }\n        }\n      }\n      return taken;\n    },\n    append: function(line) {\n      var mylen = this.text.length, mk = line.marked, mymk = this.marked;\n      this.text += line.text;\n      copyStyles(0, line.text.length, line.styles, this.styles);\n      if (mymk) {\n        for (var i = 0; i < mymk.length; ++i)\n          if (mymk[i].to == null) mymk[i].to = mylen;\n      }\n      if (mk && mk.length) {\n        if (!mymk) this.marked = mymk = [];\n        outer: for (var i = 0; i < mk.length; ++i) {\n          var mark = mk[i];\n          if (!mark.from) {\n            for (var j = 0; j < mymk.length; ++j) {\n              var mymark = mymk[j];\n              if (mymark.to == mylen && mymark.sameSet(mark)) {\n                mymark.to = mark.to == null ? null : mark.to + mylen;\n                if (mymark.isDead()) {\n                  mymark.detach(this);\n                  mk.splice(i--, 1);\n                }\n                continue outer;\n              }\n            }\n          }\n          mymk.push(mark);\n          mark.attach(this);\n          mark.from += mylen;\n          if (mark.to != null) mark.to += mylen;\n        }\n      }\n    },\n    fixMarkEnds: function(other) {\n      var mk = this.marked, omk = other.marked;\n      if (!mk) return;\n      for (var i = 0; i < mk.length; ++i) {\n        var mark = mk[i], close = mark.to == null;\n        if (close && omk) {\n          for (var j = 0; j < omk.length; ++j)\n            if (omk[j].sameSet(mark)) {close = false; break;}\n        }\n        if (close) mark.to = this.text.length;\n      }\n    },\n    addMark: function(mark) {\n      mark.attach(this);\n      if (this.marked == null) this.marked = [];\n      this.marked.push(mark);\n      this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);});\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    highlight: function(mode, state) {\n      var stream = new StringStream(this.text), st = this.styles, pos = 0;\n      var changed = false, curWord = st[0], prevWord;\n      if (this.text == \"\" && mode.blankLine) mode.blankLine(state);\n      while (!stream.eol()) {\n        var style = mode.token(stream, state);\n        var substr = this.text.slice(stream.start, stream.pos);\n        stream.start = stream.pos;\n        if (pos && st[pos-1] == style)\n          st[pos-2] += substr;\n        else if (substr) {\n          if (!changed && (st[pos+1] != style || (pos && st[pos-2] != prevWord))) changed = true;\n          st[pos++] = substr; st[pos++] = style;\n          prevWord = curWord; curWord = st[pos];\n        }\n        // Give up when line is ridiculously long\n        if (stream.pos > 5000) {\n          st[pos++] = this.text.slice(stream.pos); st[pos++] = null;\n          break;\n        }\n      }\n      if (st.length != pos) {st.length = pos; changed = true;}\n      if (pos && st[pos-2] != prevWord) changed = true;\n      // Short lines with simple highlights return null, and are\n      // counted as changed by the driver because they are likely to\n      // highlight the same way in various contexts.\n      return changed || (st.length < 5 && this.text.length < 10 ? null : false);\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(mode, state, ch) {\n      var txt = this.text, stream = new StringStream(txt);\n      while (stream.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,\n              state: state};\n    },\n    indentation: function() {return countColumn(this.text);},\n    // Produces an HTML fragment for the line, taking selection,\n    // marking, and highlighting into account.\n    getHTML: function(sfrom, sto, includePre, endAt) {\n      var html = [], first = true;\n      if (includePre)\n        html.push(this.className ? '<pre class=\"' + this.className + '\">': \"<pre>\");\n      function span(text, style) {\n        if (!text) return;\n        // Work around a bug where, in some compat modes, IE ignores leading spaces\n        if (first && ie && text.charAt(0) == \" \") text = \"\\u00a0\" + text.slice(1);\n        first = false;\n        if (style) html.push('<span class=\"', style, '\">', htmlEscape(text), \"</span>\");\n        else html.push(htmlEscape(text));\n      }\n      var st = this.styles, allText = this.text, marked = this.marked;\n      if (sfrom == sto) sfrom = null;\n      var len = allText.length;\n      if (endAt != null) len = Math.min(endAt, len);\n\n      if (!allText && endAt == null)\n        span(\" \", sfrom != null && sto == null ? \"CodeMirror-selected\" : null);\n      else if (!marked && sfrom == null)\n        for (var i = 0, ch = 0; ch < len; i+=2) {\n          var str = st[i], style = st[i+1], l = str.length;\n          if (ch + l > len) str = str.slice(0, len - ch);\n          ch += l;\n          span(str, style && \"cm-\" + style);\n        }\n      else {\n        var pos = 0, i = 0, text = \"\", style, sg = 0;\n        var markpos = -1, mark = null;\n        function nextMark() {\n          if (marked) {\n            markpos += 1;\n            mark = (markpos < marked.length) ? marked[markpos] : null;\n          }\n        }\n        nextMark();\n        while (pos < len) {\n          var upto = len;\n          var extraStyle = \"\";\n          if (sfrom != null) {\n            if (sfrom > pos) upto = sfrom;\n            else if (sto == null || sto > pos) {\n              extraStyle = \" CodeMirror-selected\";\n              if (sto != null) upto = Math.min(upto, sto);\n            }\n          }\n          while (mark && mark.to != null && mark.to <= pos) nextMark();\n          if (mark) {\n            if (mark.from > pos) upto = Math.min(upto, mark.from);\n            else {\n              extraStyle += \" \" + mark.style;\n              if (mark.to != null) upto = Math.min(upto, mark.to);\n            }\n          }\n          for (;;) {\n            var end = pos + text.length;\n            var appliedStyle = style;\n            if (extraStyle) appliedStyle = style ? style + extraStyle : extraStyle;\n            span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);\n            if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}\n            pos = end;\n            text = st[i++]; style = \"cm-\" + st[i++];\n          }\n        }\n        if (sfrom != null && sto == null) span(\" \", \"CodeMirror-selected\");\n      }\n      if (includePre) html.push(\"</pre>\");\n      return html.join(\"\");\n    },\n    cleanUp: function() {\n      this.parent = null;\n      if (this.marked)\n        for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this);\n    }\n  };\n  // Utility used by replace and split above\n  function copyStyles(from, to, source, dest) {\n    for (var i = 0, pos = 0, state = 0; pos < to; i+=2) {\n      var part = source[i], end = pos + part.length;\n      if (state == 0) {\n        if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);\n        if (end >= from) state = 1;\n      }\n      else if (state == 1) {\n        if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);\n        else dest.push(part, source[i+1]);\n      }\n      pos = end;\n    }\n  }\n\n  // Data structure that holds the sequence of lines.\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  LeafChunk.prototype = {\n    chunkSize: function() { return this.lines.length; },\n    remove: function(at, n) {\n      for (var i = at, e = at + n; i < e; ++i) {\n        var line = this.lines[i];\n        line.cleanUp();\n        this.height -= line.height;\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    insertHeight: function(at, lines, height) {\n      this.height += height;\n      this.lines.splice.apply(this.lines, [at, 0].concat(lines));\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  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  BranchChunk.prototype = {\n    chunkSize: function() { return this.size; },\n    remove: 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.remove(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      }\n    },\n    collapse: function(lines) {\n      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);\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.insertHeight(at, lines, height);\n    },\n    insertHeight: 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.insertHeight(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    iter: function(from, to, op) { this.iterN(from, to - from, op); },\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  function getLineAt(chunk, n) {\n    for (;;) {\n      for (var i = 0, e = chunk.children.length; i < e; ++i) {\n        var child = chunk.children[i], sz = child.chunkSize();\n        if (n < sz) { chunk = child; break; }\n        n -= sz;\n      }\n      if (chunk.lines) return chunk.lines[n];\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, e = chunk.children.length; ; ++i) {\n        if (chunk.children[i] == cur) break;\n        no += chunk.children[i].chunkSize();\n      }\n    }\n    return no;\n  }\n  function lineAtHeight(chunk, h) {\n    var n = 0;\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  function heightAtLine(chunk, n) {\n    var h = 0;\n    outer: do {\n      for (var i = 0, e = chunk.children.length; i < e; ++i) {\n        var child = chunk.children[i], sz = child.chunkSize();\n        if (n < sz) { chunk = child; continue outer; }\n        n -= sz;\n        h += child.height;\n      }\n      return h;\n    } while (!chunk.lines);\n    for (var i = 0; i < n; ++i) h += chunk.lines[i].height;\n    return h;\n  }\n\n  // The history object 'chunks' changes that are made close together\n  // and at almost the same time into bigger undoable units.\n  function History() {\n    this.time = 0;\n    this.done = []; this.undone = [];\n  }\n  History.prototype = {\n    addChange: function(start, added, old) {\n      this.undone.length = 0;\n      var time = +new Date, last = this.done[this.done.length - 1];\n      if (time - this.time > 400 || !last ||\n          last.start > start + added || last.start + last.added < start - last.added + last.old.length)\n        this.done.push({start: start, added: added, old: old});\n      else {\n        var oldoff = 0;\n        if (start < last.start) {\n          for (var i = last.start - start - 1; i >= 0; --i)\n            last.old.unshift(old[i]);\n          last.added += last.start - start;\n          last.start = start;\n        }\n        else if (last.start < start) {\n          oldoff = start - last.start;\n          added += oldoff;\n        }\n        for (var i = last.added - oldoff, e = old.length; i < e; ++i)\n          last.old.push(old[i]);\n        if (last.added < added) last.added = added;\n      }\n      this.time = time;\n    }\n  };\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_stop(e) {e_preventDefault(e); e_stopPropagation(e);}\n  function e_target(e) {return e.target || e.srcElement;}\n  function e_button(e) {\n    if (e.which) return e.which;\n    else if (e.button & 1) return 1;\n    else if (e.button & 2) return 3;\n    else if (e.button & 4) return 2;\n  }\n\n  // Event handler registration. If disconnect is true, it'll return a\n  // function that unregisters the handler.\n  function connect(node, type, handler, disconnect) {\n    function wrapHandler(event) {handler(event || window.event);}\n    if (typeof node.addEventListener == \"function\") {\n      node.addEventListener(type, wrapHandler, false);\n      if (disconnect) return function() {node.removeEventListener(type, wrapHandler, false);};\n    }\n    else {\n      node.attachEvent(\"on\" + type, wrapHandler);\n      if (disconnect) return function() {node.detachEvent(\"on\" + type, wrapHandler);};\n    }\n  }\n\n  function Delayed() {this.id = null;}\n  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};\n\n  // Detect drag-and-drop\n  var dragAndDrop = function() {\n    // IE8 has ondragstart and ondrop properties, but doesn't seem to\n    // actually support ondragstart the way it's supposed to work.\n    if (/MSIE [1-8]\\b/.test(navigator.userAgent)) return false;\n    var div = document.createElement('div');\n    return \"draggable\" in div;\n  }();\n\n  var gecko = /gecko\\/\\d{7}/i.test(navigator.userAgent);\n  var ie = /MSIE \\d/.test(navigator.userAgent);\n  var webkit = /WebKit\\//.test(navigator.userAgent);\n\n  var lineSep = \"\\n\";\n  // Feature-detect whether newlines in textareas are converted to \\r\\n\n  (function () {\n    var te = document.createElement(\"textarea\");\n    te.value = \"foo\\nbar\";\n    if (te.value.indexOf(\"\\r\") > -1) lineSep = \"\\r\\n\";\n  }());\n\n  var tabSize = 8;\n  var mac = /Mac/.test(navigator.platform);\n  var win = /Win/.test(navigator.platform);\n  var movementKeys = {};\n  for (var i = 35; i <= 40; ++i)\n    movementKeys[i] = movementKeys[\"c\" + i] = true;\n\n  // Counts the column offset in a string, taking tabs into account.\n  // Used mostly to find indentation.\n  function countColumn(string, end) {\n    if (end == null) {\n      end = string.search(/[^\\s\\u00a0]/);\n      if (end == -1) end = string.length;\n    }\n    for (var i = 0, n = 0; i < end; ++i) {\n      if (string.charAt(i) == \"\\t\") n += tabSize - (n % tabSize);\n      else ++n;\n    }\n    return n;\n  }\n\n  function computedStyle(elt) {\n    if (elt.currentStyle) return elt.currentStyle;\n    return window.getComputedStyle(elt, null);\n  }\n\n  // Find the position of an element by following the offsetParent chain.\n  // If screen==true, it returns screen (rather than page) coordinates.\n  function eltOffset(node, screen) {\n    var bod = node.ownerDocument.body;\n    var x = 0, y = 0, skipBody = false;\n    for (var n = node; n; n = n.offsetParent) {\n      var ol = n.offsetLeft, ot = n.offsetTop;\n      // Firefox reports weird inverted offsets when the body has a border.\n      if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); }\n      else { x += ol, y += ot; }\n      if (screen && computedStyle(n).position == \"fixed\")\n        skipBody = true;\n    }\n    var e = screen && !skipBody ? null : bod;\n    for (var n = node.parentNode; n != e; n = n.parentNode)\n      if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;}\n    return {left: x, top: y};\n  }\n  // Use the faster and saner getBoundingClientRect method when possible.\n  if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) {\n    // Take the parts of bounding client rect that we are interested in so we are able to edit if need be,\n    // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)\n    try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }\n    catch(e) { box = {top: 0, left: 0}; }\n    if (!screen) {\n      // Get the toplevel scroll, working around browser differences.\n      if (window.pageYOffset == null) {\n        var t = document.documentElement || document.body.parentNode;\n        if (t.scrollTop == null) t = document.body;\n        box.top += t.scrollTop; box.left += t.scrollLeft;\n      } else {\n        box.top += window.pageYOffset; box.left += window.pageXOffset;\n      }\n    }\n    return box;\n  };\n\n  // Get a node's text content.\n  function eltText(node) {\n    return node.textContent || node.innerText || node.nodeValue || \"\";\n  }\n\n  // Operations on {line, ch} objects.\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 copyPos(x) {return {line: x.line, ch: x.ch};}\n\n  var escapeElement = document.createElement(\"pre\");\n  function htmlEscape(str) {\n    if (badTextContent) {\n      escapeElement.innerHTML = \"\";\n      escapeElement.appendChild(document.createTextNode(str));\n    } else {\n      escapeElement.textContent = str;\n    }\n    return escapeElement.innerHTML;\n  }\n  var badTextContent = htmlEscape(\"\\t\") != \"\\t\";\n  CodeMirror.htmlEscape = htmlEscape;\n\n  // Used to position the cursor after an undo/redo by finding the\n  // last edited character.\n  function editEnd(from, to) {\n    if (!to) return from ? from.length : 0;\n    if (!from) return to.length;\n    for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)\n      if (from.charAt(i) != to.charAt(j)) break;\n    return j + 1;\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  // See if \"\".split is the broken IE version, if so, provide an\n  // alternative way to split lines.\n  var splitLines, selRange, setSelRange;\n  if (\"\\n\\nb\".split(/\\n/).length != 3)\n    splitLines = function(string) {\n      var pos = 0, nl, result = [];\n      while ((nl = string.indexOf(\"\\n\", pos)) > -1) {\n        result.push(string.slice(pos, string.charAt(nl-1) == \"\\r\" ? nl - 1 : nl));\n        pos = nl + 1;\n      }\n      result.push(string.slice(pos));\n      return result;\n    };\n  else\n    splitLines = function(string){return string.split(/\\r?\\n/);};\n  CodeMirror.splitLines = splitLines;\n\n  // Sane model of finding and setting the selection in a textarea\n  if (window.getSelection) {\n    selRange = function(te) {\n      try {return {start: te.selectionStart, end: te.selectionEnd};}\n      catch(e) {return null;}\n    };\n    if (webkit)\n      // On Safari, selection set with setSelectionRange are in a sort\n      // of limbo wrt their anchor. If you press shift-left in them,\n      // the anchor is put at the end, and the selection expanded to\n      // the left. If you press shift-right, the anchor ends up at the\n      // front. This is not what CodeMirror wants, so it does a\n      // spurious modify() call to get out of limbo.\n      setSelRange = function(te, start, end) {\n        if (start == end)\n          te.setSelectionRange(start, end);\n        else {\n          te.setSelectionRange(start, end - 1);\n          window.getSelection().modify(\"extend\", \"forward\", \"character\");\n        }\n      };\n    else\n      setSelRange = function(te, start, end) {\n        try {te.setSelectionRange(start, end);}\n        catch(e) {} // Fails on Firefox when textarea isn't part of the document\n      };\n  }\n  // IE model. Don't ask.\n  else {\n    selRange = function(te) {\n      try {var range = te.ownerDocument.selection.createRange();}\n      catch(e) {return null;}\n      if (!range || range.parentElement() != te) return null;\n      var val = te.value, len = val.length, localRange = te.createTextRange();\n      localRange.moveToBookmark(range.getBookmark());\n      var endRange = te.createTextRange();\n      endRange.collapse(false);\n\n      if (localRange.compareEndPoints(\"StartToEnd\", endRange) > -1)\n        return {start: len, end: len};\n\n      var start = -localRange.moveStart(\"character\", -len);\n      for (var i = val.indexOf(\"\\r\"); i > -1 && i < start; i = val.indexOf(\"\\r\", i+1), start++) {}\n\n      if (localRange.compareEndPoints(\"EndToEnd\", endRange) > -1)\n        return {start: start, end: len};\n\n      var end = -localRange.moveEnd(\"character\", -len);\n      for (var i = val.indexOf(\"\\r\"); i > -1 && i < end; i = val.indexOf(\"\\r\", i+1), end++) {}\n      return {start: start, end: end};\n    };\n    setSelRange = function(te, start, end) {\n      var range = te.createTextRange();\n      range.collapse(true);\n      var endrange = range.duplicate();\n      var newlines = 0, txt = te.value;\n      for (var pos = txt.indexOf(\"\\n\"); pos > -1 && pos < start; pos = txt.indexOf(\"\\n\", pos + 1))\n        ++newlines;\n      range.move(\"character\", start - newlines);\n      for (; pos > -1 && pos < end; pos = txt.indexOf(\"\\n\", pos + 1))\n        ++newlines;\n      endrange.move(\"character\", end - newlines);\n      range.setEndPoint(\"EndToEnd\", endrange);\n      range.select();\n    };\n  }\n\n  CodeMirror.defineMode(\"null\", function() {\n    return {token: function(stream) {stream.skipToEnd();}};\n  });\n  CodeMirror.defineMIME(\"text/plain\", \"null\");\n\n  return CodeMirror;\n})();\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/codemirror2/mode/css/css.js",
    "content": "CodeMirror.defineMode(\"css\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == \"@\") {stream.eatWhile(/[\\w\\\\\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"#\") {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"atom\", \"hash\");\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,.+>*\\/]/.test(ch)) {\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]]/.test(ch)) {\n      return ret(null, ch);\n    }\n    else {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"variable\", \"variable\");\n    }\n  }\n\n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context == \"rule\") style = \"atom\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = \"number\";\n        else if (!context || context == \"@media{\") style = \"tag\";\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/css\", \"css\");\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/codemirror2/mode/htmlmixed/htmlmixed.js",
    "content": "CodeMirror.defineMode(\"htmlmixed\", function(config, parserConfig) {\n  var htmlMode = CodeMirror.getMode(config, {name: \"xml\", htmlMode: true});\n  var jsMode = CodeMirror.getMode(config, \"javascript\");\n  var cssMode = CodeMirror.getMode(config, \"css\");\n\n  function html(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if (style == \"tag\" && stream.current() == \">\" && state.htmlState.context) {\n      if (/^script$/i.test(state.htmlState.context.tagName)) {\n        state.token = javascript;\n        state.localState = jsMode.startState(htmlMode.indent(state.htmlState, \"\"));\n        state.mode = \"javascript\";\n      }\n      else if (/^style$/i.test(state.htmlState.context.tagName)) {\n        state.token = css;\n        state.localState = cssMode.startState(htmlMode.indent(state.htmlState, \"\"));\n        state.mode = \"css\";\n      }\n    }\n    return style;\n  }\n  function maybeBackup(stream, pat, style) {\n    var cur = stream.current();\n    var close = cur.search(pat);\n    if (close > -1) stream.backUp(cur.length - close);\n    return style;\n  }\n  function javascript(stream, state) {\n    if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n      state.token = html;\n      state.curState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n                       jsMode.token(stream, state.localState));\n  }\n  function css(stream, state) {\n    if (stream.match(/^<\\/\\s*style\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*style\\s*>/,\n                       cssMode.token(stream, state.localState));\n  }\n\n  return {\n    startState: function() {\n      var state = htmlMode.startState();\n      return {token: html, localState: null, mode: \"html\", htmlState: state};\n    },\n\n    copyState: function(state) {\n      if (state.localState)\n        var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);\n      return {token: state.token, localState: local, mode: state.mode,\n              htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.token == html || /^\\s*<\\//.test(textAfter))\n        return htmlMode.indent(state.htmlState, textAfter);\n      else if (state.token == javascript)\n        return jsMode.indent(state.localState, textAfter);\n      else\n        return cssMode.indent(state.localState, textAfter);\n    },\n\n    compareStates: function(a, b) {\n      return htmlMode.compareStates(a.htmlState, b.htmlState);\n    },\n\n    electricChars: \"/{}:\"\n  }\n});\n\nCodeMirror.defineMIME(\"text/html\", \"htmlmixed\");\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/codemirror2/mode/javascript/javascript.js",
    "content": "CodeMirror.defineMode(\"javascript\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var jsonMode = parserConfig.json;\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    return {\n      \"if\": A, \"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,\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    };\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|]/;\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  function nextUntilUnescaped(stream, end) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (next == end && !escaped)\n        return false;\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return escaped;\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\n  function jsTokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, jsTokenString(ch));\n    else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch))\n      return ret(ch);\n    else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    }      \n    else if (/\\d/.test(ch)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    }\n    else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, jsTokenComment);\n      }\n      else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      }\n      else if (state.reAllowed) {\n        nextUntilUnescaped(stream, \"/\");\n        stream.eatWhile(/[gimy]/); // 'y' is \"sticky\" option in Mozilla\n        return ret(\"regexp\", \"string\");\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", null, stream.current());\n      }\n    }\n    else if (ch == \"#\") {\n        stream.skipToEnd();\n        return ret(\"error\", \"error\");\n    }\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", null, stream.current());\n    }\n    else {\n      stream.eatWhile(/[\\w\\$_]/);\n      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n      return known ? ret(known.type, known.style, word) :\n                     ret(\"variable\", \"variable\", word);\n    }\n  }\n\n  function jsTokenString(quote) {\n    return function(stream, state) {\n      if (!nextUntilUnescaped(stream, quote))\n        state.tokenize = jsTokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function jsTokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": 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  }\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    var state = cx.state;\n    if (state.context) {\n      cx.marked = \"def\";\n      for (var v = state.localVars; v; v = v.next)\n        if (v.name == varname) return;\n      state.localVars = {name: varname, next: state.localVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: {name: \"arguments\"}};\n  function pushcontext() {\n    if (!cx.state.context) cx.state.localVars = defaultVars;\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\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;\n      state.lexical = new JSLexical(state.indented, 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 expecting(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) {\n    if (type == \"var\") return cont(pushlex(\"vardef\"), vardef1, 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 == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), expect(\"(\"), pushlex(\")\"), forspec1, expect(\")\"),\n                                      poplex, 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    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"keyword c\") return cont(maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), expression, expect(\")\"), poplex, maybeoperator);\n    if (type == \"operator\") return cont(expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), commasep(expression, \"]\"), poplex, maybeoperator);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(objprop, \"}\"), poplex, maybeoperator);\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n    \n  function maybeoperator(type, value) {\n    if (type == \"operator\" && /\\+\\+|--/.test(value)) return cont(maybeoperator);\n    if (type == \"operator\") return cont(expression);\n    if (type == \";\") return;\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(expression, \")\"), poplex, maybeoperator);\n    if (type == \".\") return cont(property, maybeoperator);\n    if (type == \"[\") return cont(pushlex(\"]\"), expression, expect(\"]\"), poplex, maybeoperator);\n  }\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperator, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type) {\n    if (type == \"variable\") cx.marked = \"property\";\n    if (atomicTypes.hasOwnProperty(type)) return cont(expect(\":\"), expression);\n  }\n  function commasep(what, end) {\n    function proceed(type) {\n      if (type == \",\") return cont(what, proceed);\n      if (type == end) return cont();\n      return cont(expect(end));\n    }\n    return function commaSeparated(type) {\n      if (type == end) return cont();\n      else return pass(what, proceed);\n    };\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function vardef1(type, value) {\n    if (type == \"variable\"){register(value); return cont(vardef2);}\n    return cont();\n  }\n  function vardef2(type, value) {\n    if (value == \"=\") return cont(expression, vardef2);\n    if (type == \",\") return cont(vardef1);\n  }\n  function forspec1(type) {\n    if (type == \"var\") return cont(vardef1, forspec2);\n    if (type == \";\") return pass(forspec2);\n    if (type == \"variable\") return cont(formaybein);\n    return pass(forspec2);\n  }\n  function formaybein(type, value) {\n    if (value == \"in\") return cont(expression);\n    return cont(maybeoperator, forspec2);\n  }\n  function forspec2(type, value) {\n    if (type == \";\") return cont(forspec3);\n    if (value == \"in\") return cont(expression);\n    return cont(expression, expect(\";\"), forspec3);\n  }\n  function forspec3(type) {\n    if (type != \")\") cont(expression);\n  }\n  function functiondef(type, value) {\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (type == \"(\") return cont(pushlex(\")\"), pushcontext, commasep(funarg, \")\"), poplex, statement, popcontext);\n  }\n  function funarg(type, value) {\n    if (type == \"variable\") {register(value); return cont();}\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: jsTokenBase,\n        reAllowed: true,\n        cc: [],\n        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, \"block\", false),\n        localVars: null,\n        context: null,\n        indented: 0\n      };\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      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.reAllowed = type == \"operator\" || type == \"keyword c\" || type.match(/^[\\[{}\\(,;:]$/);\n      return parseJS(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != jsTokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,\n          type = lexical.type, closing = firstChar == type;\n      if (type == \"vardef\") return lexical.indented + 4;\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"stat\" || type == \"form\") return lexical.indented + indentUnit;\n      else if (lexical.info == \"switch\" && !closing)\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  };\n});\n\nCodeMirror.defineMIME(\"text/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/json\", {name: \"javascript\", json: true});\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/codemirror2/mode/xml/xml.js",
    "content": "CodeMirror.defineMode(\"xml\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var Kludges = parserConfig.htmlMode ? {\n    autoSelfClosers: {\"br\": true, \"img\": true, \"hr\": true, \"link\": true, \"input\": true,\n                      \"meta\": true, \"col\": true, \"frame\": true, \"base\": true, \"area\": true},\n    doNotIndent: {\"pre\": true, \"!cdata\": true},\n    allowUnquoted: true\n  } : {autoSelfClosers: {}, doNotIndent: {\"!cdata\": true}, allowUnquoted: false};\n  var alignCDATA = parserConfig.alignCDATA;\n\n  // Return variables for tokenizers\n  var tagName, type;\n\n  function inText(stream, state) {\n    function chain(parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n\n    var ch = stream.next();\n    if (ch == \"<\") {\n      if (stream.eat(\"!\")) {\n        if (stream.eat(\"[\")) {\n          if (stream.match(\"CDATA[\")) return chain(inBlock(\"atom\", \"]]>\"));\n          else return null;\n        }\n        else if (stream.match(\"--\")) return chain(inBlock(\"comment\", \"-->\"));\n        else if (stream.match(\"DOCTYPE\", true, true)) {\n          stream.eatWhile(/[\\w\\._\\-]/);\n          return chain(inBlock(\"meta\", \">\"));\n        }\n        else return null;\n      }\n      else if (stream.eat(\"?\")) {\n        stream.eatWhile(/[\\w\\._\\-]/);\n        state.tokenize = inBlock(\"meta\", \"?>\");\n        return \"meta\";\n      }\n      else {\n        type = stream.eat(\"/\") ? \"closeTag\" : \"openTag\";\n        stream.eatSpace();\n        tagName = \"\";\n        var c;\n        while ((c = stream.eat(/[^\\s\\u00a0=<>\\\"\\'\\/?]/))) tagName += c;\n        state.tokenize = inTag;\n        return \"tag\";\n      }\n    }\n    else if (ch == \"&\") {\n      stream.eatWhile(/[^;]/);\n      stream.eat(\";\");\n      return \"atom\";\n    }\n    else {\n      stream.eatWhile(/[^&<]/);\n      return null;\n    }\n  }\n\n  function inTag(stream, state) {\n    var ch = stream.next();\n    if (ch == \">\" || (ch == \"/\" && stream.eat(\">\"))) {\n      state.tokenize = inText;\n      type = ch == \">\" ? \"endTag\" : \"selfcloseTag\";\n      return \"tag\";\n    }\n    else if (ch == \"=\") {\n      type = \"equals\";\n      return null;\n    }\n    else if (/[\\'\\\"]/.test(ch)) {\n      state.tokenize = inAttribute(ch);\n      return state.tokenize(stream, state);\n    }\n    else {\n      stream.eatWhile(/[^\\s\\u00a0=<>\\\"\\'\\/?]/);\n      return \"word\";\n    }\n  }\n\n  function inAttribute(quote) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.next() == quote) {\n          state.tokenize = inTag;\n          break;\n        }\n      }\n      return \"string\";\n    };\n  }\n\n  function inBlock(style, terminator) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = inText;\n          break;\n        }\n        stream.next();\n      }\n      return style;\n    };\n  }\n\n  var curState, setStyle;\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n\n  function pushContext(tagName, startOfLine) {\n    var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);\n    curState.context = {\n      prev: curState.context,\n      tagName: tagName,\n      indent: curState.indented,\n      startOfLine: startOfLine,\n      noIndent: noIndent\n    };\n  }\n  function popContext() {\n    if (curState.context) curState.context = curState.context.prev;\n  }\n\n  function element(type) {\n    if (type == \"openTag\") {curState.tagName = tagName; return cont(attributes, endtag(curState.startOfLine));}\n    else if (type == \"closeTag\") {\n      var err = false;\n      if (curState.context) {\n        err = curState.context.tagName != tagName;\n      } else {\n        err = true;\n      }\n      if (err) setStyle = \"error\";\n      return cont(endclosetag(err));\n    }\n    else if (type == \"string\") {\n      if (!curState.context || curState.context.name != \"!cdata\") pushContext(\"!cdata\");\n      if (curState.tokenize == inText) popContext();\n      return cont();\n    }\n    else return cont();\n  }\n  function endtag(startOfLine) {\n    return function(type) {\n      if (type == \"selfcloseTag\" ||\n          (type == \"endTag\" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase())))\n        return cont();\n      if (type == \"endTag\") {pushContext(curState.tagName, startOfLine); return cont();}\n      return cont();\n    };\n  }\n  function endclosetag(err) {\n    return function(type) {\n      if (err) setStyle = \"error\";\n      if (type == \"endTag\") { popContext(); return cont(); }\n      setStyle = \"error\";\n      return cont(arguments.callee);\n    }\n  }\n\n  function attributes(type) {\n    if (type == \"word\") {setStyle = \"attribute\"; return cont(attributes);}\n    if (type == \"equals\") return cont(attvalue, attributes);\n    if (type == \"string\") {setStyle = \"error\"; return cont(attributes);}\n    return pass();\n  }\n  function attvalue(type) {\n    if (type == \"word\" && Kludges.allowUnquoted) {setStyle = \"string\"; return cont();}\n    if (type == \"string\") return cont(attvaluemaybe);\n    return pass();\n  }\n  function attvaluemaybe(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    else return pass();\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        state.startOfLine = true;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n\n      setStyle = type = tagName = null;\n      var style = state.tokenize(stream, state);\n      state.type = type;\n      if ((style || type) && style != \"comment\") {\n        curState = state;\n        while (true) {\n          var comb = state.cc.pop() || element;\n          if (comb(type || style)) break;\n        }\n      }\n      state.startOfLine = false;\n      return setStyle || style;\n    },\n\n    indent: function(state, textAfter) {\n      var context = state.context;\n      if (context && context.noIndent) return 0;\n      if (alignCDATA && /<!\\[CDATA\\[/.test(textAfter)) return 0;\n      if (context && /^<\\//.test(textAfter))\n        context = context.prev;\n      while (context && !context.startOfLine)\n        context = context.prev;\n      if (context) return context.indent + indentUnit;\n      else return 0;\n    },\n\n    compareStates: function(a, b) {\n      if (a.indented != b.indented || a.tokenize != b.tokenize) return false;\n      for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {\n        if (!ca || !cb) return ca == cb;\n        if (ca.tagName != cb.tagName) return false;\n      }\n    },\n\n    electricChars: \"/\"\n  };\n});\n\nCodeMirror.defineMIME(\"application/xml\", \"xml\");\nCodeMirror.defineMIME(\"text/html\", {name: \"xml\", htmlMode: true});\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/docco.css",
    "content": "/*--------------------- Layout and Typography ----------------------------*/\nbody {\n  font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;\n  font-size: 15px;\n  line-height: 22px;\n  color: #252519;\n  margin: 0; padding: 0;\n}\na {\n  color: #261a3b;\n}\n  a:visited {\n    color: #261a3b;\n  }\np {\n  margin: 0 0 15px 0;\n}\nh1, h2, h3, h4, h5, h6 {\n  margin: 0px 0 15px 0;\n}\n  h1 {\n    margin-top: 40px;\n  }\nhr {\n    border: 0 none;\n    border-top: 1px solid #e5e5ee;\n    height: 1px;\n    margin: 20px 0;\n}\n#container {\n  position: relative;\n}\n#background {\n  position: fixed;\n  top: 0; left: 525px; right: 0; bottom: 0;\n  background: #f5f5ff;\n  border-left: 1px solid #e5e5ee;\n  z-index: -1;\n}\n#jump_to, #jump_page {\n  background: white;\n  -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;\n  -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;\n  font: 10px Arial;\n  text-transform: uppercase;\n  cursor: pointer;\n  text-align: right;\n}\n#jump_to, #jump_wrapper {\n  position: fixed;\n  right: 0; top: 0;\n  padding: 5px 10px;\n}\n  #jump_wrapper {\n    padding: 0;\n    display: none;\n  }\n    #jump_to:hover #jump_wrapper {\n      display: block;\n    }\n    #jump_page {\n      padding: 5px 0 3px;\n      margin: 0 0 25px 25px;\n    }\n      #jump_page .source {\n        display: block;\n        padding: 5px 10px;\n        text-decoration: none;\n        border-top: 1px solid #eee;\n      }\n        #jump_page .source:hover {\n          background: #f5f5ff;\n        }\n        #jump_page .source:first-child {\n        }\ntable td {\n  border: 0;\n  outline: 0;\n}\n  td.docs, th.docs {\n    max-width: 450px;\n    min-width: 450px;\n    min-height: 5px;\n    padding: 10px 25px 1px 50px;\n    overflow-x: hidden;\n    vertical-align: top;\n    text-align: left;\n  }\n    .docs pre {\n      margin: 15px 0 15px;\n      padding-left: 15px;\n    }\n    .docs p tt, .docs p code {\n      background: #f8f8ff;\n      border: 1px solid #dedede;\n      font-size: 12px;\n      padding: 0 0.2em;\n    }\n    .pilwrap {\n      position: relative;\n    }\n      .pilcrow {\n        font: 12px Arial;\n        text-decoration: none;\n        color: #454545;\n        position: absolute;\n        top: 3px; left: -20px;\n        padding: 1px 2px;\n        opacity: 0;\n        -webkit-transition: opacity 0.2s linear;\n      }\n        td.docs:hover .pilcrow {\n          opacity: 1;\n        }\n  td.code, th.code {\n    padding: 14px 15px 16px 25px;\n    width: 100%;\n    vertical-align: top;\n    background: #f5f5ff;\n    border-left: 1px solid #e5e5ee;\n  }\n    pre, tt, code {\n      font-size: 12px; line-height: 18px;\n      font-family: Menlo, Monaco, Consolas, \"Lucida Console\", monospace;\n      margin: 0; padding: 0;\n    }\n\n\n/*---------------------- Syntax Highlighting -----------------------------*/\ntd.linenos { background-color: #f0f0f0; padding-right: 10px; }\nspan.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\nbody .hll { background-color: #ffffcc }\nbody .c { color: #408080; font-style: italic }  /* Comment */\nbody .err { border: 1px solid #FF0000 }         /* Error */\nbody .k { color: #954121 }                      /* Keyword */\nbody .o { color: #666666 }                      /* Operator */\nbody .cm { color: #408080; font-style: italic } /* Comment.Multiline */\nbody .cp { color: #BC7A00 }                     /* Comment.Preproc */\nbody .c1 { color: #408080; font-style: italic } /* Comment.Single */\nbody .cs { color: #408080; font-style: italic } /* Comment.Special */\nbody .gd { color: #A00000 }                     /* Generic.Deleted */\nbody .ge { font-style: italic }                 /* Generic.Emph */\nbody .gr { color: #FF0000 }                     /* Generic.Error */\nbody .gh { color: #000080; font-weight: bold }  /* Generic.Heading */\nbody .gi { color: #00A000 }                     /* Generic.Inserted */\nbody .go { color: #808080 }                     /* Generic.Output */\nbody .gp { color: #000080; font-weight: bold }  /* Generic.Prompt */\nbody .gs { font-weight: bold }                  /* Generic.Strong */\nbody .gu { color: #800080; font-weight: bold }  /* Generic.Subheading */\nbody .gt { color: #0040D0 }                     /* Generic.Traceback */\nbody .kc { color: #954121 }                     /* Keyword.Constant */\nbody .kd { color: #954121; font-weight: bold }  /* Keyword.Declaration */\nbody .kn { color: #954121; font-weight: bold }  /* Keyword.Namespace */\nbody .kp { color: #954121 }                     /* Keyword.Pseudo */\nbody .kr { color: #954121; font-weight: bold }  /* Keyword.Reserved */\nbody .kt { color: #B00040 }                     /* Keyword.Type */\nbody .m { color: #666666 }                      /* Literal.Number */\nbody .s { color: #219161 }                      /* Literal.String */\nbody .na { color: #7D9029 }                     /* Name.Attribute */\nbody .nb { color: #954121 }                     /* Name.Builtin */\nbody .nc { color: #0000FF; font-weight: bold }  /* Name.Class */\nbody .no { color: #880000 }                     /* Name.Constant */\nbody .nd { color: #AA22FF }                     /* Name.Decorator */\nbody .ni { color: #999999; font-weight: bold }  /* Name.Entity */\nbody .ne { color: #D2413A; font-weight: bold }  /* Name.Exception */\nbody .nf { color: #0000FF }                     /* Name.Function */\nbody .nl { color: #A0A000 }                     /* Name.Label */\nbody .nn { color: #0000FF; font-weight: bold }  /* Name.Namespace */\nbody .nt { color: #954121; font-weight: bold }  /* Name.Tag */\nbody .nv { color: #19469D }                     /* Name.Variable */\nbody .ow { color: #AA22FF; font-weight: bold }  /* Operator.Word */\nbody .w { color: #bbbbbb }                      /* Text.Whitespace */\nbody .mf { color: #666666 }                     /* Literal.Number.Float */\nbody .mh { color: #666666 }                     /* Literal.Number.Hex */\nbody .mi { color: #666666 }                     /* Literal.Number.Integer */\nbody .mo { color: #666666 }                     /* Literal.Number.Oct */\nbody .sb { color: #219161 }                     /* Literal.String.Backtick */\nbody .sc { color: #219161 }                     /* Literal.String.Char */\nbody .sd { color: #219161; font-style: italic } /* Literal.String.Doc */\nbody .s2 { color: #219161 }                     /* Literal.String.Double */\nbody .se { color: #BB6622; font-weight: bold }  /* Literal.String.Escape */\nbody .sh { color: #219161 }                     /* Literal.String.Heredoc */\nbody .si { color: #BB6688; font-weight: bold }  /* Literal.String.Interpol */\nbody .sx { color: #954121 }                     /* Literal.String.Other */\nbody .sr { color: #BB6688 }                     /* Literal.String.Regex */\nbody .s1 { color: #219161 }                     /* Literal.String.Single */\nbody .ss { color: #19469D }                     /* Literal.String.Symbol */\nbody .bp { color: #954121 }                     /* Name.Builtin.Pseudo */\nbody .vc { color: #19469D }                     /* Name.Variable.Class */\nbody .vg { color: #19469D }                     /* Name.Variable.Global */\nbody .vi { color: #19469D }                     /* Name.Variable.Instance */\nbody .il { color: #666666 }                     /* Literal.Number.Integer.Long */"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/jump-to.js",
    "content": "\"use strict\";\n\n// This is a simple add-on to [Brocco][] which provides a Docco-style\n// *Jump To&hellip;* menu at the top of a page, allowing for\n// navigation between different source files.\n//\n// Using this file requires populating the `<body>` of an HTML\n// page with content similar to the following:\n//\n//     <div id=\"container\">\n//       <div id=\"background\"></div>\n//       <div id=\"jump_to\">\n//         Jump To &hellip;\n//         <div id=\"jump_wrapper\">\n//         <div id=\"jump_page\">\n//           <a class=\"source\">path/to/foo.js</a>\n//           <a class=\"source\">path/to/bar.cpp</a>\n//           <!-- ... And so on ... -->\n//         </div>\n//       </div>\n//     </div>\n//\n// Simply including the `jump-to.js` script, preceded by\n// `brocco.js` and its dependencies, will automatically parse\n// all the links inside `#jump_page`, provide a table of\n// contents, and display the appropriate source file.\n// There is no need to write any JavaScript yourself\n// when using this add-on.\n//\n// Viewing specific source files happens through the URL\n// querystring. In the example above, a querystring of `?foo.js` \n// will show the source at `path/to/source/foo.js`, while `?bar.cpp`\n// will show the other file. If nothing is specified in the\n// querystring, then the first source listed (in this case,\n// `foo.js`) will be shown.\n//\n//   [Brocco]: ?brocco.js\n\nBrocco.jumpTo = (function() {\n  var sourceMap = {};\n  var defaultSource;\n  var source = location.search.slice(1);\n  var anchors = document.querySelectorAll(\"#jump_page > a.source\");\n\n  [].slice.call(anchors).forEach(function(a) {\n    var path = a.textContent.trim();\n    var basename = Brocco.path.basename(path);\n    \n    if (!defaultSource)\n      defaultSource = basename;\n    \n    sourceMap[basename] = path;\n    a.setAttribute(\"href\", \"?\" + basename);\n    a.textContent = basename;\n  });\n\n  if (!(source in sourceMap))\n    source = defaultSource;\n\n  document.title = source;\n  Brocco.document(sourceMap[source], function(html) {\n    var temp = document.createElement(\"div\");\n    temp.innerHTML = html;\n    var table = temp.querySelector(\"table\");\n    document.getElementById(\"container\").appendChild(table);\n  });\n})();\n"
  },
  {
    "path": "site/examples/friendlycode/slowparse/vendor/showdown.js",
    "content": "//\n// showdown.js -- A javascript port of Markdown.\n//\n// Copyright (c) 2007 John Fraser.\n//\n// Original Markdown Copyright (c) 2004-2005 John Gruber\n//   <http://daringfireball.net/projects/markdown/>\n//\n// Redistributable under a BSD-style open source license.\n// See license.txt for more information.\n//\n// The full source distribution is at:\n//\n//\t\t\t\tA A L\n//\t\t\t\tT C A\n//\t\t\t\tT K B\n//\n//   <http://www.attacklab.net/>\n//\n\n//\n// Wherever possible, Showdown is a straight, line-by-line port\n// of the Perl version of Markdown.\n//\n// This is not a normal parser design; it's basically just a\n// series of string substitutions.  It's hard to read and\n// maintain this way,  but keeping Showdown close to the original\n// design makes it easier to port new features.\n//\n// More importantly, Showdown behaves like markdown.pl in most\n// edge cases.  So web applications can do client-side preview\n// in Javascript, and then build identical HTML on the server.\n//\n// This port needs the new RegExp functionality of ECMA 262,\n// 3rd Edition (i.e. Javascript 1.5).  Most modern web browsers\n// should do fine.  Even with the new regular expression features,\n// We do a lot of work to emulate Perl's regex functionality.\n// The tricky changes in this file mostly have the \"attacklab:\"\n// label.  Major or self-explanatory changes don't.\n//\n// Smart diff tools like Araxis Merge will be able to match up\n// this file with markdown.pl in a useful way.  A little tweaking\n// helps: in a copy of markdown.pl, replace \"#\" with \"//\" and\n// replace \"$text\" with \"text\".  Be sure to ignore whitespace\n// and line endings.\n//\n\n\n//\n// Showdown usage:\n//\n//   var text = \"Markdown *rocks*.\";\n//\n//   var converter = new Showdown.converter();\n//   var html = converter.makeHtml(text);\n//\n//   alert(html);\n//\n// Note: move the sample code to the bottom of this\n// file before uncommenting it.\n//\n\n\n//\n// Showdown namespace\n//\nvar Showdown = {};\n\n//\n// converter\n//\n// Wraps all \"globals\" so that the only thing\n// exposed is makeHtml().\n//\nShowdown.converter = function() {\n\n//\n// Globals:\n//\n\n// Global hashes, used by various utility routines\nvar g_urls;\nvar g_titles;\nvar g_html_blocks;\n\n// Used to track when we're inside an ordered or unordered list\n// (see _ProcessListItems() for details):\nvar g_list_level = 0;\n\n\nthis.makeHtml = function(text) {\n//\n// Main function. The order in which other subs are called here is\n// essential. Link and image substitutions need to happen before\n// _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a>\n// and <img> tags get encoded.\n//\n\n\t// Clear the global hashes. If we don't clear these, you get conflicts\n\t// from other articles when generating a page which contains more than\n\t// one article (e.g. an index page that shows the N most recent\n\t// articles):\n\tg_urls = new Array();\n\tg_titles = new Array();\n\tg_html_blocks = new Array();\n\n\t// attacklab: Replace ~ with ~T\n\t// This lets us use tilde as an escape char to avoid md5 hashes\n\t// The choice of character is arbitray; anything that isn't\n    // magic in Markdown will work.\n\ttext = text.replace(/~/g,\"~T\");\n\n\t// attacklab: Replace $ with ~D\n\t// RegExp interprets $ as a special character\n\t// when it's in a replacement string\n\ttext = text.replace(/\\$/g,\"~D\");\n\n\t// Standardize line endings\n\ttext = text.replace(/\\r\\n/g,\"\\n\"); // DOS to Unix\n\ttext = text.replace(/\\r/g,\"\\n\"); // Mac to Unix\n\n\t// Make sure text begins and ends with a couple of newlines:\n\ttext = \"\\n\\n\" + text + \"\\n\\n\";\n\n\t// Convert all tabs to spaces.\n\ttext = _Detab(text);\n\n\t// Strip any lines consisting only of spaces and tabs.\n\t// This makes subsequent regexen easier to write, because we can\n\t// match consecutive blank lines with /\\n+/ instead of something\n\t// contorted like /[ \\t]*\\n+/ .\n\ttext = text.replace(/^[ \\t]+$/mg,\"\");\n\n\t// Turn block-level HTML blocks into hash entries\n\ttext = _HashHTMLBlocks(text);\n\n\t// Strip link definitions, store in hashes.\n\ttext = _StripLinkDefinitions(text);\n\n\ttext = _RunBlockGamut(text);\n\n\ttext = _UnescapeSpecialChars(text);\n\n\t// attacklab: Restore dollar signs\n\ttext = text.replace(/~D/g,\"$$\");\n\n\t// attacklab: Restore tildes\n\ttext = text.replace(/~T/g,\"~\");\n\n\treturn text;\n}\n\n\nvar _StripLinkDefinitions = function(text) {\n//\n// Strips link definitions from text, stores the URLs and titles in\n// hash references.\n//\n\n\t// Link defs are in the form: ^[id]: url \"optional title\"\n\n\t/*\n\t\tvar text = text.replace(/\n\t\t\t\t^[ ]{0,3}\\[(.+)\\]:  // id = $1  attacklab: g_tab_width - 1\n\t\t\t\t  [ \\t]*\n\t\t\t\t  \\n?\t\t\t\t// maybe *one* newline\n\t\t\t\t  [ \\t]*\n\t\t\t\t<?(\\S+?)>?\t\t\t// url = $2\n\t\t\t\t  [ \\t]*\n\t\t\t\t  \\n?\t\t\t\t// maybe one newline\n\t\t\t\t  [ \\t]*\n\t\t\t\t(?:\n\t\t\t\t  (\\n*)\t\t\t\t// any lines skipped = $3 attacklab: lookbehind removed\n\t\t\t\t  [\"(]\n\t\t\t\t  (.+?)\t\t\t\t// title = $4\n\t\t\t\t  [\")]\n\t\t\t\t  [ \\t]*\n\t\t\t\t)?\t\t\t\t\t// title is optional\n\t\t\t\t(?:\\n+|$)\n\t\t\t  /gm,\n\t\t\t  function(){...});\n\t*/\n\tvar text = text.replace(/^[ ]{0,3}\\[(.+)\\]:[ \\t]*\\n?[ \\t]*<?(\\S+?)>?[ \\t]*\\n?[ \\t]*(?:(\\n*)[\"(](.+?)[\")][ \\t]*)?(?:\\n+|\\Z)/gm,\n\t\tfunction (wholeMatch,m1,m2,m3,m4) {\n\t\t\tm1 = m1.toLowerCase();\n\t\t\tg_urls[m1] = _EncodeAmpsAndAngles(m2);  // Link IDs are case-insensitive\n\t\t\tif (m3) {\n\t\t\t\t// Oops, found blank lines, so it's not a title.\n\t\t\t\t// Put back the parenthetical statement we stole.\n\t\t\t\treturn m3+m4;\n\t\t\t} else if (m4) {\n\t\t\t\tg_titles[m1] = m4.replace(/\"/g,\"&quot;\");\n\t\t\t}\n\n\t\t\t// Completely remove the definition from the text\n\t\t\treturn \"\";\n\t\t}\n\t);\n\n\treturn text;\n}\n\n\nvar _HashHTMLBlocks = function(text) {\n\t// attacklab: Double up blank lines to reduce lookaround\n\ttext = text.replace(/\\n/g,\"\\n\\n\");\n\n\t// Hashify HTML blocks:\n\t// We only want to do this for block-level HTML tags, such as headers,\n\t// lists, and tables. That's because we still want to wrap <p>s around\n\t// \"paragraphs\" that are wrapped in non-block-level tags, such as anchors,\n\t// phrase emphasis, and spans. The list of tags we're looking for is\n\t// hard-coded:\n\tvar block_tags_a = \"p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del\"\n\tvar block_tags_b = \"p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math\"\n\n\t// First, look for nested blocks, e.g.:\n\t//   <div>\n\t//     <div>\n\t//     tags for inner block must be indented.\n\t//     </div>\n\t//   </div>\n\t//\n\t// The outermost tags must start at the left margin for this to match, and\n\t// the inner nested divs must be indented.\n\t// We need to do this before the next, more liberal match, because the next\n\t// match will start at the first `<div>` and stop at the first `</div>`.\n\n\t// attacklab: This regex can be expensive when it fails.\n\t/*\n\t\tvar text = text.replace(/\n\t\t(\t\t\t\t\t\t// save in $1\n\t\t\t^\t\t\t\t\t// start of line  (with /m)\n\t\t\t<($block_tags_a)\t// start tag = $2\n\t\t\t\\b\t\t\t\t\t// word break\n\t\t\t\t\t\t\t\t// attacklab: hack around khtml/pcre bug...\n\t\t\t[^\\r]*?\\n\t\t\t// any number of lines, minimally matching\n\t\t\t</\\2>\t\t\t\t// the matching end tag\n\t\t\t[ \\t]*\t\t\t\t// trailing spaces/tabs\n\t\t\t(?=\\n+)\t\t\t\t// followed by a newline\n\t\t)\t\t\t\t\t\t// attacklab: there are sentinel newlines at end of document\n\t\t/gm,function(){...}};\n\t*/\n\ttext = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\\b[^\\r]*?\\n<\\/\\2>[ \\t]*(?=\\n+))/gm,hashElement);\n\n\t//\n\t// Now match more liberally, simply from `\\n<tag>` to `</tag>\\n`\n\t//\n\n\t/*\n\t\tvar text = text.replace(/\n\t\t(\t\t\t\t\t\t// save in $1\n\t\t\t^\t\t\t\t\t// start of line  (with /m)\n\t\t\t<($block_tags_b)\t// start tag = $2\n\t\t\t\\b\t\t\t\t\t// word break\n\t\t\t\t\t\t\t\t// attacklab: hack around khtml/pcre bug...\n\t\t\t[^\\r]*?\t\t\t\t// any number of lines, minimally matching\n\t\t\t.*</\\2>\t\t\t\t// the matching end tag\n\t\t\t[ \\t]*\t\t\t\t// trailing spaces/tabs\n\t\t\t(?=\\n+)\t\t\t\t// followed by a newline\n\t\t)\t\t\t\t\t\t// attacklab: there are sentinel newlines at end of document\n\t\t/gm,function(){...}};\n\t*/\n\ttext = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\\b[^\\r]*?.*<\\/\\2>[ \\t]*(?=\\n+)\\n)/gm,hashElement);\n\n\t// Special case just for <hr />. It was easier to make a special case than\n\t// to make the other regex more complicated.\n\n\t/*\n\t\ttext = text.replace(/\n\t\t(\t\t\t\t\t\t// save in $1\n\t\t\t\\n\\n\t\t\t\t// Starting after a blank line\n\t\t\t[ ]{0,3}\n\t\t\t(<(hr)\t\t\t\t// start tag = $2\n\t\t\t\\b\t\t\t\t\t// word break\n\t\t\t([^<>])*?\t\t\t//\n\t\t\t\\/?>)\t\t\t\t// the matching end tag\n\t\t\t[ \\t]*\n\t\t\t(?=\\n{2,})\t\t\t// followed by a blank line\n\t\t)\n\t\t/g,hashElement);\n\t*/\n\ttext = text.replace(/(\\n[ ]{0,3}(<(hr)\\b([^<>])*?\\/?>)[ \\t]*(?=\\n{2,}))/g,hashElement);\n\n\t// Special case for standalone HTML comments:\n\n\t/*\n\t\ttext = text.replace(/\n\t\t(\t\t\t\t\t\t// save in $1\n\t\t\t\\n\\n\t\t\t\t// Starting after a blank line\n\t\t\t[ ]{0,3}\t\t\t// attacklab: g_tab_width - 1\n\t\t\t<!\n\t\t\t(--[^\\r]*?--\\s*)+\n\t\t\t>\n\t\t\t[ \\t]*\n\t\t\t(?=\\n{2,})\t\t\t// followed by a blank line\n\t\t)\n\t\t/g,hashElement);\n\t*/\n\ttext = text.replace(/(\\n\\n[ ]{0,3}<!(--[^\\r]*?--\\s*)+>[ \\t]*(?=\\n{2,}))/g,hashElement);\n\n\t// PHP and ASP-style processor instructions (<?...?> and <%...%>)\n\n\t/*\n\t\ttext = text.replace(/\n\t\t(?:\n\t\t\t\\n\\n\t\t\t\t// Starting after a blank line\n\t\t)\n\t\t(\t\t\t\t\t\t// save in $1\n\t\t\t[ ]{0,3}\t\t\t// attacklab: g_tab_width - 1\n\t\t\t(?:\n\t\t\t\t<([?%])\t\t\t// $2\n\t\t\t\t[^\\r]*?\n\t\t\t\t\\2>\n\t\t\t)\n\t\t\t[ \\t]*\n\t\t\t(?=\\n{2,})\t\t\t// followed by a blank line\n\t\t)\n\t\t/g,hashElement);\n\t*/\n\ttext = text.replace(/(?:\\n\\n)([ ]{0,3}(?:<([?%])[^\\r]*?\\2>)[ \\t]*(?=\\n{2,}))/g,hashElement);\n\n\t// attacklab: Undo double lines (see comment at top of this function)\n\ttext = text.replace(/\\n\\n/g,\"\\n\");\n\treturn text;\n}\n\nvar hashElement = function(wholeMatch,m1) {\n\tvar blockText = m1;\n\n\t// Undo double lines\n\tblockText = blockText.replace(/\\n\\n/g,\"\\n\");\n\tblockText = blockText.replace(/^\\n/,\"\");\n\n\t// strip trailing blank lines\n\tblockText = blockText.replace(/\\n+$/g,\"\");\n\n\t// Replace the element text with a marker (\"~KxK\" where x is its key)\n\tblockText = \"\\n\\n~K\" + (g_html_blocks.push(blockText)-1) + \"K\\n\\n\";\n\n\treturn blockText;\n};\n\nvar _RunBlockGamut = function(text) {\n//\n// These are all the transformations that form block-level\n// tags like paragraphs, headers, and list items.\n//\n\ttext = _DoHeaders(text);\n\n\t// Do Horizontal Rules:\n\tvar key = hashBlock(\"<hr />\");\n\ttext = text.replace(/^[ ]{0,2}([ ]?\\*[ ]?){3,}[ \\t]*$/gm,key);\n\ttext = text.replace(/^[ ]{0,2}([ ]?\\-[ ]?){3,}[ \\t]*$/gm,key);\n\ttext = text.replace(/^[ ]{0,2}([ ]?\\_[ ]?){3,}[ \\t]*$/gm,key);\n\n\ttext = _DoLists(text);\n\ttext = _DoCodeBlocks(text);\n\ttext = _DoBlockQuotes(text);\n\n\t// We already ran _HashHTMLBlocks() before, in Markdown(), but that\n\t// was to escape raw HTML in the original Markdown source. This time,\n\t// we're escaping the markup we've just created, so that we don't wrap\n\t// <p> tags around block-level tags.\n\ttext = _HashHTMLBlocks(text);\n\ttext = _FormParagraphs(text);\n\n\treturn text;\n}\n\n\nvar _RunSpanGamut = function(text) {\n//\n// These are all the transformations that occur *within* block-level\n// tags like paragraphs, headers, and list items.\n//\n\n\ttext = _DoCodeSpans(text);\n\ttext = _EscapeSpecialCharsWithinTagAttributes(text);\n\ttext = _EncodeBackslashEscapes(text);\n\n\t// Process anchor and image tags. Images must come first,\n\t// because ![foo][f] looks like an anchor.\n\ttext = _DoImages(text);\n\ttext = _DoAnchors(text);\n\n\t// Make links out of things like `<http://example.com/>`\n\t// Must come after _DoAnchors(), because you can use < and >\n\t// delimiters in inline links like [this](<url>).\n\ttext = _DoAutoLinks(text);\n\ttext = _EncodeAmpsAndAngles(text);\n\ttext = _DoItalicsAndBold(text);\n\n\t// Do hard breaks:\n\ttext = text.replace(/  +\\n/g,\" <br />\\n\");\n\n\treturn text;\n}\n\nvar _EscapeSpecialCharsWithinTagAttributes = function(text) {\n//\n// Within tags -- meaning between < and > -- encode [\\ ` * _] so they\n// don't conflict with their use in Markdown for code, italics and strong.\n//\n\n\t// Build a regex to find HTML tags and comments.  See Friedl's\n\t// \"Mastering Regular Expressions\", 2nd Ed., pp. 200-201.\n\tvar regex = /(<[a-z\\/!$](\"[^\"]*\"|'[^']*'|[^'\">])*>|<!(--.*?--\\s*)+>)/gi;\n\n\ttext = text.replace(regex, function(wholeMatch) {\n\t\tvar tag = wholeMatch.replace(/(.)<\\/?code>(?=.)/g,\"$1`\");\n\t\ttag = escapeCharacters(tag,\"\\\\`*_\");\n\t\treturn tag;\n\t});\n\n\treturn text;\n}\n\nvar _DoAnchors = function(text) {\n//\n// Turn Markdown link shortcuts into XHTML <a> tags.\n//\n\t//\n\t// First, handle reference-style links: [link text] [id]\n\t//\n\n\t/*\n\t\ttext = text.replace(/\n\t\t(\t\t\t\t\t\t\t// wrap whole match in $1\n\t\t\t\\[\n\t\t\t(\n\t\t\t\t(?:\n\t\t\t\t\t\\[[^\\]]*\\]\t\t// allow brackets nested one level\n\t\t\t\t\t|\n\t\t\t\t\t[^\\[]\t\t\t// or anything else\n\t\t\t\t)*\n\t\t\t)\n\t\t\t\\]\n\n\t\t\t[ ]?\t\t\t\t\t// one optional space\n\t\t\t(?:\\n[ ]*)?\t\t\t\t// one optional newline followed by spaces\n\n\t\t\t\\[\n\t\t\t(.*?)\t\t\t\t\t// id = $3\n\t\t\t\\]\n\t\t)()()()()\t\t\t\t\t// pad remaining backreferences\n\t\t/g,_DoAnchors_callback);\n\t*/\n\ttext = text.replace(/(\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\][ ]?(?:\\n[ ]*)?\\[(.*?)\\])()()()()/g,writeAnchorTag);\n\n\t//\n\t// Next, inline-style links: [link text](url \"optional title\")\n\t//\n\n\t/*\n\t\ttext = text.replace(/\n\t\t\t(\t\t\t\t\t\t// wrap whole match in $1\n\t\t\t\t\\[\n\t\t\t\t(\n\t\t\t\t\t(?:\n\t\t\t\t\t\t\\[[^\\]]*\\]\t// allow brackets nested one level\n\t\t\t\t\t|\n\t\t\t\t\t[^\\[\\]]\t\t\t// or anything else\n\t\t\t\t)\n\t\t\t)\n\t\t\t\\]\n\t\t\t\\(\t\t\t\t\t\t// literal paren\n\t\t\t[ \\t]*\n\t\t\t()\t\t\t\t\t\t// no id, so leave $3 empty\n\t\t\t<?(.*?)>?\t\t\t\t// href = $4\n\t\t\t[ \\t]*\n\t\t\t(\t\t\t\t\t\t// $5\n\t\t\t\t(['\"])\t\t\t\t// quote char = $6\n\t\t\t\t(.*?)\t\t\t\t// Title = $7\n\t\t\t\t\\6\t\t\t\t\t// matching quote\n\t\t\t\t[ \\t]*\t\t\t\t// ignore any spaces/tabs between closing quote and )\n\t\t\t)?\t\t\t\t\t\t// title is optional\n\t\t\t\\)\n\t\t)\n\t\t/g,writeAnchorTag);\n\t*/\n\ttext = text.replace(/(\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]\\([ \\t]*()<?(.*?)>?[ \\t]*((['\"])(.*?)\\6[ \\t]*)?\\))/g,writeAnchorTag);\n\n\t//\n\t// Last, handle reference-style shortcuts: [link text]\n\t// These must come last in case you've also got [link test][1]\n\t// or [link test](/foo)\n\t//\n\n\t/*\n\t\ttext = text.replace(/\n\t\t(\t\t \t\t\t\t\t// wrap whole match in $1\n\t\t\t\\[\n\t\t\t([^\\[\\]]+)\t\t\t\t// link text = $2; can't contain '[' or ']'\n\t\t\t\\]\n\t\t)()()()()()\t\t\t\t\t// pad rest of backreferences\n\t\t/g, writeAnchorTag);\n\t*/\n\ttext = text.replace(/(\\[([^\\[\\]]+)\\])()()()()()/g, writeAnchorTag);\n\n\treturn text;\n}\n\nvar writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {\n\tif (m7 == undefined) m7 = \"\";\n\tvar whole_match = m1;\n\tvar link_text   = m2;\n\tvar link_id\t = m3.toLowerCase();\n\tvar url\t\t= m4;\n\tvar title\t= m7;\n\n\tif (url == \"\") {\n\t\tif (link_id == \"\") {\n\t\t\t// lower-case and turn embedded newlines into spaces\n\t\t\tlink_id = link_text.toLowerCase().replace(/ ?\\n/g,\" \");\n\t\t}\n\t\turl = \"#\"+link_id;\n\n\t\tif (g_urls[link_id] != undefined) {\n\t\t\turl = g_urls[link_id];\n\t\t\tif (g_titles[link_id] != undefined) {\n\t\t\t\ttitle = g_titles[link_id];\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (whole_match.search(/\\(\\s*\\)$/m)>-1) {\n\t\t\t\t// Special case for explicit empty url\n\t\t\t\turl = \"\";\n\t\t\t} else {\n\t\t\t\treturn whole_match;\n\t\t\t}\n\t\t}\n\t}\n\n\turl = escapeCharacters(url,\"*_\");\n\tvar result = \"<a href=\\\"\" + url + \"\\\"\";\n\n\tif (title != \"\") {\n\t\ttitle = title.replace(/\"/g,\"&quot;\");\n\t\ttitle = escapeCharacters(title,\"*_\");\n\t\tresult +=  \" title=\\\"\" + title + \"\\\"\";\n\t}\n\n\tresult += \">\" + link_text + \"</a>\";\n\n\treturn result;\n}\n\n\nvar _DoImages = function(text) {\n//\n// Turn Markdown image shortcuts into <img> tags.\n//\n\n\t//\n\t// First, handle reference-style labeled images: ![alt text][id]\n\t//\n\n\t/*\n\t\ttext = text.replace(/\n\t\t(\t\t\t\t\t\t// wrap whole match in $1\n\t\t\t!\\[\n\t\t\t(.*?)\t\t\t\t// alt text = $2\n\t\t\t\\]\n\n\t\t\t[ ]?\t\t\t\t// one optional space\n\t\t\t(?:\\n[ ]*)?\t\t\t// one optional newline followed by spaces\n\n\t\t\t\\[\n\t\t\t(.*?)\t\t\t\t// id = $3\n\t\t\t\\]\n\t\t)()()()()\t\t\t\t// pad rest of backreferences\n\t\t/g,writeImageTag);\n\t*/\n\ttext = text.replace(/(!\\[(.*?)\\][ ]?(?:\\n[ ]*)?\\[(.*?)\\])()()()()/g,writeImageTag);\n\n\t//\n\t// Next, handle inline images:  ![alt text](url \"optional title\")\n\t// Don't forget: encode * and _\n\n\t/*\n\t\ttext = text.replace(/\n\t\t(\t\t\t\t\t\t// wrap whole match in $1\n\t\t\t!\\[\n\t\t\t(.*?)\t\t\t\t// alt text = $2\n\t\t\t\\]\n\t\t\t\\s?\t\t\t\t\t// One optional whitespace character\n\t\t\t\\(\t\t\t\t\t// literal paren\n\t\t\t[ \\t]*\n\t\t\t()\t\t\t\t\t// no id, so leave $3 empty\n\t\t\t<?(\\S+?)>?\t\t\t// src url = $4\n\t\t\t[ \\t]*\n\t\t\t(\t\t\t\t\t// $5\n\t\t\t\t(['\"])\t\t\t// quote char = $6\n\t\t\t\t(.*?)\t\t\t// title = $7\n\t\t\t\t\\6\t\t\t\t// matching quote\n\t\t\t\t[ \\t]*\n\t\t\t)?\t\t\t\t\t// title is optional\n\t\t\\)\n\t\t)\n\t\t/g,writeImageTag);\n\t*/\n\ttext = text.replace(/(!\\[(.*?)\\]\\s?\\([ \\t]*()<?(\\S+?)>?[ \\t]*((['\"])(.*?)\\6[ \\t]*)?\\))/g,writeImageTag);\n\n\treturn text;\n}\n\nvar writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) {\n\tvar whole_match = m1;\n\tvar alt_text   = m2;\n\tvar link_id\t = m3.toLowerCase();\n\tvar url\t\t= m4;\n\tvar title\t= m7;\n\n\tif (!title) title = \"\";\n\n\tif (url == \"\") {\n\t\tif (link_id == \"\") {\n\t\t\t// lower-case and turn embedded newlines into spaces\n\t\t\tlink_id = alt_text.toLowerCase().replace(/ ?\\n/g,\" \");\n\t\t}\n\t\turl = \"#\"+link_id;\n\n\t\tif (g_urls[link_id] != undefined) {\n\t\t\turl = g_urls[link_id];\n\t\t\tif (g_titles[link_id] != undefined) {\n\t\t\t\ttitle = g_titles[link_id];\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\treturn whole_match;\n\t\t}\n\t}\n\n\talt_text = alt_text.replace(/\"/g,\"&quot;\");\n\turl = escapeCharacters(url,\"*_\");\n\tvar result = \"<img src=\\\"\" + url + \"\\\" alt=\\\"\" + alt_text + \"\\\"\";\n\n\t// attacklab: Markdown.pl adds empty title attributes to images.\n\t// Replicate this bug.\n\n\t//if (title != \"\") {\n\t\ttitle = title.replace(/\"/g,\"&quot;\");\n\t\ttitle = escapeCharacters(title,\"*_\");\n\t\tresult +=  \" title=\\\"\" + title + \"\\\"\";\n\t//}\n\n\tresult += \" />\";\n\n\treturn result;\n}\n\n\nvar _DoHeaders = function(text) {\n\n\t// Setext-style headers:\n\t//\tHeader 1\n\t//\t========\n\t//\n\t//\tHeader 2\n\t//\t--------\n\t//\n\ttext = text.replace(/^(.+)[ \\t]*\\n=+[ \\t]*\\n+/gm,\n\t\tfunction(wholeMatch,m1){return hashBlock(\"<h1>\" + _RunSpanGamut(m1) + \"</h1>\");});\n\n\ttext = text.replace(/^(.+)[ \\t]*\\n-+[ \\t]*\\n+/gm,\n\t\tfunction(matchFound,m1){return hashBlock(\"<h2>\" + _RunSpanGamut(m1) + \"</h2>\");});\n\n\t// atx-style headers:\n\t//  # Header 1\n\t//  ## Header 2\n\t//  ## Header 2 with closing hashes ##\n\t//  ...\n\t//  ###### Header 6\n\t//\n\n\t/*\n\t\ttext = text.replace(/\n\t\t\t^(\\#{1,6})\t\t\t\t// $1 = string of #'s\n\t\t\t[ \\t]*\n\t\t\t(.+?)\t\t\t\t\t// $2 = Header text\n\t\t\t[ \\t]*\n\t\t\t\\#*\t\t\t\t\t\t// optional closing #'s (not counted)\n\t\t\t\\n+\n\t\t/gm, function() {...});\n\t*/\n\n\ttext = text.replace(/^(\\#{1,6})[ \\t]*(.+?)[ \\t]*\\#*\\n+/gm,\n\t\tfunction(wholeMatch,m1,m2) {\n\t\t\tvar h_level = m1.length;\n\t\t\treturn hashBlock(\"<h\" + h_level + \">\" + _RunSpanGamut(m2) + \"</h\" + h_level + \">\");\n\t\t});\n\n\treturn text;\n}\n\n// This declaration keeps Dojo compressor from outputting garbage:\nvar _ProcessListItems;\n\nvar _DoLists = function(text) {\n//\n// Form HTML ordered (numbered) and unordered (bulleted) lists.\n//\n\n\t// attacklab: add sentinel to hack around khtml/safari bug:\n\t// http://bugs.webkit.org/show_bug.cgi?id=11231\n\ttext += \"~0\";\n\n\t// Re-usable pattern to match any entirel ul or ol list:\n\n\t/*\n\t\tvar whole_list = /\n\t\t(\t\t\t\t\t\t\t\t\t// $1 = whole list\n\t\t\t(\t\t\t\t\t\t\t\t// $2\n\t\t\t\t[ ]{0,3}\t\t\t\t\t// attacklab: g_tab_width - 1\n\t\t\t\t([*+-]|\\d+[.])\t\t\t\t// $3 = first list item marker\n\t\t\t\t[ \\t]+\n\t\t\t)\n\t\t\t[^\\r]+?\n\t\t\t(\t\t\t\t\t\t\t\t// $4\n\t\t\t\t~0\t\t\t\t\t\t\t// sentinel for workaround; should be $\n\t\t\t|\n\t\t\t\t\\n{2,}\n\t\t\t\t(?=\\S)\n\t\t\t\t(?!\t\t\t\t\t\t\t// Negative lookahead for another list item marker\n\t\t\t\t\t[ \\t]*\n\t\t\t\t\t(?:[*+-]|\\d+[.])[ \\t]+\n\t\t\t\t)\n\t\t\t)\n\t\t)/g\n\t*/\n\tvar whole_list = /^(([ ]{0,3}([*+-]|\\d+[.])[ \\t]+)[^\\r]+?(~0|\\n{2,}(?=\\S)(?![ \\t]*(?:[*+-]|\\d+[.])[ \\t]+)))/gm;\n\n\tif (g_list_level) {\n\t\ttext = text.replace(whole_list,function(wholeMatch,m1,m2) {\n\t\t\tvar list = m1;\n\t\t\tvar list_type = (m2.search(/[*+-]/g)>-1) ? \"ul\" : \"ol\";\n\n\t\t\t// Turn double returns into triple returns, so that we can make a\n\t\t\t// paragraph for the last item in a list, if necessary:\n\t\t\tlist = list.replace(/\\n{2,}/g,\"\\n\\n\\n\");;\n\t\t\tvar result = _ProcessListItems(list);\n\n\t\t\t// Trim any trailing whitespace, to put the closing `</$list_type>`\n\t\t\t// up on the preceding line, to get it past the current stupid\n\t\t\t// HTML block parser. This is a hack to work around the terrible\n\t\t\t// hack that is the HTML block parser.\n\t\t\tresult = result.replace(/\\s+$/,\"\");\n\t\t\tresult = \"<\"+list_type+\">\" + result + \"</\"+list_type+\">\\n\";\n\t\t\treturn result;\n\t\t});\n\t} else {\n\t\twhole_list = /(\\n\\n|^\\n?)(([ ]{0,3}([*+-]|\\d+[.])[ \\t]+)[^\\r]+?(~0|\\n{2,}(?=\\S)(?![ \\t]*(?:[*+-]|\\d+[.])[ \\t]+)))/g;\n\t\ttext = text.replace(whole_list,function(wholeMatch,m1,m2,m3) {\n\t\t\tvar runup = m1;\n\t\t\tvar list = m2;\n\n\t\t\tvar list_type = (m3.search(/[*+-]/g)>-1) ? \"ul\" : \"ol\";\n\t\t\t// Turn double returns into triple returns, so that we can make a\n\t\t\t// paragraph for the last item in a list, if necessary:\n\t\t\tvar list = list.replace(/\\n{2,}/g,\"\\n\\n\\n\");;\n\t\t\tvar result = _ProcessListItems(list);\n\t\t\tresult = runup + \"<\"+list_type+\">\\n\" + result + \"</\"+list_type+\">\\n\";\n\t\t\treturn result;\n\t\t});\n\t}\n\n\t// attacklab: strip sentinel\n\ttext = text.replace(/~0/,\"\");\n\n\treturn text;\n}\n\n_ProcessListItems = function(list_str) {\n//\n//  Process the contents of a single ordered or unordered list, splitting it\n//  into individual list items.\n//\n\t// The $g_list_level global keeps track of when we're inside a list.\n\t// Each time we enter a list, we increment it; when we leave a list,\n\t// we decrement. If it's zero, we're not in a list anymore.\n\t//\n\t// We do this because when we're not inside a list, we want to treat\n\t// something like this:\n\t//\n\t//    I recommend upgrading to version\n\t//    8. Oops, now this line is treated\n\t//    as a sub-list.\n\t//\n\t// As a single paragraph, despite the fact that the second line starts\n\t// with a digit-period-space sequence.\n\t//\n\t// Whereas when we're inside a list (or sub-list), that line will be\n\t// treated as the start of a sub-list. What a kludge, huh? This is\n\t// an aspect of Markdown's syntax that's hard to parse perfectly\n\t// without resorting to mind-reading. Perhaps the solution is to\n\t// change the syntax rules such that sub-lists must start with a\n\t// starting cardinal number; e.g. \"1.\" or \"a.\".\n\n\tg_list_level++;\n\n\t// trim trailing blank lines:\n\tlist_str = list_str.replace(/\\n{2,}$/,\"\\n\");\n\n\t// attacklab: add sentinel to emulate \\z\n\tlist_str += \"~0\";\n\n\t/*\n\t\tlist_str = list_str.replace(/\n\t\t\t(\\n)?\t\t\t\t\t\t\t// leading line = $1\n\t\t\t(^[ \\t]*)\t\t\t\t\t\t// leading whitespace = $2\n\t\t\t([*+-]|\\d+[.]) [ \\t]+\t\t\t// list marker = $3\n\t\t\t([^\\r]+?\t\t\t\t\t\t// list item text   = $4\n\t\t\t(\\n{1,2}))\n\t\t\t(?= \\n* (~0 | \\2 ([*+-]|\\d+[.]) [ \\t]+))\n\t\t/gm, function(){...});\n\t*/\n\tlist_str = list_str.replace(/(\\n)?(^[ \\t]*)([*+-]|\\d+[.])[ \\t]+([^\\r]+?(\\n{1,2}))(?=\\n*(~0|\\2([*+-]|\\d+[.])[ \\t]+))/gm,\n\t\tfunction(wholeMatch,m1,m2,m3,m4){\n\t\t\tvar item = m4;\n\t\t\tvar leading_line = m1;\n\t\t\tvar leading_space = m2;\n\n\t\t\tif (leading_line || (item.search(/\\n{2,}/)>-1)) {\n\t\t\t\titem = _RunBlockGamut(_Outdent(item));\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Recursion for sub-lists:\n\t\t\t\titem = _DoLists(_Outdent(item));\n\t\t\t\titem = item.replace(/\\n$/,\"\"); // chomp(item)\n\t\t\t\titem = _RunSpanGamut(item);\n\t\t\t}\n\n\t\t\treturn  \"<li>\" + item + \"</li>\\n\";\n\t\t}\n\t);\n\n\t// attacklab: strip sentinel\n\tlist_str = list_str.replace(/~0/g,\"\");\n\n\tg_list_level--;\n\treturn list_str;\n}\n\n\nvar _DoCodeBlocks = function(text) {\n//\n//  Process Markdown `<pre><code>` blocks.\n//\n\n\t/*\n\t\ttext = text.replace(text,\n\t\t\t/(?:\\n\\n|^)\n\t\t\t(\t\t\t\t\t\t\t\t// $1 = the code block -- one or more lines, starting with a space/tab\n\t\t\t\t(?:\n\t\t\t\t\t(?:[ ]{4}|\\t)\t\t\t// Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width\n\t\t\t\t\t.*\\n+\n\t\t\t\t)+\n\t\t\t)\n\t\t\t(\\n*[ ]{0,3}[^ \\t\\n]|(?=~0))\t// attacklab: g_tab_width\n\t\t/g,function(){...});\n\t*/\n\n\t// attacklab: sentinel workarounds for lack of \\A and \\Z, safari\\khtml bug\n\ttext += \"~0\";\n\n\ttext = text.replace(/(?:\\n\\n|^)((?:(?:[ ]{4}|\\t).*\\n+)+)(\\n*[ ]{0,3}[^ \\t\\n]|(?=~0))/g,\n\t\tfunction(wholeMatch,m1,m2) {\n\t\t\tvar codeblock = m1;\n\t\t\tvar nextChar = m2;\n\n\t\t\tcodeblock = _EncodeCode( _Outdent(codeblock));\n\t\t\tcodeblock = _Detab(codeblock);\n\t\t\tcodeblock = codeblock.replace(/^\\n+/g,\"\"); // trim leading newlines\n\t\t\tcodeblock = codeblock.replace(/\\n+$/g,\"\"); // trim trailing whitespace\n\n\t\t\tcodeblock = \"<pre><code>\" + codeblock + \"\\n</code></pre>\";\n\n\t\t\treturn hashBlock(codeblock) + nextChar;\n\t\t}\n\t);\n\n\t// attacklab: strip sentinel\n\ttext = text.replace(/~0/,\"\");\n\n\treturn text;\n}\n\nvar hashBlock = function(text) {\n\ttext = text.replace(/(^\\n+|\\n+$)/g,\"\");\n\treturn \"\\n\\n~K\" + (g_html_blocks.push(text)-1) + \"K\\n\\n\";\n}\n\n\nvar _DoCodeSpans = function(text) {\n//\n//   *  Backtick quotes are used for <code></code> spans.\n//\n//   *  You can use multiple backticks as the delimiters if you want to\n//\t include literal backticks in the code span. So, this input:\n//\n//\t\t Just type ``foo `bar` baz`` at the prompt.\n//\n//\t   Will translate to:\n//\n//\t\t <p>Just type <code>foo `bar` baz</code> at the prompt.</p>\n//\n//\tThere's no arbitrary limit to the number of backticks you\n//\tcan use as delimters. If you need three consecutive backticks\n//\tin your code, use four for delimiters, etc.\n//\n//  *  You can use spaces to get literal backticks at the edges:\n//\n//\t\t ... type `` `bar` `` ...\n//\n//\t   Turns to:\n//\n//\t\t ... type <code>`bar`</code> ...\n//\n\n\t/*\n\t\ttext = text.replace(/\n\t\t\t(^|[^\\\\])\t\t\t\t\t// Character before opening ` can't be a backslash\n\t\t\t(`+)\t\t\t\t\t\t// $2 = Opening run of `\n\t\t\t(\t\t\t\t\t\t\t// $3 = The code block\n\t\t\t\t[^\\r]*?\n\t\t\t\t[^`]\t\t\t\t\t// attacklab: work around lack of lookbehind\n\t\t\t)\n\t\t\t\\2\t\t\t\t\t\t\t// Matching closer\n\t\t\t(?!`)\n\t\t/gm, function(){...});\n\t*/\n\n\ttext = text.replace(/(^|[^\\\\])(`+)([^\\r]*?[^`])\\2(?!`)/gm,\n\t\tfunction(wholeMatch,m1,m2,m3,m4) {\n\t\t\tvar c = m3;\n\t\t\tc = c.replace(/^([ \\t]*)/g,\"\");\t// leading whitespace\n\t\t\tc = c.replace(/[ \\t]*$/g,\"\");\t// trailing whitespace\n\t\t\tc = _EncodeCode(c);\n\t\t\treturn m1+\"<code>\"+c+\"</code>\";\n\t\t});\n\n\treturn text;\n}\n\n\nvar _EncodeCode = function(text) {\n//\n// Encode/escape certain characters inside Markdown code runs.\n// The point is that in code, these characters are literals,\n// and lose their special Markdown meanings.\n//\n\t// Encode all ampersands; HTML entities are not\n\t// entities within a Markdown code span.\n\ttext = text.replace(/&/g,\"&amp;\");\n\n\t// Do the angle bracket song and dance:\n\ttext = text.replace(/</g,\"&lt;\");\n\ttext = text.replace(/>/g,\"&gt;\");\n\n\t// Now, escape characters that are magic in Markdown:\n\ttext = escapeCharacters(text,\"\\*_{}[]\\\\\",false);\n\n// jj the line above breaks this:\n//---\n\n//* Item\n\n//   1. Subitem\n\n//            special char: *\n//---\n\n\treturn text;\n}\n\n\nvar _DoItalicsAndBold = function(text) {\n\n\t// <strong> must go first:\n\ttext = text.replace(/(\\*\\*|__)(?=\\S)([^\\r]*?\\S[*_]*)\\1/g,\n\t\t\"<strong>$2</strong>\");\n\n\ttext = text.replace(/(\\*|_)(?=\\S)([^\\r]*?\\S)\\1/g,\n\t\t\"<em>$2</em>\");\n\n\treturn text;\n}\n\n\nvar _DoBlockQuotes = function(text) {\n\n\t/*\n\t\ttext = text.replace(/\n\t\t(\t\t\t\t\t\t\t\t// Wrap whole match in $1\n\t\t\t(\n\t\t\t\t^[ \\t]*>[ \\t]?\t\t\t// '>' at the start of a line\n\t\t\t\t.+\\n\t\t\t\t\t// rest of the first line\n\t\t\t\t(.+\\n)*\t\t\t\t\t// subsequent consecutive lines\n\t\t\t\t\\n*\t\t\t\t\t\t// blanks\n\t\t\t)+\n\t\t)\n\t\t/gm, function(){...});\n\t*/\n\n\ttext = text.replace(/((^[ \\t]*>[ \\t]?.+\\n(.+\\n)*\\n*)+)/gm,\n\t\tfunction(wholeMatch,m1) {\n\t\t\tvar bq = m1;\n\n\t\t\t// attacklab: hack around Konqueror 3.5.4 bug:\n\t\t\t// \"----------bug\".replace(/^-/g,\"\") == \"bug\"\n\n\t\t\tbq = bq.replace(/^[ \\t]*>[ \\t]?/gm,\"~0\");\t// trim one level of quoting\n\n\t\t\t// attacklab: clean up hack\n\t\t\tbq = bq.replace(/~0/g,\"\");\n\n\t\t\tbq = bq.replace(/^[ \\t]+$/gm,\"\");\t\t// trim whitespace-only lines\n\t\t\tbq = _RunBlockGamut(bq);\t\t\t\t// recurse\n\n\t\t\tbq = bq.replace(/(^|\\n)/g,\"$1  \");\n\t\t\t// These leading spaces screw with <pre> content, so we need to fix that:\n\t\t\tbq = bq.replace(\n\t\t\t\t\t/(\\s*<pre>[^\\r]+?<\\/pre>)/gm,\n\t\t\t\tfunction(wholeMatch,m1) {\n\t\t\t\t\tvar pre = m1;\n\t\t\t\t\t// attacklab: hack around Konqueror 3.5.4 bug:\n\t\t\t\t\tpre = pre.replace(/^  /mg,\"~0\");\n\t\t\t\t\tpre = pre.replace(/~0/g,\"\");\n\t\t\t\t\treturn pre;\n\t\t\t\t});\n\n\t\t\treturn hashBlock(\"<blockquote>\\n\" + bq + \"\\n</blockquote>\");\n\t\t});\n\treturn text;\n}\n\n\nvar _FormParagraphs = function(text) {\n//\n//  Params:\n//    $text - string to process with html <p> tags\n//\n\n\t// Strip leading and trailing lines:\n\ttext = text.replace(/^\\n+/g,\"\");\n\ttext = text.replace(/\\n+$/g,\"\");\n\n\tvar grafs = text.split(/\\n{2,}/g);\n\tvar grafsOut = new Array();\n\n\t//\n\t// Wrap <p> tags.\n\t//\n\tvar end = grafs.length;\n\tfor (var i=0; i<end; i++) {\n\t\tvar str = grafs[i];\n\n\t\t// if this is an HTML marker, copy it\n\t\tif (str.search(/~K(\\d+)K/g) >= 0) {\n\t\t\tgrafsOut.push(str);\n\t\t}\n\t\telse if (str.search(/\\S/) >= 0) {\n\t\t\tstr = _RunSpanGamut(str);\n\t\t\tstr = str.replace(/^([ \\t]*)/g,\"<p>\");\n\t\t\tstr += \"</p>\"\n\t\t\tgrafsOut.push(str);\n\t\t}\n\n\t}\n\n\t//\n\t// Unhashify HTML blocks\n\t//\n\tend = grafsOut.length;\n\tfor (var i=0; i<end; i++) {\n\t\t// if this is a marker for an html block...\n\t\twhile (grafsOut[i].search(/~K(\\d+)K/) >= 0) {\n\t\t\tvar blockText = g_html_blocks[RegExp.$1];\n\t\t\tblockText = blockText.replace(/\\$/g,\"$$$$\"); // Escape any dollar signs\n\t\t\tgrafsOut[i] = grafsOut[i].replace(/~K\\d+K/,blockText);\n\t\t}\n\t}\n\n\treturn grafsOut.join(\"\\n\\n\");\n}\n\n\nvar _EncodeAmpsAndAngles = function(text) {\n// Smart processing for ampersands and angle brackets that need to be encoded.\n\n\t// Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:\n\t//   http://bumppo.net/projects/amputator/\n\ttext = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\\w+);)/g,\"&amp;\");\n\n\t// Encode naked <'s\n\ttext = text.replace(/<(?![a-z\\/?\\$!])/gi,\"&lt;\");\n\n\treturn text;\n}\n\n\nvar _EncodeBackslashEscapes = function(text) {\n//\n//   Parameter:  String.\n//   Returns:\tThe string, with after processing the following backslash\n//\t\t\t   escape sequences.\n//\n\n\t// attacklab: The polite way to do this is with the new\n\t// escapeCharacters() function:\n\t//\n\t// \ttext = escapeCharacters(text,\"\\\\\",true);\n\t// \ttext = escapeCharacters(text,\"`*_{}[]()>#+-.!\",true);\n\t//\n\t// ...but we're sidestepping its use of the (slow) RegExp constructor\n\t// as an optimization for Firefox.  This function gets called a LOT.\n\n\ttext = text.replace(/\\\\(\\\\)/g,escapeCharacters_callback);\n\ttext = text.replace(/\\\\([`*_{}\\[\\]()>#+-.!])/g,escapeCharacters_callback);\n\treturn text;\n}\n\n\nvar _DoAutoLinks = function(text) {\n\n\ttext = text.replace(/<((https?|ftp|dict):[^'\">\\s]+)>/gi,\"<a href=\\\"$1\\\">$1</a>\");\n\n\t// Email addresses: <address@domain.foo>\n\n\t/*\n\t\ttext = text.replace(/\n\t\t\t<\n\t\t\t(?:mailto:)?\n\t\t\t(\n\t\t\t\t[-.\\w]+\n\t\t\t\t\\@\n\t\t\t\t[-a-z0-9]+(\\.[-a-z0-9]+)*\\.[a-z]+\n\t\t\t)\n\t\t\t>\n\t\t/gi, _DoAutoLinks_callback());\n\t*/\n\ttext = text.replace(/<(?:mailto:)?([-.\\w]+\\@[-a-z0-9]+(\\.[-a-z0-9]+)*\\.[a-z]+)>/gi,\n\t\tfunction(wholeMatch,m1) {\n\t\t\treturn _EncodeEmailAddress( _UnescapeSpecialChars(m1) );\n\t\t}\n\t);\n\n\treturn text;\n}\n\n\nvar _EncodeEmailAddress = function(addr) {\n//\n//  Input: an email address, e.g. \"foo@example.com\"\n//\n//  Output: the email address as a mailto link, with each character\n//\tof the address encoded as either a decimal or hex entity, in\n//\tthe hopes of foiling most address harvesting spam bots. E.g.:\n//\n//\t<a href=\"&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;\n//\t   x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;\">&#102;&#111;&#111;\n//\t   &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>\n//\n//  Based on a filter by Matthew Wickline, posted to the BBEdit-Talk\n//  mailing list: <http://tinyurl.com/yu7ue>\n//\n\n\t// attacklab: why can't javascript speak hex?\n\tfunction char2hex(ch) {\n\t\tvar hexDigits = '0123456789ABCDEF';\n\t\tvar dec = ch.charCodeAt(0);\n\t\treturn(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15));\n\t}\n\n\tvar encode = [\n\t\tfunction(ch){return \"&#\"+ch.charCodeAt(0)+\";\";},\n\t\tfunction(ch){return \"&#x\"+char2hex(ch)+\";\";},\n\t\tfunction(ch){return ch;}\n\t];\n\n\taddr = \"mailto:\" + addr;\n\n\taddr = addr.replace(/./g, function(ch) {\n\t\tif (ch == \"@\") {\n\t\t   \t// this *must* be encoded. I insist.\n\t\t\tch = encode[Math.floor(Math.random()*2)](ch);\n\t\t} else if (ch !=\":\") {\n\t\t\t// leave ':' alone (to spot mailto: later)\n\t\t\tvar r = Math.random();\n\t\t\t// roughly 10% raw, 45% hex, 45% dec\n\t\t\tch =  (\n\t\t\t\t\tr > .9  ?\tencode[2](ch)   :\n\t\t\t\t\tr > .45 ?\tencode[1](ch)   :\n\t\t\t\t\t\t\t\tencode[0](ch)\n\t\t\t\t);\n\t\t}\n\t\treturn ch;\n\t});\n\n\taddr = \"<a href=\\\"\" + addr + \"\\\">\" + addr + \"</a>\";\n\taddr = addr.replace(/\">.+:/g,\"\\\">\"); // strip the mailto: from the visible part\n\n\treturn addr;\n}\n\n\nvar _UnescapeSpecialChars = function(text) {\n//\n// Swap back in all the special characters we've hidden.\n//\n\ttext = text.replace(/~E(\\d+)E/g,\n\t\tfunction(wholeMatch,m1) {\n\t\t\tvar charCodeToReplace = parseInt(m1);\n\t\t\treturn String.fromCharCode(charCodeToReplace);\n\t\t}\n\t);\n\treturn text;\n}\n\n\nvar _Outdent = function(text) {\n//\n// Remove one level of line-leading tabs or spaces\n//\n\n\t// attacklab: hack around Konqueror 3.5.4 bug:\n\t// \"----------bug\".replace(/^-/g,\"\") == \"bug\"\n\n\ttext = text.replace(/^(\\t|[ ]{1,4})/gm,\"~0\"); // attacklab: g_tab_width\n\n\t// attacklab: clean up hack\n\ttext = text.replace(/~0/g,\"\")\n\n\treturn text;\n}\n\nvar _Detab = function(text) {\n// attacklab: Detab's completely rewritten for speed.\n// In perl we could fix it by anchoring the regexp with \\G.\n// In javascript we're less fortunate.\n\n\t// expand first n-1 tabs\n\ttext = text.replace(/\\t(?=\\t)/g,\"    \"); // attacklab: g_tab_width\n\n\t// replace the nth with two sentinels\n\ttext = text.replace(/\\t/g,\"~A~B\");\n\n\t// use the sentinel to anchor our regex so it doesn't explode\n\ttext = text.replace(/~B(.+?)~A/g,\n\t\tfunction(wholeMatch,m1,m2) {\n\t\t\tvar leadingText = m1;\n\t\t\tvar numSpaces = 4 - leadingText.length % 4;  // attacklab: g_tab_width\n\n\t\t\t// there *must* be a better way to do this:\n\t\t\tfor (var i=0; i<numSpaces; i++) leadingText+=\" \";\n\n\t\t\treturn leadingText;\n\t\t}\n\t);\n\n\t// clean up sentinels\n\ttext = text.replace(/~A/g,\"    \");  // attacklab: g_tab_width\n\ttext = text.replace(/~B/g,\"\");\n\n\treturn text;\n}\n\n\n//\n//  attacklab: Utility functions\n//\n\n\nvar escapeCharacters = function(text, charsToEscape, afterBackslash) {\n\t// First we have to escape the escape characters so that\n\t// we can build a character class out of them\n\tvar regexString = \"([\" + charsToEscape.replace(/([\\[\\]\\\\])/g,\"\\\\$1\") + \"])\";\n\n\tif (afterBackslash) {\n\t\tregexString = \"\\\\\\\\\" + regexString;\n\t}\n\n\tvar regex = new RegExp(regexString,\"g\");\n\ttext = text.replace(regex,escapeCharacters_callback);\n\n\treturn text;\n}\n\n\nvar escapeCharacters_callback = function(wholeMatch,m1) {\n\tvar charCodeToEscape = m1.charCodeAt(0);\n\treturn \"~E\"+charCodeToEscape+\"E\";\n}\n\n} // end of Showdown.converter\n"
  },
  {
    "path": "site/examples/friendlycode/templates/confirm-dialog.html",
    "content": "<div class=\"confirm-dialog modal-overlay\" style=\"display: none;\">\n  <div class=\"thimble-modal-menu thimble-question-bar\">\n    <div class=\"thimble-branding\"></div>\n    <div class=\"thimble-menu-content\">\n       <div>\n         <div class=\"thimble-title\">Are you sure you want to publish your page?</div>\n         <div class=\"thimble-additionals\">\n           <div class=\"confirmation-buttons\">\n             <span class=\"confirmation-button yes-button\">Yes</span>\n             <span class=\"confirmation-button no-button\" data-close-modal>No</span>\n           </div>\n           <br>\n           <div class=\"public-warning\">\n           A published page is visible to everyone on the Web.\n           </div>\n           <div class=\"error-warning\">\n             <strong>Warning:</strong> Your code appears to contain\n             errors, and the published page may not appear as you intend.\n           </div>\n           <div class=\"development-note\">\n             <strong>Note:</strong> You are using experimental\n             software and your published page could disappear at\n             any time.\n           </div>\n         </div>\n       </div>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "site/examples/friendlycode/templates/default-content.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Your Awesome Webpage</title>\n  </head>\n  <body>\n    <p>Make something amazing with the web</p>\n  </body>\n</html>"
  },
  {
    "path": "site/examples/friendlycode/templates/error-dialog.html",
    "content": "<div class=\"modal-overlay\" style=\"display: none;\">\n  <div class=\"thimble-error\">\n    <div class=\"thimble-title thimble-grey-bar\">An error occurred</div>\n    <div class=\"thimble-additionals\">\n      <p class=\"error-text\">error text goes here</p>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "site/examples/friendlycode/templates/error-msg.html",
    "content": "<div class=\"up-arrow\"></div>\n<div class=\"icon\"></div>\n<div class=\"content\">\n  <%= error %>\n</div>\n<div class=\"down-arrow\"></div>\n"
  },
  {
    "path": "site/examples/friendlycode/templates/help-msg.html",
    "content": "<div class=\"up-arrow\"></div>\n<div class=\"icon\"></div>\n<div class=\"content\">\n  <%= html %>\n  <% if (type == \"cssSelector\") { %>\n    <span class=\"selector-matches\"> It currently matches <%- matchCount %> element(s).</span>\n  <% } %>\n  <a class=\"learn-more\" href=\"<%- url %>\">more…</a>\n</div>\n<div class=\"down-arrow\"></div>\n"
  },
  {
    "path": "site/examples/friendlycode/templates/nav-options.html",
    "content": "<div class=\"nav-options\">\n  <div class=\"editor-pane-nav-options\">\n    <!-- editor, undo, redo, text size, hinting -->\n    <div class=\"editor-nav-item nav-item\">\n      <span class=\"icon\">&nbsp;</span>Editor\n      <div class=\"pane-indicator enabled\"></div>\n    </div>\n    <div class=\"nav-item\"><div class=\"breadcrumbs\"></div></div>\n    <div class=\"undo-nav-item nav-item responsive\"\n         data-restore-help=\"We've rescued your very recent changes to this page, but you can click this button to undo them.\"\n         title=\"Undo changes\">\n         <span class=\"icon\">&nbsp;</span>Undo</div>\n    <div class=\"redo-nav-item nav-item responsive\" title=\"Redo changes\">\n      <span class=\"icon\">&nbsp;</span>Redo\n    </div>\n    <div class=\"text-nav-item nav-item responsive enabled\" title=\"Change text size\">\n      <span class=\"icon\">&nbsp;</span>Size\n      <ul class=\"text-size-options\">\n        <li data-size=\"small\">Small</li>\n        <li data-size=\"normal\" data-default-size>Normal</li>\n        <li data-size=\"large\">Large</li>\n      </ul>\n    </div>\n    <div class=\"hints-nav-item nav-item enabled\" title=\"Disable HTML and CSS hints and suggestions\">\n      <div class=\"checkbox on\">✓</div> <div class=\"checkbox-label\">Show hints</div></div>\n  </div>\n  <div class=\"preview-pane-nav-options\">\n    <!-- previous, save draft, publish -->\n     <div class=\"preview-nav-item nav-item\">\n       <span class=\"icon\">&nbsp;</span>Preview<span class=\"preview-title\"></span><div class=\"pane-indicator enabled\"></div>\n     </div>\n     <div class=\"nav-item buttons\">\n       <div class=\"publish-button wm-button wm-button-blue short\">Publish</div>\n     </div>\n  </div>\n</div>\n"
  },
  {
    "path": "site/examples/friendlycode/templates/publish-dialog.html",
    "content": "<div class=\"publish-dialog modal-overlay\" style=\"display: none;\">\n  <div class=\"thimble-modal-menu thimble-grey-bar\">\n    <div class=\"thimble-menu-content\">\n       <div class=\"modal-close-button\" data-close-modal>&nbsp;</div>\n\n       <!-- PUBLISH YOUR WORK -->\n       <div class=\"publication-result accordion\">\n         <div class=\"thimble-title\">\n           <div class=\"thimble-branding\"></div>\n           Copy and paste the url for your page\n         </div>\n         <div class=\"accordion-content\">\n           <div class=\"thimble-url-box\">\n             <a href=\"#\" class=\"view\"></a>\n           </div>\n         </div>\n       </div>\n\n       <div class=\"accordion collapsed\">\n         <div class=\"thimble-title\">Grab the link to edit your published page</div>\n         <div class=\"accordion-content\">\n           <div class=\"thimble-url-box\">\n             <a href=\"#\" class=\"remix\"></a>\n           </div>\n         </div>\n       </div>\n       <!-- PUBLISH YOUR WORK -->\n       \n       <!-- SHARE YOUR WORK -->\n       <div class=\"share-result accordion collapsed\">\n         <div class=\"thimble-title\">Share this via&hellip;</div>\n         <div class=\"accordion-content\">\n           <div class=\"thimble-additionals\">\n             <ul>\n               <li data-medium=\"twitter\">Twitter</li>\n               <li data-medium=\"google\">Google+</li>\n               <li data-medium=\"facebook\">Facebook</li>\n             </ul>\n           </div>\n         </div>\n       </div>\n       <!-- SHARE YOUR WORK -->\n       \n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "site/examples/friendlycode/test/all-tests.js",
    "content": "defineTests.combine([\n  \"test/test-app\",\n  \"test/test-help\",\n  \"test/test-templates\",\n  \"test/test-indexable-codemirror\",\n  \"test/test-parsing-codemirror\",\n  \"test/test-mark-tracker\",\n  \"test/test-live-preview\",\n  \"test/test-slowparse-errors\",\n  \"test/publisher/test-publisher\",\n  \"test/codemirror-577/test-codemirror-577\",\n  \"test/preview-to-editor-mapping/test-preview-to-editor-mapping\",\n  \"test/test-current-page-manager\",\n  \"test/test-editor-toolbar\",\n  \"test/test-prefs\",\n  \"test/test-gutter-pointer\"\n]);\n"
  },
  {
    "path": "site/examples/friendlycode/test/codemirror-577/original.html",
    "content": "<!doctype html>\n<!--\nHere is a comment.\n-->\n\n<html>\n</body>\n</html>"
  },
  {
    "path": "site/examples/friendlycode/test/codemirror-577/replacer.html",
    "content": "<html>\n  <head>\n  </head>\n  <body>\n  </body>\n</html>"
  },
  {
    "path": "site/examples/friendlycode/test/codemirror-577/test-codemirror-577.js",
    "content": "\"use strict\";\n\ndefineTests([\n  \"jquery\",\n  \"codemirror\",\n  \"text!test/codemirror-577/original.html\",\n  \"text!test/codemirror-577/replacer.html\"\n], function($, CodeMirror, original, replacer) {\n  module(\"Codemirror issue 577\");\n  \n  // Test to ensure that this bug is fixed or worked around:\n  // https://github.com/marijnh/CodeMirror2/issues/577\n  test(\"undo() doesn't throw\", function() {\n    var div = $(\"<div></div>\").appendTo(\"body\");\n    var editor = CodeMirror(div[0], {\n      mode: 'text/plain',\n      tabMode: 'indent'\n    });\n    try {\n      editor.setValue(original);\n      editor.clearHistory();\n      editor.setValue(replacer);\n      editor.undo();\n      ok(true, \"undo() didn't throw!\");\n    } finally {\n      div.remove();\n    }\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/define-tests.js",
    "content": "// Because we're using requirejs to asynchronously load tests,\n// we need to have manual control over the running of tests.\nQUnit.config.autostart = false;\n\n// We want to \"lazily\" define tests so that the order of their\n// definition isn't arbitrarily determined by requirejs. This way,\n// the test results will always be reported in the same order, which\n// makes reading test results across multiple page reloads much\n// easier.\n//\n// Note that this has NOTHING to do with the order of\n// actual test execution--our tests should always be isolated from\n// each other so that the order QUnit chooses to run them in\n// doesn't matter.\nfunction defineTests(deps, fn) {\n  define(deps, function() {\n    var injectedDeps = arguments;\n    return function describeTests() {\n      fn.apply(this, injectedDeps);\n    };\n  });\n}\n\n// String together a bunch of defineTests-based modules into a\n// single one.\ndefineTests.combine = function(deps) {\n  define(deps, function() {\n    var args = Array.prototype.slice.call(arguments);\n    return function describeManyTests() {\n      args.forEach(function(describeTests) {\n        describeTests();\n      });\n    };\n  });\n};\n\n// Run the given list of defineTests-based modules.\ndefineTests.run = function(deps) {\n  require(deps, function() {\n    var args = Array.prototype.slice.call(arguments);\n    args.forEach(function(describeTests) {\n      describeTests();\n    });\n\n    if (QUnit.config.blocking)\n      QUnit.config.autostart = true;\n    else\n      QUnit.start();\n  });\n};\n"
  },
  {
    "path": "site/examples/friendlycode/test/index-optimized.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Friendlycode Test Suite - Optimized Build</title>\n    <link rel=\"stylesheet\" href=\"qunit.css\">\n  </head>\n\n  <body>\n    <h1  id=\"qunit-header\">Friendlycode Test Suite  - Optimized Build</h1>\n    <h2  id=\"qunit-banner\"></h2>\n    <div id=\"qunit-testrunner-toolbar\"></div>\n    <h2  id=\"qunit-userAgent\"></h2>\n    <ol  id=\"qunit-tests\"></ol>\n    <div id=\"qunit-fixture\"></div>\n\n    <script src=\"qunit.js\"></script>\n    <script src=\"define-tests.js\"></script>\n    <script src=\"../js/require-config.js\"></script>\n    <script src=\"../js/require.min.js\"></script>\n    <script src=\"../js/friendlycode-built.js\"\n            onerror=\"alert('please run build-require.js!');\"></script>\n    <script>\n    defineTests.run([\"test/all-tests\"]);\n    \n    if (location.search.match(/externalreporter=1/))\n      document.write('<script src=\"/externalreporter.js\"></' + 'script>');\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/friendlycode/test/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Friendlycode Test Suite</title>\n    <link rel=\"stylesheet\" href=\"qunit.css\">\n  </head>\n\n  <body>\n    <h1  id=\"qunit-header\">Friendlycode Test Suite</h1>\n    <h2  id=\"qunit-banner\"></h2>\n    <div id=\"qunit-testrunner-toolbar\"></div>\n    <h2  id=\"qunit-userAgent\"></h2>\n    <ol  id=\"qunit-tests\"></ol>\n    <div id=\"qunit-fixture\"></div>\n\n    <script src=\"qunit.js\"></script>\n    <script src=\"define-tests.js\"></script>\n    <script src=\"../js/require-config.js\"></script>\n    <script src=\"../js/require.min.js\"></script>\n    <script>\n    defineTests.run([\"test/all-tests\"]);\n    \n    if (location.search.match(/externalreporter=1/))\n      document.write('<script src=\"/externalreporter.js\"></' + 'script>');\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/friendlycode/test/lptest.js",
    "content": "define([\n  \"jquery\",\n  \"backbone-events\",\n  \"fc/ui/live-preview\",\n  \"slowparse/slowparse\"\n], function($, BackboneEvents, LivePreview, Slowparse) {\n  return function lpTest(name, html, cb) {\n    if (typeof(html) == 'function') {\n      cb = html;\n      html = '<p>hi <em>there</em></p>';\n    }\n    test(name, function() {\n      var div = $('<div></div>').appendTo('body').css({visibility: \"hidden\"});\n      var cm = BackboneEvents.mixin({});\n      var preview = LivePreview({\n        codeMirror: cm,\n        previewArea: div\n      });\n      var result = Slowparse.HTML(document, html);\n      cm.trigger('reparse', {\n        error: null,\n        sourceCode: html,\n        document: result.document\n      });\n      try {\n        var iframe = div.find(\"iframe\");\n        if (iframe.length != 1)\n          ok(false, \"preview area should contain 1 iframe\");\n        if (!iframe[0].contentWindow)\n          ok(false, \"iframe contentWindow should be non-null\");\n        cb(iframe, preview, cm, result.document, html);\n      } finally {\n        div.remove();\n      }\n    });\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/preview-to-editor-mapping/path-to.html",
    "content": "<div class=\"test-case\" data-expect=\" > div:nth-of-type(1)\">\n  <div data-target=\"true\"></div>\n</div>\n<div class=\"test-case\" data-expect=\" > div:nth-of-type(1) > span:nth-of-type(1)\">\n  <div>\n    <span data-target=\"true\"></span>\n  </div>\n</div>\n<div class=\"test-case\" data-expect=\" > div:nth-of-type(1) > span:nth-of-type(2)\">\n  <div>\n    <span></span>\n    <span data-target=\"true\"></span>\n  </div>\n</div>\n<div class=\"test-case\" data-expect=\" > div:nth-of-type(1) > span:nth-of-type(2)\">\n  <div>\n    <span></span>\n    <p></p>\n    <span data-target=\"true\"></span>\n  </div>\n</div>\n<div class=\"test-case\" data-expect=\" > div:nth-of-type(1) > span:nth-of-type(1)\">\n  <div>\n    <span data-target=\"true\"></span>\n    <p></p>\n    <span></span>\n  </div>\n</div>\n<div class=\"test-case\" data-expect=\" > div:nth-of-type(1) > span:nth-of-type(1)\">\n  <div>\n    <span data-target=\"true\"></span>\n    <div>\n      <span></span>\n    </div>\n  </div>\n</div>\n<div class=\"test-case\" data-expect=\" > span:nth-of-type(1)\">\n  <a><span></span></a>\n  <span data-target=\"true\"></span>\n</div>"
  },
  {
    "path": "site/examples/friendlycode/test/preview-to-editor-mapping/test-preview-to-editor-mapping.js",
    "content": "defineTests([\n  \"jquery\",\n  \"fc/ui/preview-to-editor-mapping\",\n  \"test/lptest\",\n  \"text!test/preview-to-editor-mapping/path-to.html\"\n], function($, PreviewToEditorMapping, lpTest, pathToHTML) {\n  module(\"PreviewToEditorMapping\");\n  \n  var nodeToCode = PreviewToEditorMapping._nodeToCode;\n  var pathTo = PreviewToEditorMapping._pathTo;\n\n  function spaces(n) {\n    var s = [];\n    for (var i = 0; i < n; i++) s.push(\" \");\n    return s.join(\"\");\n  }\n  \n  function domStructure(node, lines, indent) {\n    if (!indent) indent = 0;\n    if (!lines) lines = [];\n    for (var i = 0; i < node.childNodes.length; i++) {\n      var child = node.childNodes[i];\n      lines.push(spaces(indent) + child.nodeName);\n      if (child.nodeType == node.ELEMENT_NODE)\n        domStructure(child, lines, indent + 2);\n    }\n    return lines.join('\\n');\n  }\n  \n  function n2cTest(options) {\n    var desc = \"in \" + JSON.stringify(options.html) + \", selector \" +\n               JSON.stringify(options.selector) + \" \";\n    lpTest(options.name,\n      options.html,\n      function(previewArea, preview, cm, docFrag, html) {\n        var originalDom = domStructure(docFrag);\n        var wind = previewArea.contents()[0].defaultView;\n        var p = wind.document.querySelector(options.selector);\n        if (!p)\n          throw new Error(\"selector doesn't map to anything\");\n        var interval = nodeToCode(p, docFrag);\n        if (!options.expect)\n          ok(interval === null, desc + \"doesn't map to any code\");\n        else\n          equal(html.slice(interval.start, interval.end), options.expect,\n                desc + \"maps to code \" + JSON.stringify(options.expect));\n        equal(domStructure(docFrag), originalDom,\n              \"DOM structure of document fragment is unchanged\");\n      });\n  }\n\n  n2cTest({\n    name: \"nodeToCode() works on HTML w/ explicit <html> and <body>\",\n    html: \"<html><body><p>u</p></body></html>\",\n    selector: \"p\",\n    expect: \"<p>u</p>\"\n  });\n\n  n2cTest({\n    name: \"nodeToCode() works on HTML w/ no <html> and <body>\",\n    html: \"<p>u</p>\",\n    selector: \"p\",\n    expect: \"<p>u</p>\"\n  });\n\n  n2cTest({\n    name: \"nodeToCode() works on HTML w/ <html> but no <body>\",\n    html: \"<html><p>u</p></html>\",\n    selector: \"p\",\n    expect: \"<p>u</p>\"\n  });\n\n  n2cTest({\n    name: \"nodeToCode() works on void element\",\n    html: '<html><img id=\"foo\"></html>',\n    selector: \"img\",\n    expect: '<img id=\"foo\">'\n  });\n\n  n2cTest({\n    name: \"nodeToCode() can't map to anything from implied <html>\",\n    html: \"<p>hi</p>\",\n    selector: \"html\",\n    expect: null\n  });\n\n  test(\"pathTo() works\", function() {\n    var div = $('<div></div>').html(pathToHTML);\n    div.find(\".test-case\").each(function() {\n      var root = this;\n\n      var expect = $(root).attr(\"data-expect\");\n      var target = $(root).find('[data-target=\"true\"]').get(0);\n      var actual = pathTo(root, target);\n      equal(actual, expect, \"actual CSS path is same as expected\");\n\n      var matches = $(root).find(expect);\n      if (matches.length != 1)\n        throw new Error(\"expected path does not uniquely identify element!\");\n      if (matches.get(0) !== target)\n        throw new Error(\"expected path is not actually valid!\");\n    });\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/publisher/post-publish.html",
    "content": "<!DOCTYPE html><html><head>\n    <title>hello</title>\n    <style>\n    p {\n      color: blue;\n    }\n    </style>\n  </head>\n  <body>\n    <p>Tinker with me.</p>\n  \n</body></html>"
  },
  {
    "path": "site/examples/friendlycode/test/publisher/pre-publish.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>hello</title>\n    <style>\n    p {\n      color: blue;\n    }\n    </style>\n  </head>\n  <body>\n    <p>Tinker with me.</p>\n  </body>\n</html>"
  },
  {
    "path": "site/examples/friendlycode/test/publisher/test-publisher.js",
    "content": "defineTests([\n  \"fc/publisher\",\n  \"text!test/publisher/pre-publish.html\",\n  \"text!test/publisher/post-publish.html\"\n], function(Publisher, prePublish, postPublish) {\n  module(\"Publisher\");\n\n  fixDoctypeHeadBodyMunging = Publisher._fixDoctypeHeadBodyMunging;\n  \n  test(\"fixDoctypeHeadBodyMunging() works\", function() {\n    equal(fixDoctypeHeadBodyMunging(postPublish), prePublish);\n  });\n\n  test(\"fixDoctypeHeadBodyMunging() ignores non-munged strings\", function() {\n    var html = '<!DOCTYPE html><html><head></head><body>hi</body></html>';\n    equal(fixDoctypeHeadBodyMunging(html), html);\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/qunit.css",
    "content": "/**\n * QUnit v1.6.0pre - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n/** Font Family and Sizes */\n\n#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n\tfont-family: \"Helvetica Neue Light\", \"HelveticaNeue-Light\", \"Helvetica Neue\", Calibri, Helvetica, Arial, sans-serif;\n}\n\n#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n#qunit-tests { font-size: smaller; }\n\n\n/** Resets */\n\n#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n\n/** Header */\n\n#qunit-header {\n\tpadding: 0.5em 0 0.5em 1em;\n\n\tcolor: #8699a4;\n\tbackground-color: #0d3349;\n\n\tfont-size: 1.5em;\n\tline-height: 1em;\n\tfont-weight: normal;\n\n\tborder-radius: 15px 15px 0 0;\n\t-moz-border-radius: 15px 15px 0 0;\n\t-webkit-border-top-right-radius: 15px;\n\t-webkit-border-top-left-radius: 15px;\n}\n\n#qunit-header a {\n\ttext-decoration: none;\n\tcolor: #c2ccd1;\n}\n\n#qunit-header a:hover,\n#qunit-header a:focus {\n\tcolor: #fff;\n}\n\n#qunit-header label {\n\tdisplay: inline-block;\n}\n\n#qunit-banner {\n\theight: 5px;\n}\n\n#qunit-testrunner-toolbar {\n\tpadding: 0.5em 0 0.5em 2em;\n\tcolor: #5E740B;\n\tbackground-color: #eee;\n}\n\n#qunit-userAgent {\n\tpadding: 0.5em 0 0.5em 2.5em;\n\tbackground-color: #2b81af;\n\tcolor: #fff;\n\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n}\n\n\n/** Tests: Pass/Fail */\n\n#qunit-tests {\n\tlist-style-position: inside;\n}\n\n#qunit-tests li {\n\tpadding: 0.4em 0.5em 0.4em 2.5em;\n\tborder-bottom: 1px solid #fff;\n\tlist-style-position: inside;\n}\n\n#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n\tdisplay: none;\n}\n\n#qunit-tests li strong {\n\tcursor: pointer;\n}\n\n#qunit-tests li a {\n\tpadding: 0.5em;\n\tcolor: #c2ccd1;\n\ttext-decoration: none;\n}\n#qunit-tests li a:hover,\n#qunit-tests li a:focus {\n\tcolor: #000;\n}\n\n#qunit-tests ol {\n\tmargin-top: 0.5em;\n\tpadding: 0.5em;\n\n\tbackground-color: #fff;\n\n\tborder-radius: 15px;\n\t-moz-border-radius: 15px;\n\t-webkit-border-radius: 15px;\n\n\tbox-shadow: inset 0px 2px 13px #999;\n\t-moz-box-shadow: inset 0px 2px 13px #999;\n\t-webkit-box-shadow: inset 0px 2px 13px #999;\n}\n\n#qunit-tests table {\n\tborder-collapse: collapse;\n\tmargin-top: .2em;\n}\n\n#qunit-tests th {\n\ttext-align: right;\n\tvertical-align: top;\n\tpadding: 0 .5em 0 0;\n}\n\n#qunit-tests td {\n\tvertical-align: top;\n}\n\n#qunit-tests pre {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\tword-wrap: break-word;\n}\n\n#qunit-tests del {\n\tbackground-color: #e0f2be;\n\tcolor: #374e0c;\n\ttext-decoration: none;\n}\n\n#qunit-tests ins {\n\tbackground-color: #ffcaca;\n\tcolor: #500;\n\ttext-decoration: none;\n}\n\n/*** Test Counts */\n\n#qunit-tests b.counts                       { color: black; }\n#qunit-tests b.passed                       { color: #5E740B; }\n#qunit-tests b.failed                       { color: #710909; }\n\n#qunit-tests li li {\n\tmargin: 0.5em;\n\tpadding: 0.4em 0.5em 0.4em 0.5em;\n\tbackground-color: #fff;\n\tborder-bottom: none;\n\tlist-style-position: inside;\n}\n\n/*** Passing Styles */\n\n#qunit-tests li li.pass {\n\tcolor: #5E740B;\n\tbackground-color: #fff;\n\tborder-left: 26px solid #C6E746;\n}\n\n#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n#qunit-tests .pass .test-name               { color: #366097; }\n\n#qunit-tests .pass .test-actual,\n#qunit-tests .pass .test-expected           { color: #999999; }\n\n#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n\n/*** Failing Styles */\n\n#qunit-tests li li.fail {\n\tcolor: #710909;\n\tbackground-color: #fff;\n\tborder-left: 26px solid #EE5757;\n\twhite-space: pre;\n}\n\n#qunit-tests > li:last-child {\n\tborder-radius: 0 0 15px 15px;\n\t-moz-border-radius: 0 0 15px 15px;\n\t-webkit-border-bottom-right-radius: 15px;\n\t-webkit-border-bottom-left-radius: 15px;\n}\n\n#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }\n#qunit-tests .fail .test-name,\n#qunit-tests .fail .module-name             { color: #000000; }\n\n#qunit-tests .fail .test-actual             { color: #EE5757; }\n#qunit-tests .fail .test-expected           { color: green;   }\n\n#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n\n\n/** Result */\n\n#qunit-testresult {\n\tpadding: 0.5em 0.5em 0.5em 2.5em;\n\n\tcolor: #2b81af;\n\tbackground-color: #D2E0E6;\n\n\tborder-bottom: 1px solid white;\n}\n#qunit-testresult .module-name {\n\tfont-weight: bold;\n}\n\n/** Fixture */\n\n#qunit-fixture {\n\tposition: absolute;\n\ttop: -10000px;\n\tleft: -10000px;\n\twidth: 1000px;\n\theight: 1000px;\n}\n"
  },
  {
    "path": "site/examples/friendlycode/test/qunit.js",
    "content": "/**\n * QUnit v1.6.0pre - A JavaScript Unit Testing Framework\n *\n * http://docs.jquery.com/QUnit\n *\n * Copyright (c) 2012 John Resig, Jörn Zaefferer\n * Dual licensed under the MIT (MIT-LICENSE.txt)\n * or GPL (GPL-LICENSE.txt) licenses.\n */\n\n(function(window) {\n\nvar defined = {\n\tsetTimeout: typeof window.setTimeout !== \"undefined\",\n\tsessionStorage: (function() {\n\t\tvar x = \"qunit-test-string\";\n\t\ttry {\n\t\t\tsessionStorage.setItem(x, x);\n\t\t\tsessionStorage.removeItem(x);\n\t\t\treturn true;\n\t\t} catch(e) {\n\t\t\treturn false;\n\t\t}\n\t}())\n};\n\nvar\ttestId = 0,\n\ttoString = Object.prototype.toString,\n\thasOwn = Object.prototype.hasOwnProperty;\n\nvar Test = function(name, testName, expected, async, callback) {\n\tthis.name = name;\n\tthis.testName = testName;\n\tthis.expected = expected;\n\tthis.async = async;\n\tthis.callback = callback;\n\tthis.assertions = [];\n};\nTest.prototype = {\n\tinit: function() {\n\t\tvar tests = id(\"qunit-tests\");\n\t\tif (tests) {\n\t\t\tvar b = document.createElement(\"strong\");\n\t\t\t\tb.innerHTML = \"Running \" + this.name;\n\t\t\tvar li = document.createElement(\"li\");\n\t\t\t\tli.appendChild( b );\n\t\t\t\tli.className = \"running\";\n\t\t\t\tli.id = this.id = \"test-output\" + testId++;\n\t\t\ttests.appendChild( li );\n\t\t}\n\t},\n\tsetup: function() {\n\t\tif (this.module != config.previousModule) {\n\t\t\tif ( config.previousModule ) {\n\t\t\t\trunLoggingCallbacks('moduleDone', QUnit, {\n\t\t\t\t\tname: config.previousModule,\n\t\t\t\t\tfailed: config.moduleStats.bad,\n\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\t\t\ttotal: config.moduleStats.all\n\t\t\t\t} );\n\t\t\t}\n\t\t\tconfig.previousModule = this.module;\n\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n\t\t\trunLoggingCallbacks( 'moduleStart', QUnit, {\n\t\t\t\tname: this.module\n\t\t\t} );\n\t\t} else if (config.autorun) {\n\t\t\trunLoggingCallbacks( 'moduleStart', QUnit, {\n\t\t\t\tname: this.module\n\t\t\t} );\n\t\t}\n\n\t\tconfig.current = this;\n\t\tthis.testEnvironment = extend({\n\t\t\tsetup: function() {},\n\t\t\tteardown: function() {}\n\t\t}, this.moduleTestEnvironment);\n\n\t\trunLoggingCallbacks( 'testStart', QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module\n\t\t});\n\n\t\t// allow utility functions to access the current test environment\n\t\t// TODO why??\n\t\tQUnit.current_testEnvironment = this.testEnvironment;\n\n\t\tif ( !config.pollution ) {\n\t\t\tsaveGlobal();\n\t\t}\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.setup.call(this.testEnvironment);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.testEnvironment.setup.call(this.testEnvironment);\n\t\t} catch(e) {\n\t\t\tQUnit.pushFailure( \"Setup failed on \" + this.testName + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t}\n\t},\n\trun: function() {\n\t\tconfig.current = this;\n\n\t\tvar running = id(\"qunit-testresult\");\n\n\t\tif ( running ) {\n\t\t\trunning.innerHTML = \"Running: <br/>\" + this.name;\n\t\t}\n\n\t\tif ( this.async ) {\n\t\t\tQUnit.stop();\n\t\t}\n\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.callback.call(this.testEnvironment);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tthis.callback.call(this.testEnvironment);\n\t\t} catch(e) {\n\t\t\tQUnit.pushFailure( \"Died on test #\" + (this.assertions.length + 1) + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t\t// else next test will carry the responsibility\n\t\t\tsaveGlobal();\n\n\t\t\t// Restart the tests if they're blocking\n\t\t\tif ( config.blocking ) {\n\t\t\t\tQUnit.start();\n\t\t\t}\n\t\t}\n\t},\n\tteardown: function() {\n\t\tconfig.current = this;\n\t\tif ( config.notrycatch ) {\n\t\t\tthis.testEnvironment.teardown.call(this.testEnvironment);\n\t\t\treturn;\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tthis.testEnvironment.teardown.call(this.testEnvironment);\n\t\t\t} catch(e) {\n\t\t\t\tQUnit.pushFailure( \"Teardown failed on \" + this.testName + \": \" + e.message, extractStacktrace( e, 1 ) );\n\t\t\t}\n\t\t}\n\t\tcheckPollution();\n\t},\n\tfinish: function() {\n\t\tconfig.current = this;\n\t\tif ( this.expected != null && this.expected != this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected \" + this.expected + \" assertions, but \" + this.assertions.length + \" were run\" );\n\t\t} else if ( this.expected == null && !this.assertions.length ) {\n\t\t\tQUnit.pushFailure( \"Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.\" );\n\t\t}\n\n\t\tvar good = 0, bad = 0,\n\t\t\tli, i,\n\t\t\ttests = id(\"qunit-tests\");\n\n\t\tconfig.stats.all += this.assertions.length;\n\t\tconfig.moduleStats.all += this.assertions.length;\n\n\t\tif ( tests ) {\n\t\t\tvar ol = document.createElement(\"ol\");\n\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tvar assertion = this.assertions[i];\n\n\t\t\t\tli = document.createElement(\"li\");\n\t\t\t\tli.className = assertion.result ? \"pass\" : \"fail\";\n\t\t\t\tli.innerHTML = assertion.message || (assertion.result ? \"okay\" : \"failed\");\n\t\t\t\tol.appendChild( li );\n\n\t\t\t\tif ( assertion.result ) {\n\t\t\t\t\tgood++;\n\t\t\t\t} else {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// store result when possible\n\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n\t\t\t\tif (bad) {\n\t\t\t\t\tsessionStorage.setItem(\"qunit-test-\" + this.module + \"-\" + this.testName, bad);\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem(\"qunit-test-\" + this.module + \"-\" + this.testName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bad === 0) {\n\t\t\t\tol.style.display = \"none\";\n\t\t\t}\n\n\t\t\tvar b = document.createElement(\"strong\");\n\t\t\tb.innerHTML = this.name + \" <b class='counts'>(<b class='failed'>\" + bad + \"</b>, <b class='passed'>\" + good + \"</b>, \" + this.assertions.length + \")</b>\";\n\n\t\t\tvar a = document.createElement(\"a\");\n\t\t\ta.innerHTML = \"Rerun\";\n\t\t\ta.href = QUnit.url({ filter: getText([b]).replace(/\\([^)]+\\)$/, \"\").replace(/(^\\s*|\\s*$)/g, \"\") });\n\n\t\t\taddEvent(b, \"click\", function() {\n\t\t\t\tvar next = b.nextSibling.nextSibling,\n\t\t\t\t\tdisplay = next.style.display;\n\t\t\t\tnext.style.display = display === \"none\" ? \"block\" : \"none\";\n\t\t\t});\n\n\t\t\taddEvent(b, \"dblclick\", function(e) {\n\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n\t\t\t\tif ( target.nodeName.toLowerCase() == \"span\" || target.nodeName.toLowerCase() == \"b\" ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === \"strong\" ) {\n\t\t\t\t\twindow.location = QUnit.url({ filter: getText([target]).replace(/\\([^)]+\\)$/, \"\").replace(/(^\\s*|\\s*$)/g, \"\") });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tli = id(this.id);\n\t\t\tli.className = bad ? \"fail\" : \"pass\";\n\t\t\tli.removeChild( li.firstChild );\n\t\t\tli.appendChild( b );\n\t\t\tli.appendChild( a );\n\t\t\tli.appendChild( ol );\n\n\t\t} else {\n\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n\t\t\t\tif ( !this.assertions[i].result ) {\n\t\t\t\t\tbad++;\n\t\t\t\t\tconfig.stats.bad++;\n\t\t\t\t\tconfig.moduleStats.bad++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tQUnit.reset();\n\n\t\trunLoggingCallbacks( 'testDone', QUnit, {\n\t\t\tname: this.testName,\n\t\t\tmodule: this.module,\n\t\t\tfailed: bad,\n\t\t\tpassed: this.assertions.length - bad,\n\t\t\ttotal: this.assertions.length\n\t\t} );\n\t},\n\n\tqueue: function() {\n\t\tvar test = this;\n\t\tsynchronize(function() {\n\t\t\ttest.init();\n\t\t});\n\t\tfunction run() {\n\t\t\t// each of these can by async\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.setup();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.run();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.teardown();\n\t\t\t});\n\t\t\tsynchronize(function() {\n\t\t\t\ttest.finish();\n\t\t\t});\n\t\t}\n\t\t// defer when previous test run passed, if storage is available\n\t\tvar bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem(\"qunit-test-\" + this.module + \"-\" + this.testName);\n\t\tif (bad) {\n\t\t\trun();\n\t\t} else {\n\t\t\tsynchronize(run, true);\n\t\t}\n\t}\n\n};\n\nvar QUnit = {\n\n\t// call on start of module test to prepend name to all tests\n\tmodule: function(name, testEnvironment) {\n\t\tconfig.currentModule = name;\n\t\tconfig.currentModuleTestEnviroment = testEnvironment;\n\t},\n\n\tasyncTest: function(testName, expected, callback) {\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tQUnit.test(testName, expected, callback, true);\n\t},\n\n\ttest: function(testName, expected, callback, async) {\n\t\tvar name = '<span class=\"test-name\">' + escapeInnerText(testName) + '</span>';\n\n\t\tif ( arguments.length === 2 ) {\n\t\t\tcallback = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\tif ( config.currentModule ) {\n\t\t\tname = '<span class=\"module-name\">' + config.currentModule + \"</span>: \" + name;\n\t\t}\n\n\t\tif ( !validTest(config.currentModule + \": \" + testName) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar test = new Test(name, testName, expected, async, callback);\n\t\ttest.module = config.currentModule;\n\t\ttest.moduleTestEnvironment = config.currentModuleTestEnviroment;\n\t\ttest.queue();\n\t},\n\n\t// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.\n\texpect: function(asserts) {\n\t\tconfig.current.expected = asserts;\n\t},\n\n\t// Asserts true.\n\t// @example ok( \"asdfasdf\".length > 5, \"There must be at least 5 chars\" );\n\tok: function(result, msg) {\n\t\tif (!config.current) {\n\t\t\tthrow new Error(\"ok() assertion outside test context, was \" + sourceFromStacktrace(2));\n\t\t}\n\t\tresult = !!result;\n\t\tvar details = {\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t};\n\t\tmsg = escapeInnerText(msg || (result ? \"okay\" : \"failed\"));\n\t\tif ( !result ) {\n\t\t\tvar source = sourceFromStacktrace(2);\n\t\t\tif (source) {\n\t\t\t\tdetails.source = source;\n\t\t\t\tmsg += '<table><tr class=\"test-source\"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>';\n\t\t\t}\n\t\t}\n\t\trunLoggingCallbacks( 'log', QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: result,\n\t\t\tmessage: msg\n\t\t});\n\t},\n\n\t// Checks that the first two arguments are equal, with an optional message. Prints out both actual and expected values.\n\t// @example equal( format(\"Received {0} bytes.\", 2), \"Received 2 bytes.\" );\n\tequal: function(actual, expected, message) {\n\t\tQUnit.push(expected == actual, actual, expected, message);\n\t},\n\n\tnotEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected != actual, actual, expected, message);\n\t},\n\n\tdeepEqual: function(actual, expected, message) {\n\t\tQUnit.push(QUnit.equiv(actual, expected), actual, expected, message);\n\t},\n\n\tnotDeepEqual: function(actual, expected, message) {\n\t\tQUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);\n\t},\n\n\tstrictEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected === actual, actual, expected, message);\n\t},\n\n\tnotStrictEqual: function(actual, expected, message) {\n\t\tQUnit.push(expected !== actual, actual, expected, message);\n\t},\n\n\traises: function(block, expected, message) {\n\t\tvar actual, ok = false;\n\n\t\tif (typeof expected === 'string') {\n\t\t\tmessage = expected;\n\t\t\texpected = null;\n\t\t}\n\n\t\ttry {\n\t\t\tblock.call(config.current.testEnvironment);\n\t\t} catch (e) {\n\t\t\tactual = e;\n\t\t}\n\n\t\tif (actual) {\n\t\t\t// we don't want to validate thrown error\n\t\t\tif (!expected) {\n\t\t\t\tok = true;\n\t\t\t// expected is a regexp\n\t\t\t} else if (QUnit.objectType(expected) === \"regexp\") {\n\t\t\t\tok = expected.test(actual);\n\t\t\t// expected is a constructor\n\t\t\t} else if (actual instanceof expected) {\n\t\t\t\tok = true;\n\t\t\t// expected is a validation function which returns true is validation passed\n\t\t\t} else if (expected.call({}, actual) === true) {\n\t\t\t\tok = true;\n\t\t\t}\n\t\t}\n\n\t\tQUnit.ok(ok, message);\n\t},\n\n\tstart: function(count) {\n\t\tconfig.semaphore -= count || 1;\n\t\tif (config.semaphore > 0) {\n\t\t\t// don't start until equal number of stop-calls\n\t\t\treturn;\n\t\t}\n\t\tif (config.semaphore < 0) {\n\t\t\t// ignore if start is called more often then stop\n\t\t\tconfig.semaphore = 0;\n\t\t}\n\t\t// A slight delay, to avoid any current callbacks\n\t\tif ( defined.setTimeout ) {\n\t\t\twindow.setTimeout(function() {\n\t\t\t\tif (config.semaphore > 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( config.timeout ) {\n\t\t\t\t\tclearTimeout(config.timeout);\n\t\t\t\t}\n\n\t\t\t\tconfig.blocking = false;\n\t\t\t\tprocess(true);\n\t\t\t}, 13);\n\t\t} else {\n\t\t\tconfig.blocking = false;\n\t\t\tprocess(true);\n\t\t}\n\t},\n\n\tstop: function(count) {\n\t\tconfig.semaphore += count || 1;\n\t\tconfig.blocking = true;\n\n\t\tif ( config.testTimeout && defined.setTimeout ) {\n\t\t\tclearTimeout(config.timeout);\n\t\t\tconfig.timeout = window.setTimeout(function() {\n\t\t\t\tQUnit.ok( false, \"Test timed out\" );\n\t\t\t\tconfig.semaphore = 1;\n\t\t\t\tQUnit.start();\n\t\t\t}, config.testTimeout);\n\t\t}\n\t}\n};\n\n//We want access to the constructor's prototype\n(function() {\n\tfunction F(){}\n\tF.prototype = QUnit;\n\tQUnit = new F();\n\t//Make F QUnit's constructor so that we can add to the prototype later\n\tQUnit.constructor = F;\n}());\n\n// deprecated; still export them to window to provide clear error messages\n// next step: remove entirely\nQUnit.equals = function() {\n\tQUnit.push(false, false, false, \"QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead\");\n};\nQUnit.same = function() {\n\tQUnit.push(false, false, false, \"QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead\");\n};\n\n// Maintain internal state\nvar config = {\n\t// The queue of tests to run\n\tqueue: [],\n\n\t// block until document ready\n\tblocking: true,\n\n\t// when enabled, show only failing tests\n\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n\thidepassed: false,\n\n\t// by default, run previously failed tests first\n\t// very useful in combination with \"Hide passed tests\" checked\n\treorder: true,\n\n\t// by default, modify document.title when suite is done\n\taltertitle: true,\n\n\turlConfig: ['noglobals', 'notrycatch'],\n\n\t//logging callback queues\n\tbegin: [],\n\tdone: [],\n\tlog: [],\n\ttestStart: [],\n\ttestDone: [],\n\tmoduleStart: [],\n\tmoduleDone: []\n};\n\n// Load paramaters\n(function() {\n\tvar location = window.location || { search: \"\", protocol: \"file:\" },\n\t\tparams = location.search.slice( 1 ).split( \"&\" ),\n\t\tlength = params.length,\n\t\turlParams = {},\n\t\tcurrent;\n\n\tif ( params[ 0 ] ) {\n\t\tfor ( var i = 0; i < length; i++ ) {\n\t\t\tcurrent = params[ i ].split( \"=\" );\n\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n\t\t}\n\t}\n\n\tQUnit.urlParams = urlParams;\n\tconfig.filter = urlParams.filter;\n\n\t// Figure out if we're running the tests from a server or not\n\tQUnit.isLocal = location.protocol === 'file:';\n}());\n\n// Expose the API as global variables, unless an 'exports'\n// object exists, in that case we assume we're in CommonJS - export everything at the end\nif ( typeof exports === \"undefined\" || typeof require === \"undefined\" ) {\n\textend(window, QUnit);\n\twindow.QUnit = QUnit;\n}\n\n// define these after exposing globals to keep them in these QUnit namespace only\nextend(QUnit, {\n\tconfig: config,\n\n\t// Initialize the configuration options\n\tinit: function() {\n\t\textend(config, {\n\t\t\tstats: { all: 0, bad: 0 },\n\t\t\tmoduleStats: { all: 0, bad: 0 },\n\t\t\tstarted: +new Date(),\n\t\t\tupdateRate: 1000,\n\t\t\tblocking: false,\n\t\t\tautostart: true,\n\t\t\tautorun: false,\n\t\t\tfilter: \"\",\n\t\t\tqueue: [],\n\t\t\tsemaphore: 0\n\t\t});\n\n\t\tvar qunit = id( \"qunit\" );\n\t\tif ( qunit ) {\n\t\t\tqunit.innerHTML =\n\t\t\t\t'<h1 id=\"qunit-header\">' + escapeInnerText( document.title ) + '</h1>' +\n\t\t\t\t'<h2 id=\"qunit-banner\"></h2>' +\n\t\t\t\t'<div id=\"qunit-testrunner-toolbar\"></div>' +\n\t\t\t\t'<h2 id=\"qunit-userAgent\"></h2>' +\n\t\t\t\t'<ol id=\"qunit-tests\"></ol>';\n\t\t}\n\n\t\tvar tests = id( \"qunit-tests\" ),\n\t\t\tbanner = id( \"qunit-banner\" ),\n\t\t\tresult = id( \"qunit-testresult\" );\n\n\t\tif ( tests ) {\n\t\t\ttests.innerHTML = \"\";\n\t\t}\n\n\t\tif ( banner ) {\n\t\t\tbanner.className = \"\";\n\t\t}\n\n\t\tif ( result ) {\n\t\t\tresult.parentNode.removeChild( result );\n\t\t}\n\n\t\tif ( tests ) {\n\t\t\tresult = document.createElement( \"p\" );\n\t\t\tresult.id = \"qunit-testresult\";\n\t\t\tresult.className = \"result\";\n\t\t\ttests.parentNode.insertBefore( result, tests );\n\t\t\tresult.innerHTML = 'Running...<br/>&nbsp;';\n\t\t}\n\t},\n\n\t// Resets the test setup. Useful for tests that modify the DOM.\n\t// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.\n\treset: function() {\n\t\tif ( window.jQuery ) {\n\t\t\tjQuery( \"#qunit-fixture\" ).html( config.fixture );\n\t\t} else {\n\t\t\tvar main = id( 'qunit-fixture' );\n\t\t\tif ( main ) {\n\t\t\t\tmain.innerHTML = config.fixture;\n\t\t\t}\n\t\t}\n\t},\n\n\t// Trigger an event on an element.\n\t// @example triggerEvent( document.body, \"click\" );\n\ttriggerEvent: function( elem, type, event ) {\n\t\tif ( document.createEvent ) {\n\t\t\tevent = document.createEvent(\"MouseEvents\");\n\t\t\tevent.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,\n\t\t\t\t0, 0, 0, 0, 0, false, false, false, false, 0, null);\n\t\t\telem.dispatchEvent( event );\n\n\t\t} else if ( elem.fireEvent ) {\n\t\t\telem.fireEvent(\"on\"+type);\n\t\t}\n\t},\n\n\t// Safe object type checking\n\tis: function( type, obj ) {\n\t\treturn QUnit.objectType( obj ) == type;\n\t},\n\n\tobjectType: function( obj ) {\n\t\tif (typeof obj === \"undefined\") {\n\t\t\t\treturn \"undefined\";\n\n\t\t// consider: typeof null === object\n\t\t}\n\t\tif (obj === null) {\n\t\t\t\treturn \"null\";\n\t\t}\n\n\t\tvar type = toString.call( obj ).match(/^\\[object\\s(.*)\\]$/)[1] || '';\n\n\t\tswitch (type) {\n\t\t\tcase 'Number':\n\t\t\t\tif (isNaN(obj)) {\n\t\t\t\t\treturn \"nan\";\n\t\t\t\t}\n\t\t\t\treturn \"number\";\n\t\t\tcase 'String':\n\t\t\tcase 'Boolean':\n\t\t\tcase 'Array':\n\t\t\tcase 'Date':\n\t\t\tcase 'RegExp':\n\t\t\tcase 'Function':\n\t\t\t\t\treturn type.toLowerCase();\n\t\t}\n\t\tif (typeof obj === \"object\") {\n\t\t\t\treturn \"object\";\n\t\t}\n\t\treturn undefined;\n\t},\n\n\tpush: function(result, actual, expected, message) {\n\t\tif (!config.current) {\n\t\t\tthrow new Error(\"assertion outside test context, was \" + sourceFromStacktrace());\n\t\t}\n\t\tvar details = {\n\t\t\tresult: result,\n\t\t\tmessage: message,\n\t\t\tactual: actual,\n\t\t\texpected: expected\n\t\t};\n\n\t\tmessage = escapeInnerText(message) || (result ? \"okay\" : \"failed\");\n\t\tmessage = '<span class=\"test-message\">' + message + \"</span>\";\n\t\tvar output = message;\n\t\tif (!result) {\n\t\t\texpected = escapeInnerText(QUnit.jsDump.parse(expected));\n\t\t\tactual = escapeInnerText(QUnit.jsDump.parse(actual));\n\t\t\toutput += '<table><tr class=\"test-expected\"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';\n\t\t\tif (actual != expected) {\n\t\t\t\toutput += '<tr class=\"test-actual\"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';\n\t\t\t\toutput += '<tr class=\"test-diff\"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';\n\t\t\t}\n\t\t\tvar source = sourceFromStacktrace();\n\t\t\tif (source) {\n\t\t\t\tdetails.source = source;\n\t\t\t\toutput += '<tr class=\"test-source\"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr>';\n\t\t\t}\n\t\t\toutput += \"</table>\";\n\t\t}\n\n\t\trunLoggingCallbacks( 'log', QUnit, details );\n\n\t\tconfig.current.assertions.push({\n\t\t\tresult: !!result,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\tpushFailure: function(message, source) {\n\t\tvar details = {\n\t\t\tresult: false,\n\t\t\tmessage: message\n\t\t};\n\t\tvar output = escapeInnerText(message);\n\t\tif (source) {\n\t\t\tdetails.source = source;\n\t\t\toutput += '<table><tr class=\"test-source\"><th>Source: </th><td><pre>' + escapeInnerText(source) + '</pre></td></tr></table>';\n\t\t}\n\t\trunLoggingCallbacks( 'log', QUnit, details );\n\t\tconfig.current.assertions.push({\n\t\t\tresult: false,\n\t\t\tmessage: output\n\t\t});\n\t},\n\n\turl: function( params ) {\n\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n\t\tvar querystring = \"?\",\n\t\t\tkey;\n\t\tfor ( key in params ) {\n\t\t\tif ( !hasOwn.call( params, key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tquerystring += encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( params[ key ] ) + \"&\";\n\t\t}\n\t\treturn window.location.pathname + querystring.slice( 0, -1 );\n\t},\n\n\textend: extend,\n\tid: id,\n\taddEvent: addEvent\n});\n\n//QUnit.constructor is set to the empty F() above so that we can add to it's prototype later\n//Doing this allows us to tell if the following methods have been overwritten on the actual\n//QUnit object, which is a deprecated way of using the callbacks.\nextend(QUnit.constructor.prototype, {\n\t// Logging callbacks; all receive a single argument with the listed properties\n\t// run test/logs.html for any related changes\n\tbegin: registerLoggingCallback('begin'),\n\t// done: { failed, passed, total, runtime }\n\tdone: registerLoggingCallback('done'),\n\t// log: { result, actual, expected, message }\n\tlog: registerLoggingCallback('log'),\n\t// testStart: { name }\n\ttestStart: registerLoggingCallback('testStart'),\n\t// testDone: { name, failed, passed, total }\n\ttestDone: registerLoggingCallback('testDone'),\n\t// moduleStart: { name }\n\tmoduleStart: registerLoggingCallback('moduleStart'),\n\t// moduleDone: { name, failed, passed, total }\n\tmoduleDone: registerLoggingCallback('moduleDone')\n});\n\nif ( typeof document === \"undefined\" || document.readyState === \"complete\" ) {\n\tconfig.autorun = true;\n}\n\nQUnit.load = function() {\n\trunLoggingCallbacks( 'begin', QUnit, {} );\n\n\t// Initialize the config, saving the execution queue\n\tvar oldconfig = extend({}, config);\n\tQUnit.init();\n\textend(config, oldconfig);\n\n\tconfig.blocking = false;\n\n\tvar urlConfigHtml = '', len = config.urlConfig.length;\n\tfor ( var i = 0, val; i < len; i++ ) {\n\t\tval = config.urlConfig[i];\n\t\tconfig[val] = QUnit.urlParams[val];\n\t\turlConfigHtml += '<label><input name=\"' + val + '\" type=\"checkbox\"' + ( config[val] ? ' checked=\"checked\"' : '' ) + '>' + val + '</label>';\n\t}\n\n\tvar userAgent = id(\"qunit-userAgent\");\n\tif ( userAgent ) {\n\t\tuserAgent.innerHTML = navigator.userAgent;\n\t}\n\tvar banner = id(\"qunit-header\");\n\tif ( banner ) {\n\t\tbanner.innerHTML = '<a href=\"' + QUnit.url({ filter: undefined }) + '\"> ' + banner.innerHTML + '</a> ' + urlConfigHtml;\n\t\taddEvent( banner, \"change\", function( event ) {\n\t\t\tvar params = {};\n\t\t\tparams[ event.target.name ] = event.target.checked ? true : undefined;\n\t\t\twindow.location = QUnit.url( params );\n\t\t});\n\t}\n\n\tvar toolbar = id(\"qunit-testrunner-toolbar\");\n\tif ( toolbar ) {\n\t\tvar filter = document.createElement(\"input\");\n\t\tfilter.type = \"checkbox\";\n\t\tfilter.id = \"qunit-filter-pass\";\n\t\taddEvent( filter, \"click\", function() {\n\t\t\tvar ol = document.getElementById(\"qunit-tests\");\n\t\t\tif ( filter.checked ) {\n\t\t\t\tol.className = ol.className + \" hidepass\";\n\t\t\t} else {\n\t\t\t\tvar tmp = \" \" + ol.className.replace( /[\\n\\t\\r]/g, \" \" ) + \" \";\n\t\t\t\tol.className = tmp.replace(/ hidepass /, \" \");\n\t\t\t}\n\t\t\tif ( defined.sessionStorage ) {\n\t\t\t\tif (filter.checked) {\n\t\t\t\t\tsessionStorage.setItem(\"qunit-filter-passed-tests\", \"true\");\n\t\t\t\t} else {\n\t\t\t\t\tsessionStorage.removeItem(\"qunit-filter-passed-tests\");\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem(\"qunit-filter-passed-tests\") ) {\n\t\t\tfilter.checked = true;\n\t\t\tvar ol = document.getElementById(\"qunit-tests\");\n\t\t\tol.className = ol.className + \" hidepass\";\n\t\t}\n\t\ttoolbar.appendChild( filter );\n\n\t\tvar label = document.createElement(\"label\");\n\t\tlabel.setAttribute(\"for\", \"qunit-filter-pass\");\n\t\tlabel.innerHTML = \"Hide passed tests\";\n\t\ttoolbar.appendChild( label );\n\t}\n\n\tvar main = id('qunit-fixture');\n\tif ( main ) {\n\t\tconfig.fixture = main.innerHTML;\n\t}\n\n\tif (config.autostart) {\n\t\tQUnit.start();\n\t}\n};\n\naddEvent(window, \"load\", QUnit.load);\n\n// addEvent(window, \"error\") gives us a useless event object\nwindow.onerror = function( message, file, line ) {\n\tif ( QUnit.config.current ) {\n\t\tQUnit.pushFailure( message, file + \":\" + line );\n\t} else {\n\t\tQUnit.test( \"global failure\", function() {\n\t\t\tQUnit.pushFailure( message, file + \":\" + line );\n\t\t});\n\t}\n};\n\nfunction done() {\n\tconfig.autorun = true;\n\n\t// Log the last module results\n\tif ( config.currentModule ) {\n\t\trunLoggingCallbacks( 'moduleDone', QUnit, {\n\t\t\tname: config.currentModule,\n\t\t\tfailed: config.moduleStats.bad,\n\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n\t\t\ttotal: config.moduleStats.all\n\t\t} );\n\t}\n\n\tvar banner = id(\"qunit-banner\"),\n\t\ttests = id(\"qunit-tests\"),\n\t\truntime = +new Date() - config.started,\n\t\tpassed = config.stats.all - config.stats.bad,\n\t\thtml = [\n\t\t\t'Tests completed in ',\n\t\t\truntime,\n\t\t\t' milliseconds.<br/>',\n\t\t\t'<span class=\"passed\">',\n\t\t\tpassed,\n\t\t\t'</span> tests of <span class=\"total\">',\n\t\t\tconfig.stats.all,\n\t\t\t'</span> passed, <span class=\"failed\">',\n\t\t\tconfig.stats.bad,\n\t\t\t'</span> failed.'\n\t\t].join('');\n\n\tif ( banner ) {\n\t\tbanner.className = (config.stats.bad ? \"qunit-fail\" : \"qunit-pass\");\n\t}\n\n\tif ( tests ) {\n\t\tid( \"qunit-testresult\" ).innerHTML = html;\n\t}\n\n\tif ( config.altertitle && typeof document !== \"undefined\" && document.title ) {\n\t\t// show ✖ for good, ✔ for bad suite result in title\n\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n\t\tdocument.title = [\n\t\t\t(config.stats.bad ? \"\\u2716\" : \"\\u2714\"),\n\t\t\tdocument.title.replace(/^[\\u2714\\u2716] /i, \"\")\n\t\t].join(\" \");\n\t}\n\n\t// clear own sessionStorage items if all tests passed\n\tif ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {\n\t\tvar key;\n\t\tfor ( var i = 0; i < sessionStorage.length; i++ ) {\n\t\t\tkey = sessionStorage.key( i++ );\n\t\t\tif ( key.indexOf(\"qunit-test-\") === 0 ) {\n\t\t\t\tsessionStorage.removeItem( key );\n\t\t\t}\n\t\t}\n\t}\n\n\trunLoggingCallbacks( 'done', QUnit, {\n\t\tfailed: config.stats.bad,\n\t\tpassed: passed,\n\t\ttotal: config.stats.all,\n\t\truntime: runtime\n\t} );\n}\n\nfunction validTest( name ) {\n\tvar filter = config.filter,\n\t\trun = false;\n\n\tif ( !filter ) {\n\t\treturn true;\n\t}\n\n\tvar not = filter.charAt( 0 ) === \"!\";\n\tif ( not ) {\n\t\tfilter = filter.slice( 1 );\n\t}\n\n\tif ( name.indexOf( filter ) !== -1 ) {\n\t\treturn !not;\n\t}\n\n\tif ( not ) {\n\t\trun = true;\n\t}\n\n\treturn run;\n}\n\n// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n// Later Safari and IE10 are supposed to support error.stack as well\n// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\nfunction extractStacktrace( e, offset ) {\n\toffset = offset || 3;\n\tif (e.stacktrace) {\n\t\t// Opera\n\t\treturn e.stacktrace.split(\"\\n\")[offset + 3];\n\t} else if (e.stack) {\n\t\t// Firefox, Chrome\n\t\tvar stack = e.stack.split(\"\\n\");\n\t\tif (/^error$/i.test(stack[0])) {\n\t\t\tstack.shift();\n\t\t}\n\t\treturn stack[offset];\n\t} else if (e.sourceURL) {\n\t\t// Safari, PhantomJS\n\t\t// hopefully one day Safari provides actual stacktraces\n\t\t// exclude useless self-reference for generated Error objects\n\t\tif ( /qunit.js$/.test( e.sourceURL ) ) {\n\t\t\treturn;\n\t\t}\n\t\t// for actual exceptions, this is useful\n\t\treturn e.sourceURL + \":\" + e.line;\n\t}\n}\nfunction sourceFromStacktrace(offset) {\n\ttry {\n\t\tthrow new Error();\n\t} catch ( e ) {\n\t\treturn extractStacktrace( e, offset );\n\t}\n}\n\nfunction escapeInnerText(s) {\n\tif (!s) {\n\t\treturn \"\";\n\t}\n\ts = s + \"\";\n\treturn s.replace(/[\\&<>]/g, function(s) {\n\t\tswitch(s) {\n\t\t\tcase \"&\": return \"&amp;\";\n\t\t\tcase \"<\": return \"&lt;\";\n\t\t\tcase \">\": return \"&gt;\";\n\t\t\tdefault: return s;\n\t\t}\n\t});\n}\n\nfunction synchronize( callback, last ) {\n\tconfig.queue.push( callback );\n\n\tif ( config.autorun && !config.blocking ) {\n\t\tprocess(last);\n\t}\n}\n\nfunction process( last ) {\n\tfunction next() {\n\t\tprocess( last );\n\t}\n\tvar start = new Date().getTime();\n\tconfig.depth = config.depth ? config.depth + 1 : 1;\n\n\twhile ( config.queue.length && !config.blocking ) {\n\t\tif ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {\n\t\t\tconfig.queue.shift()();\n\t\t} else {\n\t\t\twindow.setTimeout( next, 13 );\n\t\t\tbreak;\n\t\t}\n\t}\n\tconfig.depth--;\n\tif ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {\n\t\tdone();\n\t}\n}\n\nfunction saveGlobal() {\n\tconfig.pollution = [];\n\n\tif ( config.noglobals ) {\n\t\tfor ( var key in window ) {\n\t\t\tif ( !hasOwn.call( window, key ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconfig.pollution.push( key );\n\t\t}\n\t}\n}\n\nfunction checkPollution( name ) {\n\tvar old = config.pollution;\n\tsaveGlobal();\n\n\tvar newGlobals = diff( config.pollution, old );\n\tif ( newGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Introduced global variable(s): \" + newGlobals.join(\", \") );\n\t}\n\n\tvar deletedGlobals = diff( old, config.pollution );\n\tif ( deletedGlobals.length > 0 ) {\n\t\tQUnit.pushFailure( \"Deleted global variable(s): \" + deletedGlobals.join(\", \") );\n\t}\n}\n\n// returns a new Array with the elements that are in a but not in b\nfunction diff( a, b ) {\n\tvar result = a.slice();\n\tfor ( var i = 0; i < result.length; i++ ) {\n\t\tfor ( var j = 0; j < b.length; j++ ) {\n\t\t\tif ( result[i] === b[j] ) {\n\t\t\t\tresult.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction extend(a, b) {\n\tfor ( var prop in b ) {\n\t\tif ( b[prop] === undefined ) {\n\t\t\tdelete a[prop];\n\n\t\t// Avoid \"Member not found\" error in IE8 caused by setting window.constructor\n\t\t} else if ( prop !== \"constructor\" || a !== window ) {\n\t\t\ta[prop] = b[prop];\n\t\t}\n\t}\n\n\treturn a;\n}\n\nfunction addEvent(elem, type, fn) {\n\tif ( elem.addEventListener ) {\n\t\telem.addEventListener( type, fn, false );\n\t} else if ( elem.attachEvent ) {\n\t\telem.attachEvent( \"on\" + type, fn );\n\t} else {\n\t\tfn();\n\t}\n}\n\nfunction id(name) {\n\treturn !!(typeof document !== \"undefined\" && document && document.getElementById) &&\n\t\tdocument.getElementById( name );\n}\n\nfunction registerLoggingCallback(key){\n\treturn function(callback){\n\t\tconfig[key].push( callback );\n\t};\n}\n\n// Supports deprecated method of completely overwriting logging callbacks\nfunction runLoggingCallbacks(key, scope, args) {\n\t//debugger;\n\tvar callbacks;\n\tif ( QUnit.hasOwnProperty(key) ) {\n\t\tQUnit[key].call(scope, args);\n\t} else {\n\t\tcallbacks = config[key];\n\t\tfor( var i = 0; i < callbacks.length; i++ ) {\n\t\t\tcallbacks[i].call( scope, args );\n\t\t}\n\t}\n}\n\n// Test for equality any JavaScript type.\n// Author: Philippe Rathé <prathe@gmail.com>\nQUnit.equiv = (function() {\n\n\tvar innerEquiv; // the real equiv function\n\tvar callers = []; // stack to decide between skip/abort functions\n\tvar parents = []; // stack to avoiding loops from circular referencing\n\n\t// Call the o related callback with the given arguments.\n\tfunction bindCallbacks(o, callbacks, args) {\n\t\tvar prop = QUnit.objectType(o);\n\t\tif (prop) {\n\t\t\tif (QUnit.objectType(callbacks[prop]) === \"function\") {\n\t\t\t\treturn callbacks[prop].apply(callbacks, args);\n\t\t\t} else {\n\t\t\t\treturn callbacks[prop]; // or undefined\n\t\t\t}\n\t\t}\n\t}\n\n\tvar getProto = Object.getPrototypeOf || function (obj) {\n\t\treturn obj.__proto__;\n\t};\n\n\tvar callbacks = (function () {\n\n\t\t// for string, boolean, number and null\n\t\tfunction useStrictEquality(b, a) {\n\t\t\tif (b instanceof a.constructor || a instanceof b.constructor) {\n\t\t\t\t// to catch short annotaion VS 'new' annotation of a\n\t\t\t\t// declaration\n\t\t\t\t// e.g. var i = 1;\n\t\t\t\t// var j = new Number(1);\n\t\t\t\treturn a == b;\n\t\t\t} else {\n\t\t\t\treturn a === b;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t\"string\" : useStrictEquality,\n\t\t\t\"boolean\" : useStrictEquality,\n\t\t\t\"number\" : useStrictEquality,\n\t\t\t\"null\" : useStrictEquality,\n\t\t\t\"undefined\" : useStrictEquality,\n\n\t\t\t\"nan\" : function(b) {\n\t\t\t\treturn isNaN(b);\n\t\t\t},\n\n\t\t\t\"date\" : function(b, a) {\n\t\t\t\treturn QUnit.objectType(b) === \"date\" && a.valueOf() === b.valueOf();\n\t\t\t},\n\n\t\t\t\"regexp\" : function(b, a) {\n\t\t\t\treturn QUnit.objectType(b) === \"regexp\" &&\n\t\t\t\t\t// the regex itself\n\t\t\t\t\ta.source === b.source &&\n\t\t\t\t\t// and its modifers\n\t\t\t\t\ta.global === b.global &&\n\t\t\t\t\t// (gmi) ...\n\t\t\t\t\ta.ignoreCase === b.ignoreCase &&\n\t\t\t\t\ta.multiline === b.multiline;\n\t\t\t},\n\n\t\t\t// - skip when the property is a method of an instance (OOP)\n\t\t\t// - abort otherwise,\n\t\t\t// initial === would have catch identical references anyway\n\t\t\t\"function\" : function() {\n\t\t\t\tvar caller = callers[callers.length - 1];\n\t\t\t\treturn caller !== Object && typeof caller !== \"undefined\";\n\t\t\t},\n\n\t\t\t\"array\" : function(b, a) {\n\t\t\t\tvar i, j, loop;\n\t\t\t\tvar len;\n\n\t\t\t\t// b could be an object literal here\n\t\t\t\tif (QUnit.objectType(b) !== \"array\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tlen = a.length;\n\t\t\t\tif (len !== b.length) { // safe and faster\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// track reference to avoid circular references\n\t\t\t\tparents.push(a);\n\t\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\t\tloop = false;\n\t\t\t\t\tfor (j = 0; j < parents.length; j++) {\n\t\t\t\t\t\tif (parents[j] === a[i]) {\n\t\t\t\t\t\t\tloop = true;// dont rewalk array\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!loop && !innerEquiv(a[i], b[i])) {\n\t\t\t\t\t\tparents.pop();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tparents.pop();\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t\"object\" : function(b, a) {\n\t\t\t\tvar i, j, loop;\n\t\t\t\tvar eq = true; // unless we can proove it\n\t\t\t\tvar aProperties = [], bProperties = []; // collection of\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// strings\n\n\t\t\t\t// comparing constructors is more strict than using\n\t\t\t\t// instanceof\n\t\t\t\tif (a.constructor !== b.constructor) {\n\t\t\t\t\t// Allow objects with no prototype to be equivalent to\n\t\t\t\t\t// objects with Object as their constructor.\n\t\t\t\t\tif (!((getProto(a) === null && getProto(b) === Object.prototype) ||\n\t\t\t\t\t\t(getProto(b) === null && getProto(a) === Object.prototype)))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// stack constructor before traversing properties\n\t\t\t\tcallers.push(a.constructor);\n\t\t\t\t// track reference to avoid circular references\n\t\t\t\tparents.push(a);\n\n\t\t\t\tfor (i in a) { // be strict: don't ensures hasOwnProperty\n\t\t\t\t\t\t\t\t// and go deep\n\t\t\t\t\tloop = false;\n\t\t\t\t\tfor (j = 0; j < parents.length; j++) {\n\t\t\t\t\t\tif (parents[j] === a[i]) {\n\t\t\t\t\t\t\t// don't go down the same path twice\n\t\t\t\t\t\t\tloop = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\taProperties.push(i); // collect a's properties\n\n\t\t\t\t\tif (!loop && !innerEquiv(a[i], b[i])) {\n\t\t\t\t\t\teq = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallers.pop(); // unstack, we are done\n\t\t\t\tparents.pop();\n\n\t\t\t\tfor (i in b) {\n\t\t\t\t\tbProperties.push(i); // collect b's properties\n\t\t\t\t}\n\n\t\t\t\t// Ensures identical properties name\n\t\t\t\treturn eq && innerEquiv(aProperties.sort(), bProperties.sort());\n\t\t\t}\n\t\t};\n\t}());\n\n\tinnerEquiv = function() { // can take multiple arguments\n\t\tvar args = Array.prototype.slice.apply(arguments);\n\t\tif (args.length < 2) {\n\t\t\treturn true; // end transition\n\t\t}\n\n\t\treturn (function(a, b) {\n\t\t\tif (a === b) {\n\t\t\t\treturn true; // catch the most you can\n\t\t\t} else if (a === null || b === null || typeof a === \"undefined\" ||\n\t\t\t\t\ttypeof b === \"undefined\" ||\n\t\t\t\t\tQUnit.objectType(a) !== QUnit.objectType(b)) {\n\t\t\t\treturn false; // don't lose time with error prone cases\n\t\t\t} else {\n\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n\t\t\t}\n\n\t\t\t// apply transition with (1..n) arguments\n\t\t}(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length - 1)));\n\t};\n\n\treturn innerEquiv;\n\n}());\n\n/**\n * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n * http://flesler.blogspot.com Licensed under BSD\n * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n *\n * @projectDescription Advanced and extensible data dumping for Javascript.\n * @version 1.0.0\n * @author Ariel Flesler\n * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n */\nQUnit.jsDump = (function() {\n\tfunction quote( str ) {\n\t\treturn '\"' + str.toString().replace(/\"/g, '\\\\\"') + '\"';\n\t}\n\tfunction literal( o ) {\n\t\treturn o + '';\n\t}\n\tfunction join( pre, arr, post ) {\n\t\tvar s = jsDump.separator(),\n\t\t\tbase = jsDump.indent(),\n\t\t\tinner = jsDump.indent(1);\n\t\tif ( arr.join ) {\n\t\t\tarr = arr.join( ',' + s + inner );\n\t\t}\n\t\tif ( !arr ) {\n\t\t\treturn pre + post;\n\t\t}\n\t\treturn [ pre, inner + arr, base + post ].join(s);\n\t}\n\tfunction array( arr, stack ) {\n\t\tvar i = arr.length, ret = new Array(i);\n\t\tthis.up();\n\t\twhile ( i-- ) {\n\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n\t\t}\n\t\tthis.down();\n\t\treturn join( '[', ret, ']' );\n\t}\n\n\tvar reName = /^function (\\w+)/;\n\n\tvar jsDump = {\n\t\tparse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance\n\t\t\tstack = stack || [ ];\n\t\t\tvar parser = this.parsers[ type || this.typeOf(obj) ];\n\t\t\ttype = typeof parser;\n\t\t\tvar inStack = inArray(obj, stack);\n\t\t\tif (inStack != -1) {\n\t\t\t\treturn 'recursion('+(inStack - stack.length)+')';\n\t\t\t}\n\t\t\t//else\n\t\t\tif (type == 'function')  {\n\t\t\t\t\tstack.push(obj);\n\t\t\t\t\tvar res = parser.call( this, obj, stack );\n\t\t\t\t\tstack.pop();\n\t\t\t\t\treturn res;\n\t\t\t}\n\t\t\t// else\n\t\t\treturn (type == 'string') ? parser : this.parsers.error;\n\t\t},\n\t\ttypeOf: function( obj ) {\n\t\t\tvar type;\n\t\t\tif ( obj === null ) {\n\t\t\t\ttype = \"null\";\n\t\t\t} else if (typeof obj === \"undefined\") {\n\t\t\t\ttype = \"undefined\";\n\t\t\t} else if (QUnit.is(\"RegExp\", obj)) {\n\t\t\t\ttype = \"regexp\";\n\t\t\t} else if (QUnit.is(\"Date\", obj)) {\n\t\t\t\ttype = \"date\";\n\t\t\t} else if (QUnit.is(\"Function\", obj)) {\n\t\t\t\ttype = \"function\";\n\t\t\t} else if (typeof obj.setInterval !== undefined && typeof obj.document !== \"undefined\" && typeof obj.nodeType === \"undefined\") {\n\t\t\t\ttype = \"window\";\n\t\t\t} else if (obj.nodeType === 9) {\n\t\t\t\ttype = \"document\";\n\t\t\t} else if (obj.nodeType) {\n\t\t\t\ttype = \"node\";\n\t\t\t} else if (\n\t\t\t\t// native arrays\n\t\t\t\ttoString.call( obj ) === \"[object Array]\" ||\n\t\t\t\t// NodeList objects\n\t\t\t\t( typeof obj.length === \"number\" && typeof obj.item !== \"undefined\" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === \"undefined\" ) ) )\n\t\t\t) {\n\t\t\t\ttype = \"array\";\n\t\t\t} else {\n\t\t\t\ttype = typeof obj;\n\t\t\t}\n\t\t\treturn type;\n\t\t},\n\t\tseparator: function() {\n\t\t\treturn this.multiline ?\tthis.HTML ? '<br />' : '\\n' : this.HTML ? '&nbsp;' : ' ';\n\t\t},\n\t\tindent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing\n\t\t\tif ( !this.multiline ) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\tvar chr = this.indentChar;\n\t\t\tif ( this.HTML ) {\n\t\t\t\tchr = chr.replace(/\\t/g,'   ').replace(/ /g,'&nbsp;');\n\t\t\t}\n\t\t\treturn new Array( this._depth_ + (extra||0) ).join(chr);\n\t\t},\n\t\tup: function( a ) {\n\t\t\tthis._depth_ += a || 1;\n\t\t},\n\t\tdown: function( a ) {\n\t\t\tthis._depth_ -= a || 1;\n\t\t},\n\t\tsetParser: function( name, parser ) {\n\t\t\tthis.parsers[name] = parser;\n\t\t},\n\t\t// The next 3 are exposed so you can use them\n\t\tquote: quote,\n\t\tliteral: literal,\n\t\tjoin: join,\n\t\t//\n\t\t_depth_: 1,\n\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n\t\tparsers: {\n\t\t\twindow: '[Window]',\n\t\t\tdocument: '[Document]',\n\t\t\terror: '[ERROR]', //when no parser is found, shouldn't happen\n\t\t\tunknown: '[Unknown]',\n\t\t\t'null': 'null',\n\t\t\t'undefined': 'undefined',\n\t\t\t'function': function( fn ) {\n\t\t\t\tvar ret = 'function',\n\t\t\t\t\tname = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE\n\t\t\t\tif ( name ) {\n\t\t\t\t\tret += ' ' + name;\n\t\t\t\t}\n\t\t\t\tret += '(';\n\n\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');\n\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );\n\t\t\t},\n\t\t\tarray: array,\n\t\t\tnodelist: array,\n\t\t\t'arguments': array,\n\t\t\tobject: function( map, stack ) {\n\t\t\t\tvar ret = [ ], keys, key, val, i;\n\t\t\t\tQUnit.jsDump.up();\n\t\t\t\tif (Object.keys) {\n\t\t\t\t\tkeys = Object.keys( map );\n\t\t\t\t} else {\n\t\t\t\t\tkeys = [];\n\t\t\t\t\tfor (key in map) { keys.push( key ); }\n\t\t\t\t}\n\t\t\t\tkeys.sort();\n\t\t\t\tfor (i = 0; i < keys.length; i++) {\n\t\t\t\t\tkey = keys[ i ];\n\t\t\t\t\tval = map[ key ];\n\t\t\t\t\tret.push( QUnit.jsDump.parse( key, 'key' ) + ': ' + QUnit.jsDump.parse( val, undefined, stack ) );\n\t\t\t\t}\n\t\t\t\tQUnit.jsDump.down();\n\t\t\t\treturn join( '{', ret, '}' );\n\t\t\t},\n\t\t\tnode: function( node ) {\n\t\t\t\tvar open = QUnit.jsDump.HTML ? '&lt;' : '<',\n\t\t\t\t\tclose = QUnit.jsDump.HTML ? '&gt;' : '>';\n\n\t\t\t\tvar tag = node.nodeName.toLowerCase(),\n\t\t\t\t\tret = open + tag;\n\n\t\t\t\tfor ( var a in QUnit.jsDump.DOMAttrs ) {\n\t\t\t\t\tvar val = node[QUnit.jsDump.DOMAttrs[a]];\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\tret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn ret + close + open + '/' + tag + close;\n\t\t\t},\n\t\t\tfunctionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function\n\t\t\t\tvar l = fn.length;\n\t\t\t\tif ( !l ) {\n\t\t\t\t\treturn '';\n\t\t\t\t}\n\n\t\t\t\tvar args = new Array(l);\n\t\t\t\twhile ( l-- ) {\n\t\t\t\t\targs[l] = String.fromCharCode(97+l);//97 is 'a'\n\t\t\t\t}\n\t\t\t\treturn ' ' + args.join(', ') + ' ';\n\t\t\t},\n\t\t\tkey: quote, //object calls it internally, the key part of an item in a map\n\t\t\tfunctionCode: '[code]', //function calls it internally, it's the content of the function\n\t\t\tattribute: quote, //node calls it internally, it's an html attribute value\n\t\t\tstring: quote,\n\t\t\tdate: quote,\n\t\t\tregexp: literal, //regex\n\t\t\tnumber: literal,\n\t\t\t'boolean': literal\n\t\t},\n\t\tDOMAttrs:{//attributes to dump from nodes, name=>realName\n\t\t\tid:'id',\n\t\t\tname:'name',\n\t\t\t'class':'className'\n\t\t},\n\t\tHTML:false,//if true, entities are escaped ( <, >, \\t, space and \\n )\n\t\tindentChar:'  ',//indentation unit\n\t\tmultiline:true //if true, items in a collection, are separated by a \\n, else just a space.\n\t};\n\n\treturn jsDump;\n}());\n\n// from Sizzle.js\nfunction getText( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\t// Get the text from text nodes and CDATA nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t// Traverse everything else, except comment nodes\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n}\n\n//from jquery.js\nfunction inArray( elem, array ) {\n\tif ( array.indexOf ) {\n\t\treturn array.indexOf( elem );\n\t}\n\n\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n\t\tif ( array[ i ] === elem ) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/*\n * Javascript Diff Algorithm\n *  By John Resig (http://ejohn.org/)\n *  Modified by Chu Alan \"sprite\"\n *\n * Released under the MIT license.\n *\n * More Info:\n *  http://ejohn.org/projects/javascript-diff-algorithm/\n *\n * Usage: QUnit.diff(expected, actual)\n *\n * QUnit.diff(\"the quick brown fox jumped over\", \"the quick fox jumps over\") == \"the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over\"\n */\nQUnit.diff = (function() {\n\tfunction diff(o, n) {\n\t\tvar ns = {};\n\t\tvar os = {};\n\t\tvar i;\n\n\t\tfor (i = 0; i < n.length; i++) {\n\t\t\tif (ns[n[i]] == null) {\n\t\t\t\tns[n[i]] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\to: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tns[n[i]].rows.push(i);\n\t\t}\n\n\t\tfor (i = 0; i < o.length; i++) {\n\t\t\tif (os[o[i]] == null) {\n\t\t\t\tos[o[i]] = {\n\t\t\t\t\trows: [],\n\t\t\t\t\tn: null\n\t\t\t\t};\n\t\t\t}\n\t\t\tos[o[i]].rows.push(i);\n\t\t}\n\n\t\tfor (i in ns) {\n\t\t\tif ( !hasOwn.call( ns, i ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ns[i].rows.length == 1 && typeof(os[i]) != \"undefined\" && os[i].rows.length == 1) {\n\t\t\t\tn[ns[i].rows[0]] = {\n\t\t\t\t\ttext: n[ns[i].rows[0]],\n\t\t\t\t\trow: os[i].rows[0]\n\t\t\t\t};\n\t\t\t\to[os[i].rows[0]] = {\n\t\t\t\t\ttext: o[os[i].rows[0]],\n\t\t\t\t\trow: ns[i].rows[0]\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor (i = 0; i < n.length - 1; i++) {\n\t\t\tif (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&\n\t\t\tn[i + 1] == o[n[i].row + 1]) {\n\t\t\t\tn[i + 1] = {\n\t\t\t\t\ttext: n[i + 1],\n\t\t\t\t\trow: n[i].row + 1\n\t\t\t\t};\n\t\t\t\to[n[i].row + 1] = {\n\t\t\t\t\ttext: o[n[i].row + 1],\n\t\t\t\t\trow: i + 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfor (i = n.length - 1; i > 0; i--) {\n\t\t\tif (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&\n\t\t\tn[i - 1] == o[n[i].row - 1]) {\n\t\t\t\tn[i - 1] = {\n\t\t\t\t\ttext: n[i - 1],\n\t\t\t\t\trow: n[i].row - 1\n\t\t\t\t};\n\t\t\t\to[n[i].row - 1] = {\n\t\t\t\t\ttext: o[n[i].row - 1],\n\t\t\t\t\trow: i - 1\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\to: o,\n\t\t\tn: n\n\t\t};\n\t}\n\n\treturn function(o, n) {\n\t\to = o.replace(/\\s+$/, '');\n\t\tn = n.replace(/\\s+$/, '');\n\t\tvar out = diff(o === \"\" ? [] : o.split(/\\s+/), n === \"\" ? [] : n.split(/\\s+/));\n\n\t\tvar str = \"\";\n\t\tvar i;\n\n\t\tvar oSpace = o.match(/\\s+/g);\n\t\tif (oSpace == null) {\n\t\t\toSpace = [\" \"];\n\t\t}\n\t\telse {\n\t\t\toSpace.push(\" \");\n\t\t}\n\t\tvar nSpace = n.match(/\\s+/g);\n\t\tif (nSpace == null) {\n\t\t\tnSpace = [\" \"];\n\t\t}\n\t\telse {\n\t\t\tnSpace.push(\" \");\n\t\t}\n\n\t\tif (out.n.length === 0) {\n\t\t\tfor (i = 0; i < out.o.length; i++) {\n\t\t\t\tstr += '<del>' + out.o[i] + oSpace[i] + \"</del>\";\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (out.n[0].text == null) {\n\t\t\t\tfor (n = 0; n < out.o.length && out.o[n].text == null; n++) {\n\t\t\t\t\tstr += '<del>' + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (i = 0; i < out.n.length; i++) {\n\t\t\t\tif (out.n[i].text == null) {\n\t\t\t\t\tstr += '<ins>' + out.n[i] + nSpace[i] + \"</ins>\";\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvar pre = \"\";\n\n\t\t\t\t\tfor (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {\n\t\t\t\t\t\tpre += '<del>' + out.o[n] + oSpace[n] + \"</del>\";\n\t\t\t\t\t}\n\t\t\t\t\tstr += \" \" + out.n[i].text + nSpace[i] + pre;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn str;\n\t};\n}());\n\n// for CommonJS enviroments, export everything\nif ( typeof exports !== \"undefined\" || typeof require !== \"undefined\" ) {\n\textend(exports, QUnit);\n}\n\n// get at whatever the global object is, like window in browsers\n}( (function() {return this;}.call()) ));\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-app-optimized.html",
    "content": "<!DOCTYPE html>\n<meta charset=\"utf-8\">\n<title>App Test Frame - Optimized Build</title>\n<!-- For faster loading times, don't load our CSS. -->\n<!-- <link rel=\"stylesheet\" href=\"../css/friendlycode.css\"> -->\n<div id=\"fc\" class=\"friendlycode-loading\"></div>\n<script src=\"../js/require.min.js\"></script>\n<script src=\"../js/friendlycode-built.js\"></script>\n<script>\nvar publishURL = \"https://webpagemaker-dev.allizom.org\";\n\ndefine('main', [\"jquery\", \"friendlycode\"], function($, FriendlycodeEditor) {\n  return FriendlycodeEditor({\n    publishURL: publishURL,\n    container: $(\"#fc\")\n  });\n});\n\nrequire(['main'], function () {});\n</script>\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-app.html",
    "content": "<!DOCTYPE html>\n<meta charset=\"utf-8\">\n<title>App Test Frame</title>\n<!-- For faster loading times, don't load our CSS. -->\n<!-- <link rel=\"stylesheet\" href=\"../css/friendlycode.css\"> -->\n<div id=\"fc\" class=\"friendlycode-loading\"></div>\n<script src=\"../js/require-config.js\"></script>\n<script src=\"../js/require.min.js\"></script>\n<script>\nvar publishURL = \"https://webpagemaker-dev.allizom.org\";\n\ndefine('main', [\"jquery\", \"friendlycode\"], function($, FriendlycodeEditor) {\n  return FriendlycodeEditor({\n    publishURL: publishURL,\n    container: $(\"#fc\")\n  });\n});\n\nrequire(['main'], function () {});\n</script>\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-app.js",
    "content": "\"use strict\";\n\ndefineTests([\"jquery\", \"lscache\"], function($, lscache) {\n  module(\"app\");\n\n  function appTest(name, cb) {\n    var url = 'test/test-app' +\n              (location.pathname.match(/optimized/) ? '-optimized' : '') +\n              '.html';\n    var iframe = $('<iframe src=\"' + require.toUrl(url) + '\"></iframe>');\n    iframe.css({\n      display: \"none\"\n    });\n\n    asyncTest(name, function() {\n      lscache.flush();\n      iframe.appendTo(\"body\").load(function() {\n        var wind = iframe.contents()[0].defaultView;\n        wind.require([\"main\"], function(main) {\n          main.ready.done(function() {\n            cb(wind, function() {\n              setTimeout(function() {\n                // Hopefully this should avoid a spurious\n                // NS_ERROR_NOT_INITIALIZED coming from \n                // nsIDOMJSWindow.setTimeout (via jQuery) in Firefox.\n                iframe.remove();\n              }, 100);\n              start();\n            });\n          });\n        });\n      });\n    });\n  }\n  \n  appTest(\"publish works\", function(window, start) {\n    var $ = window.require(\"jquery\");\n    var publishURL = window.publishURL;\n    var url = window.location.href;\n    \n    // Inject a fake ajax transport handler so we get called instead\n    // of a real Ajax request being made to the publishing server.\n    $.ajaxTransport(\"+*\", function(options, originalOptions, jqXHR) {\n      return {\n        send: function(headers, completeCallback) {\n          equal(originalOptions.type, \"POST\", \"request is POST\");\n          equal(originalOptions.url, publishURL + \"/api/page\",\n                \"request URL is correct\");\n          equal(originalOptions.dataType, \"text\",\n                \"expected response type is text\");\n          equal(originalOptions.data.html, \"<p>hi</p>\",\n                \"editor HTML is submitted in POST data\");\n          completeCallback(200, \"OK\", {\n            text: \"/lol\"\n          });\n          var viewURL = publishURL + \"/lol\";\n          var view = $(\".publication-result .view\");\n          var remix = $(\".publish-dialog .remix\");\n          equal(view.text(), viewURL, \"view URL text is \" + viewURL);\n          equal(view.attr(\"href\"), viewURL, \"view URL href is \" + viewURL);\n          ok(remix.text().indexOf(\"/lol\") != -1,\n             \"remix URL text contains '/lol'\");\n          ok(remix.attr(\"href\").indexOf(\"/lol\") != -1,\n            \"remix URL href contains '/lol'\");\n          ok(window.location.href != url &&\n             window.location.href.indexOf(\"/lol\") != -1,\n             \"editor URL is different from before and contains '/lol'\");\n          start();\n        }\n      };\n    });\n\n    window.require(\"main\").codeMirror.setValue(\"<p>hi</p>\");\n    $(\"#publish\").click();\n    $(\".yes-button\").click();\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-current-page-manager.js",
    "content": "\"use strict\";\n\ndefineTests([\n  \"jquery\",\n  \"fc/current-page-manager\"\n], function($, CurrentPageManager) {\n  module(\"CurrentPageManager\");\n  \n  function FakeWindow() {\n    return {\n      history: {},\n      location: {\n        hash: \"\",\n        href: \"\",\n        reload: function() { this._reloads++; },\n        _reloads: 0\n      },\n      _listeners: {},\n      addEventListener: function(name, cb) {\n        if (name in this._listeners) throw new Error();\n        this._listeners[name] = cb;\n      }\n    };\n  }\n\n  test(\"changePage triggers hashchange\", function() {\n    var w = FakeWindow();\n    var cpm = CurrentPageManager({window: w});\n    cpm.changePage(\"/newpage\", \"/newpage/edit\");\n    equal(cpm.currentPage(), \"/newpage\", \"currentPage changed\");\n    equal(w.location.hash, \"#/newpage\", \"location.hash changed\");\n  });\n  \n  test(\"changePage triggers pushState\", function() {\n    var w = FakeWindow();\n    w.history = {\n      _stateChanges: [],\n      pushState: function(state, title, url) {\n        this._stateChanges.push([\"push\", state, title, url]);\n      },\n      replaceState: function(state, title, url) {\n        this._stateChanges.push([\"replace\", state, title, url]);\n      }\n    };\n    w.location.href = \"http://bop/\";\n    var cpm = CurrentPageManager({\n      window: w,\n      currentPage: \"/blah\"\n    });\n    cpm.changePage(\"/newpage\", \"/newpage/edit\");\n    equal(cpm.currentPage(), \"/newpage\", \"currentPage changed\");\n    deepEqual(w.history._stateChanges, [\n      [\"replace\", {\"pageToLoad\": \"/blah\"}, \"\", \"http://bop/\"],\n      [\"push\", {\"pageToLoad\": \"/newpage\"}, \"\", \"/newpage/edit\"]\n    ], \"state changes made\");\n  });\n  \n  test(\"popstate triggers loadPage\", function() {\n    var w = FakeWindow();\n    w.history = {\n      pushState: function() {},\n      replaceState: function() {}\n    };\n    var cpm = CurrentPageManager({window: w});\n    w._listeners.popstate({state: {pageToLoad: \"/bloop\"}});\n    equal(w.location._reloads, 1, \"default loadPage triggered\");\n    equal(cpm.currentPage(), \"/bloop\", \"currentPage changed\");\n  });\n\n  test(\"hashchange triggers loadPage\", function() {\n    var w = FakeWindow();\n    var cpm = CurrentPageManager({window: w});\n    w.location.hash = \"#/different\";\n    w._listeners.hashchange();\n    equal(w.location._reloads, 1, \"default loadPage triggered\");\n    equal(cpm.currentPage(), \"/different\", \"currentPage changed\");\n  });\n  \n  test(\"current page is taken from location hash\", function() {\n    var w = FakeWindow();\n    w.location.hash = \"#/blorp\";\n    var cpm = CurrentPageManager({window: w});\n    equal(cpm.currentPage(), \"/blorp\");\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-editor-toolbar.js",
    "content": "\"use strict\";\n\ndefineTests([\n  \"jquery\",\n  \"fc/ui/editor-panes\",\n  \"fc/ui/editor-toolbar\"\n], function($, EditorPanes, EditorToolbar) {\n  var parentDiv, panesDiv, toolbarDiv, panes, options;\n\n  module(\"EditorToolbar\", {\n    setup: function() {\n      parentDiv = $('<div></div>').appendTo(\"#qunit-fixture\").hide();\n      panesDiv = $('<div></div>').appendTo(parentDiv);\n      toolbarDiv = $('<div></div>').appendTo(parentDiv);\n      panes = EditorPanes({container: panesDiv});\n      options = {panes: panes, container: toolbarDiv};\n    },\n    teardown: function() {\n      parentDiv.remove();\n    }\n  });\n  \n  test(\"shows page title when <title> is present\", function() {\n    var toolbar = EditorToolbar(options);\n    panes.codeMirror.setValue(\"<title>supdog</title>\");\n    panes.codeMirror.reparse();\n    parentDiv.show();\n    equal($(\".preview-title:visible\", toolbarDiv).length, 1,\n          \"navbar preview title is not hidden\");\n    equal($(\".preview-title\", toolbarDiv).text(), \"supdog\",\n          \"navbar preview title is 'supdog'\");\n  });\n  \n  test(\"doesn't show page title when <title> is absent\", function() {\n    var toolbar = EditorToolbar(options);\n    panes.codeMirror.setValue(\"<p>hello</p>\");\n    panes.codeMirror.reparse();\n    parentDiv.show();\n    equal($(\".preview-title:visible\", toolbarDiv).length, 0,\n          \"navbar preview title is hidden\");\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-gutter-pointer.js",
    "content": "defineTests([\n  \"jquery\",\n  \"codemirror\",\n  \"fc/ui/gutter-pointer\"\n], function($, CodeMirror, gutterPointer) {\n  module(\"gutterPointer\");\n  \n  test(\"does not smoke\", function() {\n    var div = $(\"<div></div>\").appendTo(\"#qunit-fixture\");\n    var cm = CodeMirror(div[0], {\n      value: \"hello\\nthere\\ndude\",\n      lineNumbers: true\n    });\n    \n    cm.setMarker(1, null, \"blarg\");\n    \n    var gp = gutterPointer(cm, \"blarg\");\n    equal(gp.css('position'), 'absolute',\n          'gutterPointer is absolutely positioned');\n    equal(gp[0].nodeName, \"svg\", \"gutterPointer is <svg>\");\n    equal(gp[0].namespaceURI, \"http://www.w3.org/2000/svg\",\n          \"gutterPointer has SVG namespace\");\n    equal(gp.attr(\"class\"), \"gutter-pointer blarg\");\n    div.remove();\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-help.js",
    "content": "\"use strict\";\n\ndefineTests([\"fc/help\", \"slowparse/slowparse\"], function(Help, Slowparse) {\n  module(\"Help\");\n\n  function helpAt(index, searchString, html) {\n    return index.get(html.indexOf(searchString));\n  }\n  \n  function assertHighlightIntervals(index, searchString, strings, html) {\n    var highlights = helpAt(index, searchString, html).highlights;\n    var prefix = \"in \" + JSON.stringify(html) + \", when cursor is at \" +\n                 JSON.stringify(searchString) + \", \";\n    equal(highlights.length, strings.length,\n          prefix + \"there are \" + strings.length + \" highlight(s)\");\n    for (var i = 0; i < highlights.length; i++)\n      equal(html.slice(highlights[i].start, highlights[i].end), strings[i],\n            prefix + \"highlight interval \" + i + \" is \" +\n            JSON.stringify(strings[i]));\n  }\n\n  function buildIndex(html) {\n    var index = Help.Index();\n    var doc = Slowparse.HTML(document, html).document;\n\n    index.build(doc, html);\n    return index;\n  }\n  \n  test(\"Index.clear() works\", function() {\n    var index = buildIndex('<p>hi</p>');\n    ok(index.get(1));\n    index.clear();\n    equal(index.get(1), undefined);\n  });\n  \n  test(\"Index.get() returns undefined when in text node\", function() {\n    equal(buildIndex('<em>hi</em>').get(4), undefined);\n  });\n  \n  test(\"Index.get() returns help for HTML elements\", function() {\n    var html = '<p>he<br>llo</p>';\n    var index = buildIndex(html);\n    var help = helpAt(index, \"p>h\", html);\n    \n    ok(help.html.match(/paragraph/i),\n       \"Index contains HTML help from hacktionary\");\n    equal(help.url, Help.MDN_URLS.html + 'p',\n          \"Index contains MDN URL for HTML elements\");\n    assertHighlightIntervals(index, \"p>h\", [\"<p>\", \"</p>\"], html);\n    assertHighlightIntervals(index, \"br>\", [\"<br>\"], html);\n  });\n\n  test(\"Index.get() returns help for <h1> thru <h6>\", function() {\n    var html = '<h1>a</h1> <h2>b</h2> <h3>c</h3>' + \n               '<h4>d</h4> <H5>e</H5> <h6>f</h6>';\n    var index = buildIndex(html);\n    \n    [\"<h1>\", \"<h2>\", \"<h3>\", \"<h4>\", \"<H5>\", \"<h6>\"].forEach(function(hTag) {\n      ok(helpAt(index, hTag.slice(1), html).html.match(/heading/i));\n    });\n  });\n  \n  test(\"Index.get() returns help for CSS properties\", function() {\n    var html = '<style>body { color: blue; }</style>';\n    var index = buildIndex(html);\n    var help = helpAt(index, \"color\", html);\n    \n    ok(help.html.match(/foreground/i),\n       \"Index contains CSS property help from hacktionary\");\n    equal(help.url, Help.MDN_URLS.css + \"color\",\n          \"Index contains MDN URL for CSS properties\");\n    assertHighlightIntervals(index, \"color\", [\"color\"], html);\n  });\n\n  test(\"Index.get() returns help for CSS selectors\", function() {\n    var html = '<style>body { color: blue; }</style>';\n    var index = buildIndex(html);\n    var help = helpAt(index, \"body\", html);\n\n    ok(help.html.match(/selector/i),\n       \"Index contains CSS selector help from hacktionary\");\n    ok(help.url, Help.MDN_URLS.cssSelectors,\n       \"Index contains MDN URL for CSS selectors\");\n    assertHighlightIntervals(buildIndex(html), \"body\", [\"body\"], html);\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-indexable-codemirror.js",
    "content": "\"use strict\";\n\ndefineTests([\n  \"jquery\",\n  \"fc/ui/indexable-codemirror\"\n], function($, IndexableCodeMirror) {\n  module(\"IndexableCodeMirror\");\n  \n  function icmTest(name, cb) {\n    test(name, function() {\n      var place = $(\"<div></div>\").appendTo(document.body);\n      var cm = IndexableCodeMirror(place[0], {mode: \"text/plain\"});\n      var content = \"hello\\nthere\";\n      cm.setValue(content);\n      try {\n        cb(cm, content);\n      } finally {\n        place.remove();\n      }\n    });\n  }\n  \n  icmTest(\"indexFromPos() works\", function(cm, content) {\n    equal(cm.indexFromPos({line: 0, ch: 0}), 0,\n          \"index of line 0, char 0 is 0\");\n    equal(cm.indexFromPos({line: 1, ch: 0}), content.indexOf(\"there\"),\n          \"index of line 1, char 0 works\");\n  });\n  \n  icmTest(\"getCursorIndex() works\", function(cm, content) {\n    cm.setCursor({line: 1, ch: 0});\n    equal(cm.getCursorIndex(), content.indexOf(\"there\"));\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-live-preview.js",
    "content": "\"use strict\";\n\ndefineTests([\n  \"jquery\",\n  \"backbone-events\",\n  \"test/lptest\",\n  \"fc/ui/live-preview\"\n], function($, BackboneEvents, lpTest, LivePreview) {\n  module(\"LivePreview\");\n  \n  test(\"does nothing if preview area isn't attached\", function() {\n    var div = $(\"<div></div>\");\n    var cm = BackboneEvents.mixin({});\n    var lp = LivePreview({\n      previewArea: div,\n      codeMirror: cm\n    });\n    cm.trigger('reparse', {error: null});\n    ok(true);\n  });\n  \n  lpTest(\n    \"title property reflects document title\",\n    \"<title>hello</title>\",\n    function(previewArea, preview) {\n      equal(preview.title, \"hello\");\n    }\n  );\n\n  lpTest(\n    \"change:title event is fired when page title changes\",\n    \"<title>hello</title>\",\n    function(previewArea, preview, cm) {\n      stop();\n      preview.on('change:title', function(title) {\n        equal(title, 'yo');\n        equal(preview.title, title);\n        start();\n      });\n      cm.trigger('reparse', {\n        error: null,\n        sourceCode: '<title>yo</title>'\n      });\n    }\n  );\n\n  lpTest(\n    \"change:title event is not fired when page title stays the same\",\n    \"<title>hello</title>\",\n    function(previewArea, preview, cm) {\n      var changed = 0;\n      preview.on('change:title', function(title) { changed++; });\n      cm.trigger('reparse', {\n        error: null,\n        sourceCode: '<title>hello</title><p>there</p>'\n      });\n      equal(changed, 0);\n    }\n  );\n    \n  lpTest(\"HTML is written into document\", function(previewArea, preview, cm) {\n    equal($(\"body\", previewArea.contents()).html(),\n          \"<p>hi <em>there</em></p>\",\n          \"HTML source code is written into preview area\");\n  });\n  \n  lpTest('<base target=\"_blank\"> inserted', function(previewArea) {\n    equal($('base[target=\"_blank\"]', previewArea.contents()).length, 1);\n  });\n  \n  lpTest(\"refresh event is triggered\", function(previewArea, preview, cm) {\n    var refreshTriggered = false;\n    equal(preview.codeMirror, cm, \"codeMirror property exists\");\n    preview.on(\"refresh\", function(event) {\n      equal(event.documentFragment, \"blop\", \"documentFragment is passed\");\n      ok(event.window, \"window is passed\");\n      refreshTriggered = true;\n    });\n    cm.trigger('reparse', {\n      error: null,\n      sourceCode: '',\n      document: \"blop\"\n    });\n    ok(refreshTriggered, \"refresh event is triggered\");\n  });\n  \n  lpTest('scrolling is preserved across refresh',\n    function(previewArea, preview, cm) {\n      var wind;\n      preview.on('refresh', function(event) {\n        wind = event.window;\n      });\n      \n      cm.trigger('reparse', {\n        error: null,\n        sourceCode: '<p style=\"font-size: 400px\">hi <em>there</em></p>'\n      });\n      wind.scroll(5, 6);\n      var oldWind = wind;\n      cm.trigger('reparse', {\n        error: null,\n        sourceCode: '<p style=\"font-size: 400px\">hi <em>dood</em></p>'\n      });\n      ok(oldWind != wind, \"window changes across reparse\");\n      equal(wind.pageXOffset, 5, \"x scroll is preserved across refresh\");\n      equal(wind.pageYOffset, 6, \"y scroll is preserved across refresh\");\n    });\n  \n  return {\n    lpTest: lpTest\n  };\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-mark-tracker.js",
    "content": "\"use strict\";\n\ndefineTests([\n  \"jquery\",\n  \"fc/ui/mark-tracker\",\n  \"codemirror\"\n], function($, MarkTracker, CodeMirror) {\n  module(\"MarkTracker\");\n  \n  function mtTest(name, cb) {\n    test(name, function() {\n      var place = $(\"<div></div>\").appendTo(document.body);\n      var cm = CodeMirror(place[0], {mode: \"text/plain\"});\n      var mt = MarkTracker(cm);\n      try {\n        cb(place, cm, mt);\n      } finally {\n        place.remove();\n      }\n    });\n  }\n  \n  mtTest(\"codeMirror content mark/clear works\", function(place, cm, mt) {\n    cm.setValue(\"hello\");\n    mt.mark(2, 4, \"blah\");\n    equal(place.find(\".blah\").text(), \"ll\", \"source code is marked w/ class\");\n    mt.clear();\n    equal(place.find(\".blah\").length, 0, \"source code class is cleared\");\n  });\n  \n  mtTest(\"related element mark/clear works\", function(place, cm, mt) {\n    var thing = $(\"<div></div>\");\n    cm.setValue(\"hello\");\n    mt.mark(1, 4, \"foo\", thing[0]);\n    ok(thing.hasClass(\"foo\"), \"related element is marked w/ class\");\n    mt.clear();\n    ok(!thing.hasClass(\"foo\"), \"related element class is cleared\");\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-parsing-codemirror.js",
    "content": "\"use strict\";\n\ndefineTests([\n  \"jquery\",\n  \"fc/ui/parsing-codemirror\"\n], function($, ParsingCodeMirror) {\n  module(\"ParsingCodeMirror\");\n  \n  function pcmTest(name, cb) {\n    test(name, function() {\n      var place = $(\"<div></div>\").appendTo(document.body);\n      var events = [];\n      var fakeTime = {\n        id: 0,\n        setTimeout: function(cb, ms) {\n          this.cb = cb;\n          events.push(\"time.setTimeout(fn, \" + ms + \") -> \" + this.id);\n          return this.id++;\n        },\n        clearTimeout: function(id) {\n          events.push(\"time.clearTimeout(\" + id + \")\");\n        }\n      };\n      var cm = ParsingCodeMirror(place[0], {\n        mode: \"text/plain\",\n        parseDelay: 1,\n        parse: function(code) {\n          return {\n            error: \"here is an error\",\n            document: \"here is a document\"\n          };\n        },\n        time: fakeTime\n      });\n      cm.on(\"all\", function(eventName, arg) {\n        events.push(\"cm.trigger('\" + eventName + \"')\");\n      });\n      try {\n        cb(cm, events, fakeTime);\n      } finally {\n        place.remove();\n      }\n    });\n  }\n  \n  pcmTest(\"change triggered and timeout set on codeMirror.setValue()\",\n    function(cm, events, fakeTime) {\n      cm.setValue(\"hello\");\n      deepEqual(events, [\n        \"cm.trigger('change')\",\n        \"time.setTimeout(fn, 1) -> 0\",\n      ]);\n    });\n\n  pcmTest(\"change triggered but no timeout set if reparseEnabled is false\",\n    function(cm, events, fakeTime) {\n      cm.reparseEnabled = false;\n      cm.setValue(\"hello\");\n      deepEqual(events, [\n        \"cm.trigger('change')\"\n      ]);\n    });\n  \n  pcmTest(\"reparse() triggers events and passes expected arguments\",\n    function(cm, events, fakeTime) {\n      cm.setValue(\"hello\"); events.splice(0);\n      cm.on(\"reparse\", function(arg) {\n        equal(arg.document, \"here is a document\", \"document passed\");\n        equal(arg.error, \"here is an error\", \"error passed\");\n        equal(arg.sourceCode, \"hello\", \"source code passed\");\n      });\n      cm.reparse();\n      deepEqual(events, [\n        \"cm.trigger('reparse')\",\n        \"cm.trigger('cursor-activity')\",\n       ]);\n    });\n  \n  pcmTest(\"old timeout cancelled on multiple content changes\",\n    function(cm, events, fakeTime) {\n      cm.setValue(\"hello\"); events.splice(0);\n      cm.setValue(\"hello goober\");\n      deepEqual(events, [\n        \"cm.trigger('change')\",\n        \"time.clearTimeout(0)\",\n        \"time.setTimeout(fn, 1) -> 1\"\n      ]);\n    });\n\n  pcmTest(\"timeout function triggers events w/ expected args\",\n    function(cm, events, fakeTime) {\n      cm.setValue(\"hello goober\"); events.splice(0);\n      cm.on(\"reparse\", function(event) {\n        equal(event.sourceCode, \"hello goober\",\n              \"correct source code is passed on reparse event\");\n      });\n      fakeTime.cb();\n      deepEqual(events, [\n        \"cm.trigger('reparse')\",\n        \"cm.trigger('cursor-activity')\"\n      ], \"events are triggered\");\n    });\n\n  pcmTest(\"cursor-activity event is triggered by codeMirror.setCursor()\",\n    function(cm, events, fakeTime) {\n      cm.setValue(\"hello\"); events.splice(0);\n      cm.setCursor({line: 0, ch: 2});\n      deepEqual(events, [\"cm.trigger('cursor-activity')\"]);\n    });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-prefs.js",
    "content": "defineTests([\"fc/prefs\", \"lscache\"], function(Preferences, lscache) {\n  Preferences.CACHE_KEY = \"TestPreferences\";\n\n  module(\"Preferences\", {\n    setup: function() {\n      Preferences.off();\n      Preferences.clear();\n      Preferences.save();\n    }\n  });\n\n  test(\"is resilient when no stored value is available\", function() {\n    lscache.remove(Preferences.CACHE_KEY);\n    Preferences.fetch();\n    equal(Preferences.get(\"blah\"), undefined);\n  });\n\n  test(\"is resilient with corrupt JSON\", function() {\n    lscache.set(Preferences.CACHE_KEY, \"NO U!\", 500);\n    Preferences.fetch();\n    equal(Preferences.get(\"blah\"), undefined);\n  });\n  \n  test(\"loads stored preferences\", function() {\n    lscache.set(Preferences.CACHE_KEY, {\n      meh: 1\n    }, 500);\n    Preferences.fetch();\n    equal(Preferences.get(\"meh\"), 1);\n  });\n  \n  test(\"stores preferences\", function() {\n    Preferences.set(\"blop\", 5);\n    Preferences.save();\n    deepEqual(lscache.get(Preferences.CACHE_KEY), {\n      blop: 5\n    });\n  });\n  \n  test(\"can be destroyed\", function() {\n    deepEqual(lscache.get(Preferences.CACHE_KEY), {});\n    Preferences.destroy();\n    equal(lscache.get(Preferences.CACHE_KEY), undefined);\n  });\n  \n  test(\"triggers change events\", function() {\n    Preferences.on(\"change:foo\", function() {\n      ok(true, \"change:foo is triggered\");\n    });\n    Preferences.set(\"foo\", 1);\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-slowparse-errors.js",
    "content": "\"use strict\";\n\ndefineTests([\"jquery\", \"slowparse-errors\"], function($) {\n  module(\"slowparse-errors\");\n\n  test(\"base errors are available\", function() {\n    equal($.errorTemplates.filter(\".CLOSE_TAG_FOR_VOID_ELEMENT\").length, 1);\n  });\n  \n  test(\"forbidjs errors are available\", function() {\n    equal($.errorTemplates.filter(\".SCRIPT_ELEMENT_NOT_ALLOWED\").length, 1);\n  });\n});\n"
  },
  {
    "path": "site/examples/friendlycode/test/test-templates.js",
    "content": "\"use strict\";\n\ndefineTests([\"template!error-msg\", \"template!help-msg\"], function(err, help) {\n  module(\"templates\");\n\n  function contains(str, terms) {\n    if (typeof(terms) == \"string\")\n      terms = [terms];\n    terms.forEach(function(term) {\n      ok(str.indexOf(term) != -1, \"'\" + term + \"' is in \" + \n         JSON.stringify(str));\n    });\n  }\n  \n  test(\"error template works\", function() {\n    contains(err({error: \"<p>yo</p>\"}), \"<p>yo</p>\")\n  });\n  \n  test(\"help template works\", function() {\n    contains(help({\n      html: \"<i>hi</i>\",\n      type: \"nom\",\n      url: \"meh<\"\n    }), [\"<i>hi</i>\", \"meh&lt;\"]);\n\n    contains(help({\n      html: \"<i>hi</i>\",\n      type: \"cssSelector\",\n      matchCount: 5,\n      url: \"meh<\"\n    }), [\"5\", \"<i>hi</i>\", \"meh&lt;\"]);\n  });\n});\n"
  },
  {
    "path": "site/examples/madlibs/css/app.css",
    "content": ".madlib-hidden {\n    color: transparent;\n    text-shadow: 0 0 15px rgba(0,0,0,0.5);\n}\n\n.madlib-hidden input {\n    /*color: #000;*/\n}\n\n\n\n"
  },
  {
    "path": "site/examples/madlibs/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world by @mdo and @fat.\n */\n\n/*! normalize.css v2.1.0 | MIT License | git.io/normalize */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n[hidden] {\n  display: none;\n}\n\nhtml {\n  font-family: sans-serif;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\nbody {\n  margin: 0;\n}\n\na:focus {\n  outline: thin dotted;\n}\n\na:active,\na:hover {\n  outline: 0;\n}\n\nh1 {\n  margin: 0.67em 0;\n  font-size: 2em;\n}\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\nb,\nstrong {\n  font-weight: bold;\n}\n\ndfn {\n  font-style: italic;\n}\n\nhr {\n  height: 0;\n  -moz-box-sizing: content-box;\n       box-sizing: content-box;\n}\n\nmark {\n  color: #000;\n  background: #ff0;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n\npre {\n  white-space: pre-wrap;\n}\n\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n\nsmall {\n  font-size: 80%;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  border: 0;\n}\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\nfigure {\n  margin: 0;\n}\n\nfieldset {\n  padding: 0.35em 0.625em 0.75em;\n  margin: 0 2px;\n  border: 1px solid #c0c0c0;\n}\n\nlegend {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: 100%;\n}\n\nbutton,\ninput {\n  line-height: normal;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  padding: 0;\n  box-sizing: border-box;\n}\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}\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\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  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\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  @page  {\n    margin: 2cm .5cm;\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  .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* {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #333333;\n  background-color: #ffffff;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\na {\n  color: #428bca;\n  text-decoration: none;\n}\n\na:hover,\na:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\nimg {\n  vertical-align: middle;\n}\n\n.img-responsive {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n}\n\n.img-rounded {\n  border-radius: 6px;\n}\n\n.img-circle {\n  border-radius: 500px;\n}\n\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 16.099999999999998px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\n\nsmall {\n  font-size: 85%;\n}\n\ncite {\n  font-style: normal;\n}\n\n.text-muted {\n  color: #999999;\n}\n\n.text-primary {\n  color: #428bca;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\n.text-danger {\n  color: #b94a48;\n}\n\n.text-success {\n  color: #468847;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\n.text-left {\n  text-align: left;\n}\n\n.text-right {\n  text-align: right;\n}\n\n.text-center {\n  text-align: center;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 500;\n  line-height: 1.1;\n}\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 {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\n\nh4,\nh5,\nh6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\nh1,\n.h1 {\n  font-size: 38px;\n}\n\nh2,\n.h2 {\n  font-size: 32px;\n}\n\nh3,\n.h3 {\n  font-size: 24px;\n}\n\nh4,\n.h4 {\n  font-size: 18px;\n}\n\nh5,\n.h5 {\n  font-size: 14px;\n}\n\nh6,\n.h6 {\n  font-size: 12px;\n}\n\nh1 small,\n.h1 small {\n  font-size: 24px;\n}\n\nh2 small,\n.h2 small {\n  font-size: 18px;\n}\n\nh3 small,\n.h3 small,\nh4 small,\n.h4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\n\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 1.428571429;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 0;\n}\n\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\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\n.dl-horizontal dd:before,\n.dl-horizontal dd:after {\n  display: table;\n  content: \" \";\n}\n\n.dl-horizontal dd:after {\n  clear: both;\n}\n\n.dl-horizontal dd:before,\n.dl-horizontal dd:after {\n  display: table;\n  content: \" \";\n}\n\n.dl-horizontal dd:after {\n  clear: both;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\n\nblockquote p:last-child {\n  margin-bottom: 0;\n}\n\nblockquote small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.428571429;\n}\n\ncode,\npre {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n}\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}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.428571429;\n  color: #333333;\n  word-break: break-all;\n  word-wrap: break-word;\n  background-color: #f5f5f5;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .row {\n    margin-right: -15px;\n    margin-left: -15px;\n  }\n}\n\n.row .row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.col-1,\n.col-2,\n.col-3,\n.col-4,\n.col-5,\n.col-6,\n.col-7,\n.col-8,\n.col-9,\n.col-10,\n.col-11,\n.col-12,\n.col-sm-1,\n.col-sm-2,\n.col-sm-3,\n.col-sm-4,\n.col-sm-5,\n.col-sm-6,\n.col-sm-7,\n.col-sm-8,\n.col-sm-9,\n.col-sm-10,\n.col-sm-11,\n.col-sm-12,\n.col-lg-1,\n.col-lg-2,\n.col-lg-3,\n.col-lg-4,\n.col-lg-5,\n.col-lg-6,\n.col-lg-7,\n.col-lg-8,\n.col-lg-9,\n.col-lg-10,\n.col-lg-11,\n.col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col-1,\n.col-2,\n.col-3,\n.col-4,\n.col-5,\n.col-6,\n.col-7,\n.col-8,\n.col-9,\n.col-10,\n.col-11,\n.col-12 {\n  float: left;\n}\n\n.col-1 {\n  width: 8.333333333333332%;\n}\n\n.col-2 {\n  width: 16.666666666666664%;\n}\n\n.col-3 {\n  width: 25%;\n}\n\n.col-4 {\n  width: 33.33333333333333%;\n}\n\n.col-5 {\n  width: 41.66666666666667%;\n}\n\n.col-6 {\n  width: 50%;\n}\n\n.col-7 {\n  width: 58.333333333333336%;\n}\n\n.col-8 {\n  width: 66.66666666666666%;\n}\n\n.col-9 {\n  width: 75%;\n}\n\n.col-10 {\n  width: 83.33333333333334%;\n}\n\n.col-11 {\n  width: 91.66666666666666%;\n}\n\n.col-12 {\n  width: 100%;\n}\n\n@media (min-width: 768px) {\n  .container {\n    max-width: 728px;\n  }\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11,\n  .col-sm-12 {\n    float: left;\n  }\n  .col-sm-1 {\n    width: 8.333333333333332%;\n  }\n  .col-sm-2 {\n    width: 16.666666666666664%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-4 {\n    width: 33.33333333333333%;\n  }\n  .col-sm-5 {\n    width: 41.66666666666667%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-7 {\n    width: 58.333333333333336%;\n  }\n  .col-sm-8 {\n    width: 66.66666666666666%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-10 {\n    width: 83.33333333333334%;\n  }\n  .col-sm-11 {\n    width: 91.66666666666666%;\n  }\n  .col-sm-12 {\n    width: 100%;\n  }\n  .col-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-push-3 {\n    left: 25%;\n  }\n  .col-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-push-6 {\n    left: 50%;\n  }\n  .col-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-push-9 {\n    left: 75%;\n  }\n  .col-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-pull-3 {\n    right: 25%;\n  }\n  .col-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-pull-6 {\n    right: 50%;\n  }\n  .col-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-pull-9 {\n    right: 75%;\n  }\n  .col-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-pull-11 {\n    right: 91.66666666666666%;\n  }\n}\n\n@media (min-width: 992px) {\n  .container {\n    max-width: 940px;\n  }\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11,\n  .col-lg-12 {\n    float: left;\n  }\n  .col-lg-1 {\n    width: 8.333333333333332%;\n  }\n  .col-lg-2 {\n    width: 16.666666666666664%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-4 {\n    width: 33.33333333333333%;\n  }\n  .col-lg-5 {\n    width: 41.66666666666667%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-7 {\n    width: 58.333333333333336%;\n  }\n  .col-lg-8 {\n    width: 66.66666666666666%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-10 {\n    width: 83.33333333333334%;\n  }\n  .col-lg-11 {\n    width: 91.66666666666666%;\n  }\n  .col-lg-12 {\n    width: 100%;\n  }\n  .col-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-offset-3 {\n    margin-left: 25%;\n  }\n  .col-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-offset-6 {\n    margin-left: 50%;\n  }\n  .col-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-offset-9 {\n    margin-left: 75%;\n  }\n  .col-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container {\n    max-width: 1170px;\n  }\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n}\n\nth {\n  text-align: left;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\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.428571429;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table thead > tr > th {\n  vertical-align: bottom;\n}\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\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\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\n.table-bordered {\n  border: 1px solid #dddddd;\n}\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 #dddddd;\n}\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\n.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n  background-color: #f5f5f5;\n}\n\ntable col[class^=\"col-\"] {\n  display: table-column;\n  float: none;\n}\n\ntable td[class^=\"col-\"],\ntable th[class^=\"col-\"] {\n  display: table-cell;\n  float: none;\n}\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\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  border-color: #d6e9c6;\n}\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  border-color: #eed3d7;\n}\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  border-color: #fbeed5;\n}\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  background-color: #d0e9c6;\n  border-color: #c9e2b3;\n}\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  background-color: #ebcccc;\n  border-color: #e6c1c7;\n}\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  background-color: #faf2cc;\n  border-color: #f8e5be;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\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: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n\n  line-height: normal;\n}\n\ninput[type=\"file\"] {\n  display: block;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect optgroup {\n  font-family: inherit;\n  font-size: inherit;\n  font-style: inherit;\n}\n\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\n\n.form-control:-moz-placeholder {\n  color: #999999;\n}\n\n.form-control::-moz-placeholder {\n  color: #999999;\n}\n\n.form-control:-ms-input-placeholder {\n  color: #999999;\n}\n\n.form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: 38px;\n  padding: 8px 12px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n          transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n\n.form-control:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ntextarea.form-control {\n  height: auto;\n}\n\n.form-group {\n  margin-bottom: 15px;\n}\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  vertical-align: middle;\n}\n\n.radio label,\n.checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\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\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\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\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\n\n.input-large {\n  height: 56px;\n  padding: 14px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.input-small {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n\nselect.input-large {\n  height: 56px;\n  line-height: 56px;\n}\n\nselect.input-small {\n  height: 30px;\n  line-height: 30px;\n}\n\ntextarea.input-large,\ntextarea.input-small {\n  height: auto;\n}\n\n.has-warning .help-block,\n.has-warning .control-label {\n  color: #c09853;\n}\n\n.has-warning .form-control {\n  padding-right: 32px;\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-warning .form-control:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.has-warning .input-group-addon {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.has-error .help-block,\n.has-error .control-label {\n  color: #b94a48;\n}\n\n.has-error .form-control {\n  padding-right: 32px;\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-error .form-control:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.has-error .input-group-addon {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.has-success .help-block,\n.has-success .control-label {\n  color: #468847;\n}\n\n.has-success .form-control {\n  padding-right: 32px;\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-success .form-control:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.has-success .input-group-addon {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n\n.btn {\n  display: inline-block;\n  padding: 8px 12px;\n  margin-bottom: 0;\n  font-size: 14px;\n  font-weight: 500;\n  line-height: 1.428571429;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  cursor: pointer;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n       -o-user-select: none;\n          user-select: none;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn:hover,\n.btn:focus {\n  color: #ffffff;\n  text-decoration: none;\n}\n\n.btn:active,\n.btn.active {\n  outline: 0;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  pointer-events: none;\n  cursor: default;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-default {\n  color: #ffffff;\n  background-color: #474949;\n  border-color: #474949;\n}\n\n.btn-default:hover,\n.btn-default:focus,\n.btn-default:active,\n.btn-default.active {\n  background-color: #3a3c3c;\n  border-color: #2e2f2f;\n}\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: #474949;\n  border-color: #474949;\n}\n\n.btn-primary {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #357ebd;\n  border-color: #3071a9;\n}\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: #428bca;\n}\n\n.btn-warning {\n  color: #ffffff;\n  background-color: #f0ad4e;\n  border-color: #f0ad4e;\n}\n\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #eea236;\n  border-color: #ec971f;\n}\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: #f0ad4e;\n}\n\n.btn-danger {\n  color: #ffffff;\n  background-color: #d9534f;\n  border-color: #d9534f;\n}\n\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #d43f3a;\n  border-color: #c9302c;\n}\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: #d9534f;\n}\n\n.btn-success {\n  color: #ffffff;\n  background-color: #5cb85c;\n  border-color: #5cb85c;\n}\n\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active {\n  background-color: #4cae4c;\n  border-color: #449d44;\n}\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: #5cb85c;\n}\n\n.btn-info {\n  color: #ffffff;\n  background-color: #5bc0de;\n  border-color: #5bc0de;\n}\n\n.btn-info:hover,\n.btn-info:focus,\n.btn-info:active,\n.btn-info.active {\n  background-color: #46b8da;\n  border-color: #31b0d5;\n}\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: #5bc0de;\n}\n\n.btn-link {\n  font-weight: normal;\n  color: #428bca;\n  cursor: pointer;\n  border-radius: 0;\n}\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\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n\n.btn-link:hover,\n.btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-large {\n  padding: 14px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.btn-small,\n.btn-mini {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-mini {\n  padding: 3px 5px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  display: none;\n}\n\n.collapse.in {\n  display: block;\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.input-group {\n  display: table;\n  border-collapse: separate;\n}\n\n.input-group.col {\n  float: none;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.input-group .form-control {\n  width: 100%;\n  margin-bottom: 0;\n}\n\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n}\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\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n\n.input-group-addon {\n  padding: 8px 12px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1.428571429;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.input-group-addon.input-small {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n\n.input-group-addon.input-large {\n  padding: 14px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\n}\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 > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group-addon:first-child {\n  border-right: 0;\n}\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 > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n.input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n\n.input-group-btn > .btn {\n  position: relative;\n}\n\n.input-group-btn > .btn + .btn {\n  margin-left: -4px;\n}\n\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:active {\n  z-index: 2;\n}\n\n.form-inline .form-control,\n.form-inline .radio,\n.form-inline .checkbox {\n  display: inline-block;\n}\n\n.form-inline .radio,\n.form-inline .checkbox {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.form-horizontal .control-label {\n  padding-top: 9px;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .form-horizontal .form-group {\n    margin-right: -15px;\n    margin-left: -15px;\n  }\n}\n\n.form-horizontal .form-group .row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\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 #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\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  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 4px;\n  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n          box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n  background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 1.428571429;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #357ebd;\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);\n}\n\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #357ebd;\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);\n}\n\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #999999;\n}\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\n.open > .dropdown-menu {\n  display: block;\n}\n\n.open > a {\n  outline: 0;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.428571429;\n  color: #999999;\n}\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\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.list-group {\n  padding-left: 0;\n  margin-bottom: 20px;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 30px 10px 15px;\n  margin-bottom: -1px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n}\n\n.list-group-item:first-child {\n  border-top-right-radius: 4px;\n  border-top-left-radius: 4px;\n}\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\n.list-group-item > .badge {\n  float: right;\n  margin-right: -15px;\n}\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n\na.list-group-item .list-group-item-heading {\n  color: #333333;\n}\n\na.list-group-item .list-group-item-text {\n  color: #555555;\n}\n\na.list-group-item:hover,\na.list-group-item:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\na.list-group-item.active {\n  z-index: 2;\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\na.list-group-item.active .list-group-item-heading {\n  color: inherit;\n}\n\na.list-group-item.active .list-group-item-text {\n  color: #e1edf7;\n}\n\n.panel {\n  padding: 15px;\n  margin-bottom: 20px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.panel-heading {\n  padding: 10px 15px;\n  margin: -15px -15px 15px;\n  background-color: #f5f5f5;\n  border-bottom: 1px solid #dddddd;\n  border-top-right-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 17.5px;\n  font-weight: 500;\n}\n\n.panel-footer {\n  padding: 10px 15px;\n  margin: 15px -15px -15px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dddddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n\n.panel-primary {\n  border-color: #428bca;\n}\n\n.panel-primary .panel-heading {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.panel-success {\n  border-color: #d6e9c6;\n}\n\n.panel-success .panel-heading {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.panel-warning {\n  border-color: #fbeed5;\n}\n\n.panel-warning .panel-heading {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #fbeed5;\n}\n\n.panel-danger {\n  border-color: #eed3d7;\n}\n\n.panel-danger .panel-heading {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.panel-info {\n  border-color: #bce8f1;\n}\n\n.panel-info .panel-heading {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.list-group-flush {\n  margin: 15px -15px -15px;\n}\n\n.list-group-flush .list-group-item {\n  border-width: 1px 0;\n}\n\n.list-group-flush .list-group-item:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.list-group-flush .list-group-item:last-child {\n  border-bottom: 0;\n}\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, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  border-radius: 3px;\n}\n\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover,\n.close:focus {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.nav {\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav > li {\n  position: relative;\n  display: block;\n}\n\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li.disabled > a {\n  color: #999999;\n}\n\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n}\n\n.nav.open > a,\n.nav.open > a:hover,\n.nav.open > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.nav.open > a .caret,\n.nav.open > a:hover .caret,\n.nav.open > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.428571429;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee;\n}\n\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-bottom-color: transparent;\n}\n\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-justified > li {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.nav-tabs.nav-justified > li > a {\n  text-align: center;\n}\n\n.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs.nav-justified > .active > a {\n  border-bottom-color: #ffffff;\n}\n\n.nav-pills > li {\n  float: left;\n}\n\n.nav-pills > li > a {\n  border-radius: 5px;\n}\n\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n\n.nav-justified {\n  width: 100%;\n}\n\n.nav-justified > li {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.nav-justified > li > a {\n  text-align: center;\n}\n\n.nav-tabs-justified {\n  border-bottom: 0;\n}\n\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs-justified > .active > a {\n  border-bottom-color: #ffffff;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  content: \" \";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  content: \" \";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.nav .caret {\n  border-top-color: #428bca;\n  border-bottom-color: #428bca;\n}\n\n.nav a:hover .caret {\n  border-top-color: #2a6496;\n  border-bottom-color: #2a6496;\n}\n\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar {\n  position: relative;\n  min-height: 50px;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 20px;\n  background-color: #eeeeee;\n  border-radius: 4px;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n.navbar-nav {\n  margin-top: 10px;\n  margin-bottom: 15px;\n}\n\n.navbar-nav > li > a {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  line-height: 20px;\n  color: #777777;\n  border-radius: 4px;\n}\n\n.navbar-nav > li > a:hover,\n.navbar-nav > li > a:focus {\n  color: #333333;\n  background-color: transparent;\n}\n\n.navbar-nav > .active > a,\n.navbar-nav > .active > a:hover,\n.navbar-nav > .active > a:focus {\n  color: #555555;\n  background-color: #d5d5d5;\n}\n\n.navbar-nav > .disabled > a,\n.navbar-nav > .disabled > a:hover,\n.navbar-nav > .disabled > a:focus {\n  color: #cccccc;\n  background-color: transparent;\n}\n\n.navbar-nav.pull-right {\n  width: 100%;\n}\n\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  border-radius: 0;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n}\n\n.navbar-brand {\n  display: block;\n  max-width: 200px;\n  padding: 15px 15px;\n  margin-right: auto;\n  margin-left: auto;\n  font-size: 18px;\n  font-weight: 500;\n  line-height: 20px;\n  color: #777777;\n  text-align: center;\n}\n\n.navbar-brand:hover,\n.navbar-brand:focus {\n  color: #5e5e5e;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar-toggle {\n  position: absolute;\n  top: 9px;\n  right: 10px;\n  width: 48px;\n  height: 32px;\n  padding: 8px 12px;\n  background-color: transparent;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n}\n\n.navbar-toggle:hover,\n.navbar-toggle:focus {\n  background-color: #dddddd;\n}\n\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  background-color: #cccccc;\n  border-radius: 1px;\n}\n\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n\n.navbar-form {\n  margin-top: 6px;\n  margin-bottom: 6px;\n}\n\n.navbar-form .form-control,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  display: inline-block;\n}\n\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.navbar-nav > .dropdown > a:hover .caret,\n.navbar-nav > .dropdown > a:focus .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n\n.navbar-nav > .open > a,\n.navbar-nav > .open > a:hover,\n.navbar-nav > .open > a:focus {\n  color: #555555;\n  background-color: #d5d5d5;\n}\n\n.navbar-nav > .open > a .caret,\n.navbar-nav > .open > a:hover .caret,\n.navbar-nav > .open > a:focus .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar-nav > .dropdown > a .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar-inverse {\n  background-color: #222222;\n}\n\n.navbar-inverse .navbar-brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\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: #ffffff;\n  background-color: #080808;\n}\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: #444444;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-toggle {\n  border-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #ffffff;\n}\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: #ffffff;\n  background-color: #080808;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .navbar-nav > .open > a .caret,\n.navbar-inverse .navbar-nav > .open > a:hover .caret,\n.navbar-inverse .navbar-nav > .open > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n@media screen and (min-width: 768px) {\n  .navbar-brand {\n    float: left;\n    margin-right: 5px;\n    margin-left: -15px;\n  }\n  .navbar-nav {\n    float: left;\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n  .navbar-nav > li {\n    float: left;\n  }\n  .navbar-nav > li > a {\n    border-radius: 0;\n  }\n  .navbar-nav.pull-right {\n    float: right;\n    width: auto;\n  }\n  .navbar-toggle {\n    position: relative;\n    top: auto;\n    left: auto;\n    display: none;\n  }\n  .nav-collapse.collapse {\n    display: block !important;\n    height: auto !important;\n    overflow: visible !important;\n  }\n}\n\n.navbar-btn {\n  margin-top: 6px;\n}\n\n.navbar-text {\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.btn .caret {\n  border-top-color: #ffffff;\n}\n\n.dropup .btn .caret {\n  border-bottom-color: #ffffff;\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\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  z-index: 2;\n}\n\n.btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar .btn-group {\n  float: left;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group,\n.btn-toolbar > .btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n}\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\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group > .btn-group {\n  float: left;\n}\n\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\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\n.btn-group > .btn-group:last-child > .btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  padding-right: 8px;\n  padding-left: 8px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  padding-right: 12px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn .caret {\n  margin-left: 0;\n}\n\n.btn-large .caret {\n  border-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n}\n\n.btn-group-vertical .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n\n.btn-group-vertical .btn:first-child {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical .btn:last-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n}\n\n.btn-group-justified .btn {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.btn-group[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n.btn-group[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\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\n.breadcrumb > li {\n  display: inline-block;\n}\n\n.breadcrumb > li + li:before {\n  padding: 0 5px;\n  color: #cccccc;\n  content: \"/\\00a0\";\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n\n.pagination > li {\n  display: inline;\n}\n\n.pagination > li > a,\n.pagination > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 1.428571429;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  border-left-width: 1px;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n}\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\n.pagination > li > a:hover,\n.pagination > li > a:focus,\n.pagination > .active > a,\n.pagination > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination > .active > a,\n.pagination > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination > .disabled > span,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n}\n\n.pagination-large > li > a,\n.pagination-large > li > span {\n  padding: 14px 16px;\n  font-size: 18px;\n}\n\n.pagination-large > li:first-child > a,\n.pagination-large > li:first-child > span {\n  border-bottom-left-radius: 6px;\n  border-top-left-radius: 6px;\n}\n\n.pagination-large > li:last-child > a,\n.pagination-large > li:last-child > span {\n  border-top-right-radius: 6px;\n  border-bottom-right-radius: 6px;\n}\n\n.pagination-small > li > a,\n.pagination-small > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n\n.pagination-small > li:first-child > a,\n.pagination-small > li:first-child > span {\n  border-bottom-left-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.pagination-small > li:last-child > a,\n.pagination-small > li:last-child > span {\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n\n.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 15px;\n}\n\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n}\n\n.modal-open {\n  overflow: hidden;\n}\n\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n}\n\n.modal.fade .modal-dialog {\n  -webkit-transform: translate(0, -25%);\n      -ms-transform: translate(0, -25%);\n          transform: translate(0, -25%);\n  -webkit-transition: -webkit-transform 0.3s ease-out;\n     -moz-transition: -moz-transform 0.3s ease-out;\n       -o-transition: -o-transform 0.3s ease-out;\n          transition: transform 0.3s ease-out;\n}\n\n.modal.fade.in .modal-dialog {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n\n.modal-dialog {\n  z-index: 1050;\n  width: auto;\n  padding: 10px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.modal-content {\n  position: relative;\n  background-color: #ffffff;\n  border: 1px solid #999999;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n          box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n  background-clip: padding-box;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n\n.modal-backdrop.fade.in {\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.modal-header {\n  min-height: 16.428571429px;\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n}\n\n.modal-header .close {\n  margin-top: -2px;\n}\n\n.modal-title {\n  margin: 0;\n  line-height: 1.428571429;\n}\n\n.modal-body {\n  position: relative;\n  padding: 20px;\n}\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\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n@media screen and (min-width: 768px) {\n  .modal-dialog {\n    right: auto;\n    left: 50%;\n    width: 600px;\n    padding-top: 30px;\n    padding-bottom: 30px;\n  }\n  .modal-content {\n    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n  }\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 12px;\n  line-height: 1.4;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: rgba(0, 0, 0, 0.9);\n  border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-top-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-right .tooltip-arrow {\n  right: 5px;\n  bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: rgba(0, 0, 0, 0.9);\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-bottom-color: rgba(0, 0, 0, 0.9);\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-bottom-color: rgba(0, 0, 0, 0.9);\n  border-width: 0 5px 5px;\n}\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: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  background-clip: padding-box;\n  -webkit-bg-clip: padding-box;\n     -moz-bg-clip: padding;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\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\n.popover-content {\n  padding: 9px 14px;\n}\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\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n  content: \" \";\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n  content: \" \";\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n  content: \" \";\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n  content: \" \";\n}\n\n.alert {\n  padding: 10px 35px 10px 15px;\n  margin-bottom: 20px;\n  color: #c09853;\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  border-radius: 4px;\n}\n\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n\n.alert hr {\n  border-top-color: #f8e5be;\n}\n\n.alert .alert-link {\n  font-weight: 500;\n  color: #a47e3c;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n\n.alert-success .alert-link {\n  color: #356635;\n}\n\n.alert-danger {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger hr {\n  border-top-color: #e6c1c7;\n}\n\n.alert-danger .alert-link {\n  color: #953b39;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n\n.alert-info .alert-link {\n  color: #2d6987;\n}\n\n.alert-block {\n  padding-top: 15px;\n  padding-bottom: 15px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.thumbnail,\n.img-thumbnail {\n  padding: 4px;\n  line-height: 1.428571429;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\n.thumbnail {\n  display: block;\n}\n\n.thumbnail > img,\n.img-thumbnail {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n}\n\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: #428bca;\n}\n\n.thumbnail > img {\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #333333;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media > .pull-left {\n  margin-right: 10px;\n}\n\n.media > .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n\n.label {\n  display: inline;\n  padding: .25em .6em;\n  font-size: 75%;\n  font-weight: 500;\n  line-height: 1;\n  color: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  background-color: #999999;\n  border-radius: .25em;\n}\n\n.label[href]:hover,\n.label[href]:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n  background-color: #808080;\n}\n\n.label-danger {\n  background-color: #d9534f;\n}\n\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\n}\n\n.label-success {\n  background-color: #5cb85c;\n}\n\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n\n.label-warning {\n  background-color: #f0ad4e;\n}\n\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n\n.label-info {\n  background-color: #5bc0de;\n}\n\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\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: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  background-color: #999999;\n  border-radius: 10px;\n}\n\n.badge:empty {\n  display: none;\n}\n\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #ffffff;\n}\n\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\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\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\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\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, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  background-color: #428bca;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress-striped .progress-bar {\n  background-color: #428bca;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-size: 40px 40px;\n}\n\n.progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n\n.progress-striped .progress-bar-danger {\n  background-color: #d9534f;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-success {\n  background-color: #5cb85c;\n}\n\n.progress-striped .progress-bar-success {\n  background-color: #5cb85c;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n\n.progress-striped .progress-bar-warning {\n  background-color: #f0ad4e;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n\n.progress-striped .progress-bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\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: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.left {\n  background-color: rgba(0, 0, 0, 0.0001);\n  background-color: transparent;\n  background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%));\n  background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n\n.carousel-control.right {\n  right: 0;\n  left: auto;\n  background-color: rgba(0, 0, 0, 0.5);\n  background-color: transparent;\n  background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%));\n  background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-control .glyphicon,\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  z-index: 5;\n  display: inline-block;\n  width: 20px;\n  height: 20px;\n  margin-top: -10px;\n  margin-left: -10px;\n  font-family: serif;\n}\n\n.carousel-control .icon-prev:before {\n  content: '\\2039';\n}\n\n.carousel-control .icon-next:before {\n  content: '\\203a';\n}\n\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 120px;\n  padding-left: 0;\n  margin-left: -60px;\n  text-align: center;\n  list-style: none;\n}\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  border: 1px solid #ffffff;\n  border-radius: 10px;\n}\n\n.carousel-indicators .active {\n  width: 12px;\n  height: 12px;\n  margin: 0;\n  background-color: #ffffff;\n}\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: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n\n.carousel-caption .btn {\n  text-shadow: none;\n}\n\n@media screen and (min-width: 768px) {\n  .carousel-control .glyphicon,\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\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 2.1428571435;\n  color: inherit;\n  background-color: #eeeeee;\n}\n\n.jumbotron h1 {\n  line-height: 1;\n  color: inherit;\n}\n\n.jumbotron p {\n  line-height: 1.4;\n}\n\n@media screen and (min-width: 768px) {\n  .jumbotron {\n    padding: 50px 60px;\n    border-radius: 6px;\n  }\n  .jumbotron h1 {\n    font-size: 63px;\n  }\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  content: \" \";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none !important;\n}\n\n.show {\n  display: block !important;\n}\n\n.invisible {\n  visibility: hidden;\n}\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\n.affix {\n  position: fixed;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\n@media screen and (max-width: 400px) {\n  @-ms-viewport {\n    width: 320px;\n  }\n}\n\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n.visible-sm {\n  display: block !important;\n}\n\ntr.visible-sm {\n  display: table-row !important;\n}\n\nth.visible-sm,\ntd.visible-sm {\n  display: table-cell !important;\n}\n\n.visible-md {\n  display: none !important;\n}\n\ntr.visible-md {\n  display: none !important;\n}\n\nth.visible-md,\ntd.visible-md {\n  display: none !important;\n}\n\n.visible-lg {\n  display: none !important;\n}\n\ntr.visible-lg {\n  display: none !important;\n}\n\nth.visible-lg,\ntd.visible-lg {\n  display: none !important;\n}\n\n.hidden-sm {\n  display: none !important;\n}\n\ntr.hidden-sm {\n  display: none !important;\n}\n\nth.hidden-sm,\ntd.hidden-sm {\n  display: none !important;\n}\n\n.hidden-md {\n  display: block !important;\n}\n\ntr.hidden-md {\n  display: table-row !important;\n}\n\nth.hidden-md,\ntd.hidden-md {\n  display: table-cell !important;\n}\n\n.hidden-lg {\n  display: block !important;\n}\n\ntr.hidden-lg {\n  display: table-row !important;\n}\n\nth.hidden-lg,\ntd.hidden-lg {\n  display: table-cell !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm {\n    display: none !important;\n  }\n  tr.visible-sm {\n    display: none !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: none !important;\n  }\n  .visible-md {\n    display: block !important;\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  .visible-lg {\n    display: none !important;\n  }\n  tr.visible-lg {\n    display: none !important;\n  }\n  th.visible-lg,\n  td.visible-lg {\n    display: none !important;\n  }\n  .hidden-sm {\n    display: block !important;\n  }\n  tr.hidden-sm {\n    display: table-row !important;\n  }\n  th.hidden-sm,\n  td.hidden-sm {\n    display: table-cell !important;\n  }\n  .hidden-md {\n    display: none !important;\n  }\n  tr.hidden-md {\n    display: none !important;\n  }\n  th.hidden-md,\n  td.hidden-md {\n    display: none !important;\n  }\n  .hidden-lg {\n    display: block !important;\n  }\n  tr.hidden-lg {\n    display: table-row !important;\n  }\n  th.hidden-lg,\n  td.hidden-lg {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .visible-sm {\n    display: none !important;\n  }\n  tr.visible-sm {\n    display: none !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: none !important;\n  }\n  .visible-md {\n    display: none !important;\n  }\n  tr.visible-md {\n    display: none !important;\n  }\n  th.visible-md,\n  td.visible-md {\n    display: none !important;\n  }\n  .visible-lg {\n    display: block !important;\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  .hidden-sm {\n    display: block !important;\n  }\n  tr.hidden-sm {\n    display: table-row !important;\n  }\n  th.hidden-sm,\n  td.hidden-sm {\n    display: table-cell !important;\n  }\n  .hidden-md {\n    display: block !important;\n  }\n  tr.hidden-md {\n    display: table-row !important;\n  }\n  th.hidden-md,\n  td.hidden-md {\n    display: table-cell !important;\n  }\n  .hidden-lg {\n    display: none !important;\n  }\n  tr.hidden-lg {\n    display: none !important;\n  }\n  th.hidden-lg,\n  td.hidden-lg {\n    display: none !important;\n  }\n}\n\n.visible-print {\n  display: none !important;\n}\n\ntr.visible-print {\n  display: none !important;\n}\n\nth.visible-print,\ntd.visible-print {\n  display: none !important;\n}\n\n@media print {\n  .visible-print {\n    display: block !important;\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  .hidden-print {\n    display: none !important;\n  }\n  tr.hidden-print {\n    display: none !important;\n  }\n  th.hidden-print,\n  td.hidden-print {\n    display: none !important;\n  }\n}"
  },
  {
    "path": "site/examples/madlibs/index.html",
    "content": "<!DOCTYPE html>\n\n<html>\n<head>\n  <title>Mad Libs</title>\n  <meta name=\"description\" content=\"\">\n  <meta name=\"author\" content=\"\">\n  <link rel=\"stylesheet\" href=\"css/app.css\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <!-- Bootstrap -->\n  <link href=\"css/bootstrap.min.css\" rel=\"stylesheet\" media=\"screen\">\n\n  <style type=\"text/css\" media=\"screen\">\n    .main{\n      padding: 80px 15px;\n    }\n\n    h1 {\n      color: #2D373F;\n    }\n\n    .navbar {\n      background: #16a085;\n    }\n\n    .navbar-inverse .navbar-brand {\n      color: #fff;\n    }\n\n    .revealarea {\n\n    }\n\n    .madlib {\n      background: #f5f5f5;\n      padding: 20px;\n      border-radius: 4px;\n      border:1px solid #e3e3e3;\n    }\n\n    .form-control {\n      width: inherit;\n      display: inline;\n      margin-bottom: 10px;\n      padding: 0px 8px;\n    }\n\n    /*reset Twitter Bootstrap*/\n    @media screen {\n      * {\n        -webkit-box-sizing: content-box !important;\n        -moz-box-sizing: content-box !important;\n        box-sizing: content-box !important;\n      }\n    }\n\n    .container a img {\n      width: 135px;\n      height: 34px;\n    }\n\n\n  </style>\n\n</head>\n  <body>\n\n    <div class=\"navbar navbar-inverse navbar-fixed-top\">\n      <div class=\"container\">\n        <a class=\"navbar-brand pull-left\" href=\"#\">Mad Libs</a>\n        <a href=\"#\" class=\"navbar-btn pull-right\" onclick=\"TogetherJS(this); return false;\"><img src=\"/images/start-togetherjs-gray.png\"></a>\n      </div>\n    </div>\n\n    <div class=\"container\">\n      <div class=\"main\">\n        <div class=\"row\">\n            <h1>Let's play Mad Libs with a friend!</h1>\n            <div class=\"madlib madlib-hidden\">\n              <p>One day my <input type=\"text\" class=\"form-control\" placeholder=\"adjective\"> friend and I decided to go to the <input type=\"text\" class=\"form-control\" placeholder=\"sports noun\"> game in <input type=\"text\" class=\"form-control\" placeholder=\"city name\">.  We really wanted to see the <input type=\"text\" class=\"form-control\" placeholder=\"noun\"> play the <input type=\"text\" class=\"form-control\" placeholder=\"noun\">.  So we <input type=\"text\" class=\"form-control\" placeholder=\"action verb\"> our <input type=\"text\" class=\"form-control\" placeholder=\"noun\"> down to the <input type=\"text\" class=\"form-control\" placeholder=\"noun\"> and bought some <input type=\"text\" class=\"form-control\" placeholder=\"noun\">.  We got into the game and it was a lot of fun.  We ate some <input type=\"text\" class=\"form-control\" placeholder=\"adjective\"> <input type=\"text\" class=\"form-control\" placeholder=\"noun\"> and drank some <input type=\"text\" class=\"form-control\" placeholder=\"adjective\"> <input type=\"text\" class=\"form-control\" placeholder=\"noun\">.  We had a great time!  We plan to go again next year!</p>\n\n              <button type=\"button\" class=\"btn btn-default btn-block\" id=\"reveal\">Reveal MadLib!</button>\n              <button type=\"button\" id=\"hide\" style=\"display: none\" class=\"btn btn-default btn-block\">Hide Madlib!</button>\n\n\n            </div>\n\n        </div>\n      </div>\n    </div>\n\n    <!-- togetherjs -->\n    <script>\n      TogetherJSConfig_findRoom = {prefix: \"togetherjsmadlibs\", max: 5};\n      TogetherJSConfig_autoStart = true;\n      TogetherJSConfig_suppressJoinConfirmation = true;\n      TogetherJSConfig_storagePrefix = \"tjs_madlibs\";\n    </script>\n    <script src=\"/togetherjs.js\"></script>\n\n    <!-- JavaScript plugins (requires jQuery) -->\n    <script src=\"js/jquery-1.10.2.min.js\"></script>\n    <!-- Include all compiled plugins (below), or include individual files as needed -->\n    <script src=\"js/bootstrap.min.js\"></script>\n    <script src=\"js/app.js\"></script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/madlibs/js/app.js",
    "content": "function reveal() {\n  $(\".madlib\").removeClass(\"madlib-hidden\");\n  $(\"#reveal\").hide();\n  $(\"#hide\").show();\n}\n\nfunction hide() {\n  $(\".madlib\").addClass(\"madlib-hidden\");\n  $(\"#reveal\").show();\n  $(\"#hide\").hide();\n}\n\n$(\"#reveal\").click(reveal);\n$(\"#hide\").click(hide);\nTogetherJS.config(\"cloneClicks\", \"#reveal, #hide\");\n"
  },
  {
    "path": "site/examples/madlibs/js/bootstrap.js",
    "content": "/**\n* bootstrap.js v3.0.0 by @fat and @mdo\n* Copyright 2013 Twitter Inc.\n* http://www.apache.org/licenses/LICENSE-2.0\n*/\nif (!jQuery) { throw new Error(\"Bootstrap requires jQuery\") }\n\n/* ========================================================================\n * Bootstrap: transition.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#transitions\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)\n  // ============================================================\n\n  function transitionEnd() {\n    var el = document.createElement('bootstrap')\n\n    var transEndEventNames = {\n      'WebkitTransition' : 'webkitTransitionEnd'\n    , 'MozTransition'    : 'transitionend'\n    , 'OTransition'      : 'oTransitionEnd otransitionend'\n    , 'transition'       : 'transitionend'\n    }\n\n    for (var name in transEndEventNames) {\n      if (el.style[name] !== undefined) {\n        return { end: transEndEventNames[name] }\n      }\n    }\n  }\n\n  // http://blog.alexmaccaw.com/css-transitions\n  $.fn.emulateTransitionEnd = function (duration) {\n    var called = false, $el    = this\n    $(this).one($.support.transition.end, function () { called = true })\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\n    setTimeout(callback, duration)\n    return this\n  }\n\n  $(function () {\n    $.support.transition = transitionEnd()\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: alert.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#alerts\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // ALERT CLASS DEFINITION\n  // ======================\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n  var Alert   = function (el) {\n    $(el).on('click', dismiss, this.close)\n  }\n\n  Alert.prototype.close = function (e) {\n    var $this    = $(this)\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = $(selector)\n\n    if (e) e.preventDefault()\n\n    if (!$parent.length) {\n      $parent = $this.hasClass('alert') ? $this : $this.parent()\n    }\n\n    $parent.trigger(e = $.Event('close.bs.alert'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      $parent.trigger('closed.bs.alert').remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent\n        .one($.support.transition.end, removeElement)\n        .emulateTransitionEnd(150) :\n      removeElement()\n  }\n\n\n  // ALERT PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.alert\n\n  $.fn.alert = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.alert')\n\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.alert.Constructor = Alert\n\n\n  // ALERT NO CONFLICT\n  // =================\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n  // ALERT DATA-API\n  // ==============\n\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: button.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#buttons\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // BUTTON PUBLIC CLASS DEFINITION\n  // ==============================\n\n  var Button = function (element, options) {\n    this.$element = $(element)\n    this.options  = $.extend({}, Button.DEFAULTS, options)\n  }\n\n  Button.DEFAULTS = {\n    loadingText: 'loading...'\n  }\n\n  Button.prototype.setState = function (state) {\n    var d    = 'disabled'\n    var $el  = this.$element\n    var val  = $el.is('input') ? 'val' : 'html'\n    var data = $el.data()\n\n    state = state + 'Text'\n\n    if (!data.resetText) $el.data('resetText', $el[val]())\n\n    $el[val](data[state] || this.options[state])\n\n    // push to event loop to allow forms to submit\n    setTimeout(function () {\n      state == 'loadingText' ?\n        $el.addClass(d).attr(d, d) :\n        $el.removeClass(d).removeAttr(d);\n    }, 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input').prop('checked', !this.$element.hasClass('active'))\n      if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')\n    }\n\n    this.$element.toggleClass('active')\n  }\n\n\n  // BUTTON PLUGIN DEFINITION\n  // ========================\n\n  var old = $.fn.button\n\n  $.fn.button = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('button')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  $.fn.button.Constructor = Button\n\n\n  // BUTTON NO CONFLICT\n  // ==================\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n  // BUTTON DATA-API\n  // ===============\n\n  $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {\n    var $btn = $(e.target)\n    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\n    $btn.button('toggle')\n    e.preventDefault()\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: carousel.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#carousel\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CAROUSEL CLASS DEFINITION\n  // =========================\n\n  var Carousel = function (element, options) {\n    this.$element    = $(element)\n    this.$indicators = this.$element.find('.carousel-indicators')\n    this.options     = options\n    this.paused      =\n    this.sliding     =\n    this.interval    =\n    this.$active     =\n    this.$items      = null\n\n    this.options.pause == 'hover' && this.$element\n      .on('mouseenter', $.proxy(this.pause, this))\n      .on('mouseleave', $.proxy(this.cycle, this))\n  }\n\n  Carousel.DEFAULTS = {\n    interval: 5000\n  , pause: 'hover'\n  }\n\n  Carousel.prototype.cycle =  function (e) {\n    e || (this.paused = false)\n\n    this.interval && clearInterval(this.interval)\n\n    this.options.interval\n      && !this.paused\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n\n    return this\n  }\n\n  Carousel.prototype.getActiveIndex = function () {\n    this.$active = this.$element.find('.item.active')\n    this.$items  = this.$active.parent().children()\n\n    return this.$items.index(this.$active)\n  }\n\n  Carousel.prototype.to = function (pos) {\n    var that        = this\n    var activeIndex = this.getActiveIndex()\n\n    if (pos > (this.$items.length - 1) || pos < 0) return\n\n    if (this.sliding)       return this.$element.one('slid', function () { that.to(pos) })\n    if (activeIndex == pos) return this.pause().cycle()\n\n    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))\n  }\n\n  Carousel.prototype.pause = function (e) {\n    e || (this.paused = true)\n\n    if (this.$element.find('.next, .prev').length && $.support.transition.end) {\n      this.$element.trigger($.support.transition.end)\n      this.cycle(true)\n    }\n\n    this.interval = clearInterval(this.interval)\n\n    return this\n  }\n\n  Carousel.prototype.next = function () {\n    if (this.sliding) return\n    return this.slide('next')\n  }\n\n  Carousel.prototype.prev = function () {\n    if (this.sliding) return\n    return this.slide('prev')\n  }\n\n  Carousel.prototype.slide = function (type, next) {\n    var $active   = this.$element.find('.item.active')\n    var $next     = next || $active[type]()\n    var isCycling = this.interval\n    var direction = type == 'next' ? 'left' : 'right'\n    var fallback  = type == 'next' ? 'first' : 'last'\n    var that      = this\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    $next = $next.length ? $next : this.$element.find('.item')[fallback]()\n\n    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })\n\n    if ($next.hasClass('active')) return\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      this.$element.one('slid', function () {\n        var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])\n        $nextIndicator && $nextIndicator.addClass('active')\n      })\n    }\n\n    if ($.support.transition && this.$element.hasClass('slide')) {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $next.addClass(type)\n      $next[0].offsetWidth // force reflow\n      $active.addClass(direction)\n      $next.addClass(direction)\n      $active\n        .one($.support.transition.end, function () {\n          $next.removeClass([type, direction].join(' ')).addClass('active')\n          $active.removeClass(['active', direction].join(' '))\n          that.sliding = false\n          setTimeout(function () { that.$element.trigger('slid') }, 0)\n        })\n        .emulateTransitionEnd(600)\n    } else {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger('slid')\n    }\n\n    isCycling && this.cycle()\n\n    return this\n  }\n\n\n  // CAROUSEL PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.carousel\n\n  $.fn.carousel = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.carousel')\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\n      var action  = typeof option == 'string' ? option : options.slide\n\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\n      if (typeof option == 'number') data.to(option)\n      else if (action) data[action]()\n      else if (options.interval) data.pause().cycle()\n    })\n  }\n\n  $.fn.carousel.Constructor = Carousel\n\n\n  // CAROUSEL NO CONFLICT\n  // ====================\n\n  $.fn.carousel.noConflict = function () {\n    $.fn.carousel = old\n    return this\n  }\n\n\n  // CAROUSEL DATA-API\n  // =================\n\n  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {\n    var $this   = $(this), href\n    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n    var options = $.extend({}, $target.data(), $this.data())\n    var slideIndex = $this.attr('data-slide-to')\n    if (slideIndex) options.interval = false\n\n    $target.carousel(options)\n\n    if (slideIndex = $this.attr('data-slide-to')) {\n      $target.data('bs.carousel').to(slideIndex)\n    }\n\n    e.preventDefault()\n  })\n\n  $(window).on('load', function () {\n    $('[data-ride=\"carousel\"]').each(function () {\n      var $carousel = $(this)\n      $carousel.carousel($carousel.data())\n    })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: collapse.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#collapse\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // COLLAPSE PUBLIC CLASS DEFINITION\n  // ================================\n\n  var Collapse = function (element, options) {\n    this.$element      = $(element)\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\n    this.transitioning = null\n\n    if (this.options.parent) this.$parent = $(this.options.parent)\n    if (this.options.toggle) this.toggle()\n  }\n\n  Collapse.DEFAULTS = {\n    toggle: true\n  }\n\n  Collapse.prototype.dimension = function () {\n    var hasWidth = this.$element.hasClass('width')\n    return hasWidth ? 'width' : 'height'\n  }\n\n  Collapse.prototype.show = function () {\n    if (this.transitioning || this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('show.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var actives   = this.$parent && this.$parent.find('> .accordion-group > .in')\n\n    if (actives && actives.length) {\n      var hasData = actives.data('bs.collapse')\n      if (hasData && hasData.transitioning) return\n      actives.collapse('hide')\n      hasData || actives.data('bs.collapse', null)\n    }\n\n    var dimension = this.dimension()\n\n    this.$element\n      .removeClass('collapse')\n      .addClass('collapsing')\n      [dimension](0)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.$element\n        .removeClass('collapsing')\n        .addClass('in')\n        [dimension]('auto')\n      this.transitioning = 0\n      this.$element.trigger('shown.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\n\n    this.$element\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n      [dimension](this.$element[0][scrollSize])\n  }\n\n  Collapse.prototype.hide = function () {\n    if (this.transitioning || !this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('hide.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var dimension = this.dimension()\n\n    this.$element\n      [dimension](this.$element[dimension]())\n      [0].offsetHeight\n\n    this.$element\n      .addClass('collapsing')\n      .removeClass('collapse')\n      .removeClass('in')\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.transitioning = 0\n      this.$element\n        .trigger('hidden.bs.collapse')\n        .removeClass('collapsing')\n        .addClass('collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    this.$element\n      [dimension](0)\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n  }\n\n  Collapse.prototype.toggle = function () {\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\n  }\n\n\n  // COLLAPSE PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.collapse\n\n  $.fn.collapse = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.collapse')\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.collapse.Constructor = Collapse\n\n\n  // COLLAPSE NO CONFLICT\n  // ====================\n\n  $.fn.collapse.noConflict = function () {\n    $.fn.collapse = old\n    return this\n  }\n\n\n  // COLLAPSE DATA-API\n  // =================\n\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {\n    var $this   = $(this), href\n    var target  = $this.attr('data-target')\n        || e.preventDefault()\n        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') //strip for ie7\n    var $target = $(target)\n    var data    = $target.data('bs.collapse')\n    var option  = data ? 'toggle' : $this.data()\n    var parent  = $this.attr('data-parent')\n    var $parent = parent && $(parent)\n\n    if (!data || !data.transitioning) {\n      if ($parent) $parent.find('[data-toggle=collapse][data-parent=' + parent + ']').not($this).addClass('collapsed')\n      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')\n    }\n\n    $target.collapse(option)\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: dropdown.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#dropdowns\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // DROPDOWN CLASS DEFINITION\n  // =========================\n\n  var backdrop = '.dropdown-backdrop'\n  var toggle   = '[data-toggle=dropdown]'\n  var Dropdown = function (element) {\n    var $el = $(element).on('click.bs.dropdown', this.toggle)\n  }\n\n  Dropdown.prototype.toggle = function (e) {\n    var $this = $(this)\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    clearMenus()\n\n    if (!isActive) {\n      if ('ontouchstart' in document.documentElement) {\n        // if mobile we we use a backdrop because click events don't delegate\n        $('<div class=\"dropdown-backdrop\"/>').insertAfter($(this)).on('click', clearMenus)\n      }\n\n      $parent.trigger(e = $.Event('show.bs.dropdown'))\n\n      if (e.isDefaultPrevented()) return\n\n      $parent\n        .toggleClass('open')\n        .trigger('shown.bs.dropdown')\n    }\n\n    $this.focus()\n\n    return false\n  }\n\n  Dropdown.prototype.keydown = function (e) {\n    if (!/(38|40|27)/.test(e.keyCode)) return\n\n    var $this = $(this)\n\n    e.preventDefault()\n    e.stopPropagation()\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    if (!isActive || (isActive && e.keyCode == 27)) {\n      if (e.which == 27) $parent.find(toggle).focus()\n      return $this.click()\n    }\n\n    var $items = $('[role=menu] li:not(.divider):visible a', $parent)\n\n    if (!$items.length) return\n\n    var index = $items.index($items.filter(':focus'))\n\n    if (e.keyCode == 38 && index > 0)                 index--                        // up\n    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down\n    if (!~index)                                      index=0\n\n    $items.eq(index).focus()\n  }\n\n  function clearMenus() {\n    $(backdrop).remove()\n    $(toggle).each(function (e) {\n      var $parent = getParent($(this))\n      if (!$parent.hasClass('open')) return\n      $parent.trigger(e = $.Event('hide.bs.dropdown'))\n      if (e.isDefaultPrevented()) return\n      $parent.removeClass('open').trigger('hidden.bs.dropdown')\n    })\n  }\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    var $parent = selector && $(selector)\n\n    return $parent && $parent.length ? $parent : $this.parent()\n  }\n\n\n  // DROPDOWN PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('dropdown')\n\n      if (!data) $this.data('dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.dropdown.Constructor = Dropdown\n\n\n  // DROPDOWN NO CONFLICT\n  // ====================\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\n  // ===================================\n\n  $(document)\n    .on('click.bs.dropdown.data-api', clearMenus)\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.bs.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\n    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: modal.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#modals\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // MODAL CLASS DEFINITION\n  // ======================\n\n  var Modal = function (element, options) {\n    this.options   = options\n    this.$element  = $(element).on('click.dismiss.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this))\n    this.$backdrop =\n    this.isShown   = null\n\n    if (this.options.remote) this.$element.find('.modal-body').load(this.options.remote)\n  }\n\n  Modal.DEFAULTS = {\n      backdrop: true\n    , keyboard: true\n    , show: true\n  }\n\n  Modal.prototype.toggle = function () {\n    return this[!this.isShown ? 'show' : 'hide']()\n  }\n\n  Modal.prototype.show = function () {\n    var that = this\n    var e    = $.Event('show.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = true\n\n    this.escape()\n\n    this.backdrop(function () {\n      var transition = $.support.transition && that.$element.hasClass('fade')\n\n      if (!that.$element.parent().length) {\n        that.$element.appendTo(document.body) // don't move modals dom position\n      }\n\n      that.$element.show()\n\n      if (transition) {\n        that.$element[0].offsetWidth // force reflow\n      }\n\n      that.$element\n        .addClass('in')\n        .attr('aria-hidden', false)\n\n      that.enforceFocus()\n\n      transition ?\n        that.$element\n          .one($.support.transition.end, function () {\n            that.$element.focus().trigger('shown.bs.modal')\n          })\n          .emulateTransitionEnd(300) :\n        that.$element.focus().trigger('shown.bs.modal')\n    })\n  }\n\n  Modal.prototype.hide = function (e) {\n    if (e) e.preventDefault()\n\n    e = $.Event('hide.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (!this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = false\n\n    this.escape()\n\n    $(document).off('focusin.bs.modal')\n\n    this.$element\n      .removeClass('in')\n      .attr('aria-hidden', true)\n\n    $.support.transition && this.$element.hasClass('fade') ?\n      this.$element\n        .one($.support.transition.end, $.proxy(this.hideModal, this))\n        .emulateTransitionEnd(300) :\n      this.hideModal()\n  }\n\n  Modal.prototype.enforceFocus = function () {\n    $(document)\n      .off('focusin.bs.modal') // guard against infinite focus loop\n      .on('focusin.bs.modal', $.proxy(function (e) {\n        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\n          this.$element.focus()\n        }\n      }, this))\n  }\n\n  Modal.prototype.escape = function () {\n    if (this.isShown && this.options.keyboard) {\n      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {\n        e.which == 27 && this.hide()\n      }, this))\n    } else if (!this.isShown) {\n      this.$element.off('keyup.dismiss.bs.modal')\n    }\n  }\n\n  Modal.prototype.hideModal = function () {\n    var that = this\n    this.$element.hide()\n    this.backdrop(function () {\n      that.removeBackdrop()\n      that.$element.trigger('hidden.bs.modal')\n    })\n  }\n\n  Modal.prototype.removeBackdrop = function () {\n    this.$backdrop && this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  Modal.prototype.backdrop = function (callback) {\n    var that    = this\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n    if (this.isShown && this.options.backdrop) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n        .appendTo(document.body)\n\n      this.$element.on('click', $.proxy(function (e) {\n        if (e.target !== e.currentTarget) return\n        this.options.backdrop == 'static'\n          ? this.$element[0].focus.call(this.$element[0])\n          : this.hide.call(this)\n      }, this))\n\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n      this.$backdrop.addClass('in')\n\n      if (!callback) return\n\n      doAnimate ?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (!this.isShown && this.$backdrop) {\n      this.$backdrop.removeClass('in')\n\n      $.support.transition && this.$element.hasClass('fade')?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (callback) {\n      callback()\n    }\n  }\n\n\n  // MODAL PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.modal\n\n  $.fn.modal = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.modal')\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option]()\n      else if (options.show) data.show()\n    })\n  }\n\n  $.fn.modal.Constructor = Modal\n\n\n  // MODAL NO CONFLICT\n  // =================\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n  // MODAL DATA-API\n  // ==============\n\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this   = $(this)\n    var href    = $this.attr('href')\n    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) //strip for ie7\n    var option  = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())\n\n    e.preventDefault()\n\n    $target\n      .modal(option)\n      .one('hide', function () {\n        $this.is(':visible') && $this.focus()\n      })\n  })\n\n  $(function () {\n    var $body = $(document.body)\n      .on('shown.bs.modal',  '.modal', function () { $body.addClass('modal-open') })\n      .on('hidden.bs.modal', '.modal', function () { $body.removeClass('modal-open') })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: tooltip.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#affix\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // TOOLTIP PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Tooltip = function (element, options) {\n    this.type       =\n    this.options    =\n    this.enabled    =\n    this.timeout    =\n    this.hoverState =\n    this.$element   = null\n\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.DEFAULTS = {\n    animation: true\n  , placement: 'top'\n  , selector: false\n  , template: '<div class=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n  , trigger: 'hover focus'\n  , title: ''\n  , delay: 0\n  , html: false\n  , container: false\n  }\n\n  Tooltip.prototype.init = function (type, element, options) {\n    this.enabled  = true\n    this.type     = type\n    this.$element = $(element)\n    this.options  = this.getOptions(options)\n\n    var triggers = this.options.trigger.split(' ')\n\n    for (var i = triggers.length; i--;) {\n      var trigger = triggers[i]\n\n      if (trigger == 'click') {\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n      } else if (trigger != 'manual') {\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\n\n        this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n      }\n    }\n\n    this.options.selector ?\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n      this.fixTitle()\n  }\n\n  Tooltip.prototype.getDefaults = function () {\n    return Tooltip.DEFAULTS\n  }\n\n  Tooltip.prototype.getOptions = function (options) {\n    options = $.extend({}, this.getDefaults(), this.$element.data(), options)\n\n    if (options.delay && typeof options.delay == 'number') {\n      options.delay = {\n        show: options.delay\n      , hide: options.delay\n      }\n    }\n\n    return options\n  }\n\n  Tooltip.prototype.enter = function (obj) {\n    var defaults = this.getDefaults()\n    var options  = {}\n\n    this._options && $.each(this._options, function (key, value) {\n      if (defaults[key] != value) options[key] = value\n    })\n\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](options).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    if (!self.options.delay || !self.options.delay.show) return self.show()\n\n    self.hoverState = 'in'\n    self.timeout    = setTimeout(function () {\n      if (self.hoverState == 'in') self.show()\n    }, self.options.delay.show)\n  }\n\n  Tooltip.prototype.leave = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this._options).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n    self.hoverState = 'out'\n    self.timeout    = setTimeout(function () {\n      if (self.hoverState == 'out') self.hide()\n    }, self.options.delay.hide)\n  }\n\n  Tooltip.prototype.show = function () {\n    var e = $.Event('show.bs.'+ this.type)\n\n    if (this.hasContent() && this.enabled) {\n      this.$element.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      var $tip = this.tip()\n\n      this.setContent()\n\n      if (this.options.animation) $tip.addClass('fade')\n\n      var placement = typeof this.options.placement == 'function' ?\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\n        this.options.placement\n\n      var autoToken = /\\s?auto?\\s?/i\n      var autoPlace = autoToken.test(placement)\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\n\n      $tip\n        .detach()\n        .css({ top: 0, left: 0, display: 'block' })\n        .addClass(placement)\n\n      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n\n      var pos          = this.getPosition()\n      var actualWidth  = $tip[0].offsetWidth\n      var actualHeight = $tip[0].offsetHeight\n\n      if (autoPlace) {\n        var $parent = this.$element.parent()\n\n        var orgPlacement = placement\n        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop\n        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()\n        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()\n        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left\n\n        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :\n                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :\n                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :\n                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :\n                    placement\n\n        $tip\n          .removeClass(orgPlacement)\n          .addClass(placement)\n      }\n\n      var tp = placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :\n               placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :\n               placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\n            /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }\n\n      this.applyPlacement(tp, placement)\n      this.$element.trigger('shown.bs.' + this.type)\n    }\n  }\n\n  Tooltip.prototype.applyPlacement = function(offset, placement) {\n    var replace\n    var $tip   = this.tip()\n    var width  = $tip[0].offsetWidth\n    var height = $tip[0].offsetHeight\n\n    // manually read margins because getBoundingClientRect includes difference\n    offset.top  = offset.top  + parseInt($tip.css('margin-top'), 10)\n    offset.left = offset.left + parseInt($tip.css('margin-left'), 10)\n\n    $tip\n      .offset(offset)\n      .addClass('in')\n\n    var actualWidth  = $tip[0].offsetWidth\n    var actualHeight = $tip[0].offsetHeight\n\n    if (placement == 'top' && actualHeight != height) {\n      replace = true\n      offset.top  = offset.top + height - actualHeight\n    }\n\n    if (placement == 'bottom' || placement == 'top') {\n      var delta = 0\n\n      if (offset.left < 0){\n        delta       = offset.left * -2\n        offset.left = 0\n\n        $tip.offset(offset)\n\n        actualWidth  = $tip[0].offsetWidth\n        actualHeight = $tip[0].offsetHeight\n      }\n\n      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')\n    } else {\n      this.replaceArrow(actualHeight - height, actualHeight, 'top')\n    }\n\n    if (replace) $tip.offset(offset)\n  }\n\n  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {\n    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + \"%\") : '')\n  }\n\n  Tooltip.prototype.setContent = function () {\n    var $tip  = this.tip()\n    var title = this.getTitle()\n\n    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\n    $tip.removeClass('fade in top bottom left right')\n  }\n\n  Tooltip.prototype.hide = function () {\n    var that = this\n    var $tip = this.tip()\n    var e    = $.Event('hide.bs.' + this.type)\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    $tip.removeClass('in')\n\n    $.support.transition && this.$tip.hasClass('fade') ?\n      $tip\n        .one($.support.transition.end, $tip.detach)\n        .emulateTransitionEnd(150) :\n      $tip.detach()\n\n    this.$element.trigger('hidden.bs.' + this.type)\n\n    return this\n  }\n\n  Tooltip.prototype.fixTitle = function () {\n    var $e = this.$element\n    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n    }\n  }\n\n  Tooltip.prototype.hasContent = function () {\n    return this.getTitle()\n  }\n\n  Tooltip.prototype.getPosition = function () {\n    var el = this.$element[0]\n    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {\n      width: el.offsetWidth\n    , height: el.offsetHeight\n    }, this.$element.offset())\n  }\n\n  Tooltip.prototype.getTitle = function () {\n    var title\n    var $e = this.$element\n    var o  = this.options\n\n    title = $e.attr('data-original-title')\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n    return title\n  }\n\n  Tooltip.prototype.tip = function () {\n    return this.$tip = this.$tip || $(this.options.template)\n  }\n\n  Tooltip.prototype.arrow =function(){\n    return this.$arrow = this.$arrow || this.tip().find(\".tooltip-arrow\")\n  }\n\n  Tooltip.prototype.validate = function () {\n    if (!this.$element[0].parentNode) {\n      this.hide()\n      this.$element = null\n      this.options  = null\n    }\n  }\n\n  Tooltip.prototype.enable = function () {\n    this.enabled = true\n  }\n\n  Tooltip.prototype.disable = function () {\n    this.enabled = false\n  }\n\n  Tooltip.prototype.toggleEnabled = function () {\n    this.enabled = !this.enabled\n  }\n\n  Tooltip.prototype.toggle = function (e) {\n    var self = e ? $(e.currentTarget)[this.type](this._options).data('bs.' + this.type) : this\n    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n  }\n\n  Tooltip.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)\n  }\n\n\n  // TOOLTIP PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.tooltip')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n\n  // TOOLTIP NO CONFLICT\n  // ===================\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: popover.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#popovers\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // POPOVER PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\n\n  Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {\n    placement: 'right'\n  , trigger: 'click'\n  , content: ''\n  , template: '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n  // NOTE: POPOVER EXTENDS tooltip.js\n  // ================================\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\n\n  Popover.prototype.constructor = Popover\n\n  Popover.prototype.getDefaults = function () {\n    return Popover.DEFAULTS\n  }\n\n  Popover.prototype.setContent = function () {\n    var $tip    = this.tip()\n    var title   = this.getTitle()\n    var content = this.getContent()\n\n    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\n    $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)\n\n    $tip.removeClass('fade top bottom left right in')\n\n    $tip.find('.popover-title:empty').hide()\n  }\n\n  Popover.prototype.hasContent = function () {\n    return this.getTitle() || this.getContent()\n  }\n\n  Popover.prototype.getContent = function () {\n    var $e = this.$element\n    var o  = this.options\n\n    return $e.attr('data-content')\n      || (typeof o.content == 'function' ?\n            o.content.call($e[0]) :\n            o.content)\n  }\n\n  Popover.prototype.tip = function () {\n    if (!this.$tip) this.$tip = $(this.options.template)\n    return this.$tip\n  }\n\n  Popover.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData(this.type)\n  }\n\n\n  // POPOVER PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.popover\n\n  $.fn.popover = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.popover')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n\n  // POPOVER NO CONFLICT\n  // ===================\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: scrollspy.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#scrollspy\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    var href\n    var process  = $.proxy(this.process, this)\n\n    this.$element       = $(element).is('body') ? $(window) : $(element)\n    this.$body          = $('body')\n    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.offsets        = $([])\n    this.targets        = $([])\n    this.activeTarget   = null\n\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'\n\n    this.offsets = $([])\n    this.targets = $([])\n\n    var self     = this\n    var $targets = this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#\\w/.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        self.offsets.push(this[0])\n        self.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n    var maxScroll    = scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets.last()[0]) && this.activate(i)\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\n        && this.activate( targets[i] )\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    $(this.selector)\n      .parents('.active')\n      .removeClass('active')\n\n    var selector = this.selector\n      + '[data-target=\"' + target + '\"],'\n      + this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length)  {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      $spy.scrollspy($spy.data())\n    })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: tab.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#tabs\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // TAB CLASS DEFINITION\n  // ====================\n\n  var Tab = function (element) {\n    this.element = $(element)\n  }\n\n  Tab.prototype.show = function () {\n    var $this    = this.element\n    var $ul      = $this.closest('ul:not(.dropdown-menu)')\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    if ($this.parent('li').hasClass('active')) return\n\n    var previous = $ul.find('.active:last a')[0]\n    var e        = $.Event('show.bs.tab', {\n      relatedTarget: previous\n    })\n\n    $this.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    var $target = $(selector)\n\n    this.activate($this.parent('li'), $ul)\n    this.activate($target, $target.parent(), function () {\n      $this.trigger({\n        type: 'shown.bs.tab'\n      , relatedTarget: previous\n      })\n    })\n  }\n\n  Tab.prototype.activate = function (element, container, callback) {\n    var $active    = container.find('> .active')\n    var transition = callback\n      && $.support.transition\n      && $active.hasClass('fade')\n\n    function next() {\n      $active\n        .removeClass('active')\n        .find('> .dropdown-menu > .active')\n        .removeClass('active')\n\n      element.addClass('active')\n\n      if (transition) {\n        element[0].offsetWidth // reflow for transition\n        element.addClass('in')\n      } else {\n        element.removeClass('fade')\n      }\n\n      if (element.parent('.dropdown-menu')) {\n        element.closest('li.dropdown').addClass('active')\n      }\n\n      callback && callback()\n    }\n\n    transition ?\n      $active\n        .one($.support.transition.end, next)\n        .emulateTransitionEnd(150) :\n      next()\n\n    $active.removeClass('in')\n  }\n\n\n  // TAB PLUGIN DEFINITION\n  // =====================\n\n  var old = $.fn.tab\n\n  $.fn.tab = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.tab')\n\n      if (!data) $this.data('bs.tab', (data = new Tab(this)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tab.Constructor = Tab\n\n\n  // TAB NO CONFLICT\n  // ===============\n\n  $.fn.tab.noConflict = function () {\n    $.fn.tab = old\n    return this\n  }\n\n\n  // TAB DATA-API\n  // ============\n\n  $(document).on('click.bs.tab.data-api', '[data-toggle=\"tab\"], [data-toggle=\"pill\"]', function (e) {\n    e.preventDefault()\n    $(this).tab('show')\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: affix.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#affix\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // AFFIX CLASS DEFINITION\n  // ======================\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, Affix.DEFAULTS, options)\n    this.$window = $(window)\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\n\n    this.$element = $(element)\n    this.affixed  =\n    this.unpin    = null\n\n    this.checkPosition()\n  }\n\n  Affix.RESET = 'affix affix-top affix-bottom'\n\n  Affix.DEFAULTS = {\n    offset: 0\n  }\n\n  Affix.prototype.checkPositionWithEventLoop = function () {\n    setTimeout($.proxy(this.checkPosition, this), 1)\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var scrollHeight = $(document).height()\n    var scrollTop    = this.$window.scrollTop()\n    var position     = this.$element.offset()\n    var offset       = this.options.offset\n    var offsetTop    = offset.top\n    var offsetBottom = offset.bottom\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top()\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()\n\n    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :\n                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :\n                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false\n\n    if (this.affixed === affix) return\n    if (this.unpin) this.$element.css('top', '')\n\n    this.affixed = affix\n    this.unpin   = affix == 'bottom' ? position.top - scrollTop : null\n\n    this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))\n\n    if (affix == 'bottom') {\n      this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })\n    }\n  }\n\n\n  // AFFIX PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.affix\n\n  $.fn.affix = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.affix')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.affix.Constructor = Affix\n\n\n  // AFFIX NO CONFLICT\n  // =================\n\n  $.fn.affix.noConflict = function () {\n    $.fn.affix = old\n    return this\n  }\n\n\n  // AFFIX DATA-API\n  // ==============\n\n  $(window).on('load', function () {\n    $('[data-spy=\"affix\"]').each(function () {\n      var $spy = $(this)\n      var data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      if (data.offsetBottom) data.offset.bottom = data.offsetBottom\n      if (data.offsetTop)    data.offset.top    = data.offsetTop\n\n      $spy.affix(data)\n    })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "site/examples/persona/index.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block title %} Mozilla Labs : TogetherJS app integration example {% endblock %}\n{# set enableExample true #}\n{% block body %}\n\n<div class=\"container\">\n  <section class=\"body-content row\" id=\"main-section\" data-speed=\"4\" data-type=\"background\">\n\n<h1>Identity/Persona Example</h1>\n\n<p>TogetherJS will pick up your login information (and gravatar):\n<button id=\"login\"><img src=\"https://developer.mozilla.org/files/3969/plain_sign_in_blue.png\"></button>\n<button id=\"logout\" style=\"display: none\">logout</button>\n<button onclick=\"TogetherJS(this); return false\">Collaborate</button>\n</p>\n\n<div>\nThe integration code:<br>\n<pre id=\"main-code-dest\">\n</pre>\n\n<!--\n<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n   <circle cx=\"100\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"2\" fill=\"red\" />\n</svg>\n-->\n\n</div>\n\n    <script src=\"https://login.persona.org/include.js\"></script>\n    <script src=\"./md5.js\"></script>\n    <script id=\"main-code\">\nvar USER;\n$(function () {\n  $(\"#main-code-dest\").text($(\"#main-code\").text());\n\n  $(\"#login\").click(function () {\n    navigator.id.request();\n  });\n  $(\"#logout\").click(function () {\n    navigator.id.logout();\n  });\n\n  navigator.id.watch({\n    onlogin: function (assertion) {\n      assertion = assertion.replace(/-/g, \"+\");\n      assertion = assertion.replace(/_/g, \"/\");\n      var parts = assertion.split(/\\./g);\n      var data = JSON.parse(atob(parts[1]));\n      USER = data.principal.email;\n      $(\"#logout\").text(\"Logged in: \" + USER);\n      $(\"#login\").hide();\n      $(\"#logout\").show();\n      TogetherJS.refreshUserData();\n    },\n    onlogout: function () {\n      USER = null;\n      $(\"#login\").show();\n      $(\"#logout\").hide();\n      if (TogetherJS.require) {\n        TogetherJS.require(\"session\").close();\n      }\n    }\n  });\n});\n\nfunction gravatar(email, options) {\n  options = options || \"\";\n  email = email.toLowerCase().replace(/^\\s+/, \"\").replace(/\\s+$/, \"\");\n  var md5 = CryptoJS.MD5(email);\n  return \"https://www.gravatar.com/avatar/\" + md5 + options;\n}\n\nTogetherJS.config(\"getUserName\", function () {\n  return USER;\n});\n\nTogetherJS.config(\"getUserAvatar\", function () {\n  if (! USER) {\n    return null;\n  }\n  console.log(\"avatar\", gravatar(USER, \"?s=40&d=retro\"));\n  return gravatar(USER, \"?s=40&d=retro\");\n});\n\n    </script>\n\n  </section>\n\n</div><!-- /.container -->\n\n{% endblock %}\n"
  },
  {
    "path": "site/examples/persona/md5.js",
    "content": "/*\nCryptoJS v3.1.2\ncode.google.com/p/crypto-js\n(c) 2009-2013 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto-js/wiki/License\n*/\nvar CryptoJS=CryptoJS||function(s,p){var m={},l=m.lib={},n=function(){},r=l.Base={extend:function(b){n.prototype=this;var h=new n;b&&h.mixIn(b);h.hasOwnProperty(\"init\")||(h.init=function(){h.$super.init.apply(this,arguments)});h.init.prototype=h;h.$super=this;return h},create:function(){var b=this.extend();b.init.apply(b,arguments);return b},init:function(){},mixIn:function(b){for(var h in b)b.hasOwnProperty(h)&&(this[h]=b[h]);b.hasOwnProperty(\"toString\")&&(this.toString=b.toString)},clone:function(){return this.init.prototype.extend(this)}},\nq=l.WordArray=r.extend({init:function(b,h){b=this.words=b||[];this.sigBytes=h!=p?h:4*b.length},toString:function(b){return(b||t).stringify(this)},concat:function(b){var h=this.words,a=b.words,j=this.sigBytes;b=b.sigBytes;this.clamp();if(j%4)for(var g=0;g<b;g++)h[j+g>>>2]|=(a[g>>>2]>>>24-8*(g%4)&255)<<24-8*((j+g)%4);else if(65535<a.length)for(g=0;g<b;g+=4)h[j+g>>>2]=a[g>>>2];else h.push.apply(h,a);this.sigBytes+=b;return this},clamp:function(){var b=this.words,h=this.sigBytes;b[h>>>2]&=4294967295<<\n32-8*(h%4);b.length=s.ceil(h/4)},clone:function(){var b=r.clone.call(this);b.words=this.words.slice(0);return b},random:function(b){for(var h=[],a=0;a<b;a+=4)h.push(4294967296*s.random()|0);return new q.init(h,b)}}),v=m.enc={},t=v.Hex={stringify:function(b){var a=b.words;b=b.sigBytes;for(var g=[],j=0;j<b;j++){var k=a[j>>>2]>>>24-8*(j%4)&255;g.push((k>>>4).toString(16));g.push((k&15).toString(16))}return g.join(\"\")},parse:function(b){for(var a=b.length,g=[],j=0;j<a;j+=2)g[j>>>3]|=parseInt(b.substr(j,\n2),16)<<24-4*(j%8);return new q.init(g,a/2)}},a=v.Latin1={stringify:function(b){var a=b.words;b=b.sigBytes;for(var g=[],j=0;j<b;j++)g.push(String.fromCharCode(a[j>>>2]>>>24-8*(j%4)&255));return g.join(\"\")},parse:function(b){for(var a=b.length,g=[],j=0;j<a;j++)g[j>>>2]|=(b.charCodeAt(j)&255)<<24-8*(j%4);return new q.init(g,a)}},u=v.Utf8={stringify:function(b){try{return decodeURIComponent(escape(a.stringify(b)))}catch(g){throw Error(\"Malformed UTF-8 data\");}},parse:function(b){return a.parse(unescape(encodeURIComponent(b)))}},\ng=l.BufferedBlockAlgorithm=r.extend({reset:function(){this._data=new q.init;this._nDataBytes=0},_append:function(b){\"string\"==typeof b&&(b=u.parse(b));this._data.concat(b);this._nDataBytes+=b.sigBytes},_process:function(b){var a=this._data,g=a.words,j=a.sigBytes,k=this.blockSize,m=j/(4*k),m=b?s.ceil(m):s.max((m|0)-this._minBufferSize,0);b=m*k;j=s.min(4*b,j);if(b){for(var l=0;l<b;l+=k)this._doProcessBlock(g,l);l=g.splice(0,b);a.sigBytes-=j}return new q.init(l,j)},clone:function(){var b=r.clone.call(this);\nb._data=this._data.clone();return b},_minBufferSize:0});l.Hasher=g.extend({cfg:r.extend(),init:function(b){this.cfg=this.cfg.extend(b);this.reset()},reset:function(){g.reset.call(this);this._doReset()},update:function(b){this._append(b);this._process();return this},finalize:function(b){b&&this._append(b);return this._doFinalize()},blockSize:16,_createHelper:function(b){return function(a,g){return(new b.init(g)).finalize(a)}},_createHmacHelper:function(b){return function(a,g){return(new k.HMAC.init(b,\ng)).finalize(a)}}});var k=m.algo={};return m}(Math);\n(function(s){function p(a,k,b,h,l,j,m){a=a+(k&b|~k&h)+l+m;return(a<<j|a>>>32-j)+k}function m(a,k,b,h,l,j,m){a=a+(k&h|b&~h)+l+m;return(a<<j|a>>>32-j)+k}function l(a,k,b,h,l,j,m){a=a+(k^b^h)+l+m;return(a<<j|a>>>32-j)+k}function n(a,k,b,h,l,j,m){a=a+(b^(k|~h))+l+m;return(a<<j|a>>>32-j)+k}for(var r=CryptoJS,q=r.lib,v=q.WordArray,t=q.Hasher,q=r.algo,a=[],u=0;64>u;u++)a[u]=4294967296*s.abs(s.sin(u+1))|0;q=q.MD5=t.extend({_doReset:function(){this._hash=new v.init([1732584193,4023233417,2562383102,271733878])},\n_doProcessBlock:function(g,k){for(var b=0;16>b;b++){var h=k+b,w=g[h];g[h]=(w<<8|w>>>24)&16711935|(w<<24|w>>>8)&4278255360}var b=this._hash.words,h=g[k+0],w=g[k+1],j=g[k+2],q=g[k+3],r=g[k+4],s=g[k+5],t=g[k+6],u=g[k+7],v=g[k+8],x=g[k+9],y=g[k+10],z=g[k+11],A=g[k+12],B=g[k+13],C=g[k+14],D=g[k+15],c=b[0],d=b[1],e=b[2],f=b[3],c=p(c,d,e,f,h,7,a[0]),f=p(f,c,d,e,w,12,a[1]),e=p(e,f,c,d,j,17,a[2]),d=p(d,e,f,c,q,22,a[3]),c=p(c,d,e,f,r,7,a[4]),f=p(f,c,d,e,s,12,a[5]),e=p(e,f,c,d,t,17,a[6]),d=p(d,e,f,c,u,22,a[7]),\nc=p(c,d,e,f,v,7,a[8]),f=p(f,c,d,e,x,12,a[9]),e=p(e,f,c,d,y,17,a[10]),d=p(d,e,f,c,z,22,a[11]),c=p(c,d,e,f,A,7,a[12]),f=p(f,c,d,e,B,12,a[13]),e=p(e,f,c,d,C,17,a[14]),d=p(d,e,f,c,D,22,a[15]),c=m(c,d,e,f,w,5,a[16]),f=m(f,c,d,e,t,9,a[17]),e=m(e,f,c,d,z,14,a[18]),d=m(d,e,f,c,h,20,a[19]),c=m(c,d,e,f,s,5,a[20]),f=m(f,c,d,e,y,9,a[21]),e=m(e,f,c,d,D,14,a[22]),d=m(d,e,f,c,r,20,a[23]),c=m(c,d,e,f,x,5,a[24]),f=m(f,c,d,e,C,9,a[25]),e=m(e,f,c,d,q,14,a[26]),d=m(d,e,f,c,v,20,a[27]),c=m(c,d,e,f,B,5,a[28]),f=m(f,c,\nd,e,j,9,a[29]),e=m(e,f,c,d,u,14,a[30]),d=m(d,e,f,c,A,20,a[31]),c=l(c,d,e,f,s,4,a[32]),f=l(f,c,d,e,v,11,a[33]),e=l(e,f,c,d,z,16,a[34]),d=l(d,e,f,c,C,23,a[35]),c=l(c,d,e,f,w,4,a[36]),f=l(f,c,d,e,r,11,a[37]),e=l(e,f,c,d,u,16,a[38]),d=l(d,e,f,c,y,23,a[39]),c=l(c,d,e,f,B,4,a[40]),f=l(f,c,d,e,h,11,a[41]),e=l(e,f,c,d,q,16,a[42]),d=l(d,e,f,c,t,23,a[43]),c=l(c,d,e,f,x,4,a[44]),f=l(f,c,d,e,A,11,a[45]),e=l(e,f,c,d,D,16,a[46]),d=l(d,e,f,c,j,23,a[47]),c=n(c,d,e,f,h,6,a[48]),f=n(f,c,d,e,u,10,a[49]),e=n(e,f,c,d,\nC,15,a[50]),d=n(d,e,f,c,s,21,a[51]),c=n(c,d,e,f,A,6,a[52]),f=n(f,c,d,e,q,10,a[53]),e=n(e,f,c,d,y,15,a[54]),d=n(d,e,f,c,w,21,a[55]),c=n(c,d,e,f,v,6,a[56]),f=n(f,c,d,e,D,10,a[57]),e=n(e,f,c,d,t,15,a[58]),d=n(d,e,f,c,B,21,a[59]),c=n(c,d,e,f,r,6,a[60]),f=n(f,c,d,e,z,10,a[61]),e=n(e,f,c,d,j,15,a[62]),d=n(d,e,f,c,x,21,a[63]);b[0]=b[0]+c|0;b[1]=b[1]+d|0;b[2]=b[2]+e|0;b[3]=b[3]+f|0},_doFinalize:function(){var a=this._data,k=a.words,b=8*this._nDataBytes,h=8*a.sigBytes;k[h>>>5]|=128<<24-h%32;var l=s.floor(b/\n4294967296);k[(h+64>>>9<<4)+15]=(l<<8|l>>>24)&16711935|(l<<24|l>>>8)&4278255360;k[(h+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;a.sigBytes=4*(k.length+1);this._process();a=this._hash;k=a.words;for(b=0;4>b;b++)h=k[b],k[b]=(h<<8|h>>>24)&16711935|(h<<24|h>>>8)&4278255360;return a},clone:function(){var a=t.clone.call(this);a._hash=this._hash.clone();return a}});r.MD5=t._createHelper(q);r.HmacMD5=t._createHmacHelper(q)})(Math);\n"
  },
  {
    "path": "site/examples/tinymce/css/application.css",
    "content": ".tinymce {\n\tmargin-top: 40px;\n}\n\n.tjsbutton img {\n\twidth: 125px;\n}\n\n.subtitle {\n\tmargin-top: -10px;\n\tpadding-bottom: 15px;\n}\n"
  },
  {
    "path": "site/examples/tinymce/index.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block title %} Mozilla Labs : YouTube example {% endblock %}\n{% block configs %}\n  <script>\n    var TogetherJSConfig_autoStart = true;\n    var TogetherJSConfig_dontShowClicks = true;\n    var TogetherJSConfig_suppressJoinConfirmation = true;\n  </script>\n{% endblock %}\n\n{% block body %}\n  {% block styles %}\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/application.css\" />\n  {% endblock %}\n\n  <div class=\"container\"> <!-- container -->\n    <div class=\"body-content row\" id=\"youtube-example\">\n      <div class=\"col-md-6 col-md-offset-3\">\n        <div id=\"introduction\">\n          <h1>\n            Write Together \n            <a href=\"javascript:;\" class=\"pull-right tjsbutton\"><img src=\"https://togetherjs.com/images/start-togetherjs-blue.png\"></img></a>\n          </h1>\n          <h3 class='subtitle'>TogetherJS supports built-in synchronization for popular web editors like TinyMCE, Ace, CodeMirror, CKEditor.</h3>\n        </div>\n        <div class=\"tinymce\"></div>\n        <form role=\"form\">\n          <div class=\"row\">\n            <div class=\"col-xs-12 labelarea\">\n              <h4>Invite someone to start writing together.</h4>\n              <p class=\"youtube-embed-label\">Write a blog post with your friend, edit an essay for your student, or even draft a business proposal with your team in real-time. To invite someone, click the invite button on the right blue menu and send the url to the person you want to write together.</p>\n            </div>\n          </div>\n        </form>\n      </div> <!-- // youtube container -->\n    </div> <!-- //body-content -->\n\n  <script type=\"text/javascript\" src=\"/js/jquery-1.10.2.min.js\"></script>\n  <script src=\"http://tinymce.cachefly.net/4.0/tinymce.min.js\"></script>\n  <script type=\"text/javascript\" src=\"js/application.js\"></script>\n\n{% endblock %}\n"
  },
  {
    "path": "site/examples/tinymce/js/application.js",
    "content": "$(function () {\n  tinymce.init({ \n    selector: '.tinymce'\n  });\n\n  $('.tjsbutton').click(function () {\n    $('#togetherjs-dock').toggle();\n  });\n});\n"
  },
  {
    "path": "site/examples/tinymce/js/application.js~",
    "content": ""
  },
  {
    "path": "site/examples/todo/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world by @mdo and @fat.\n */\n\n/*! normalize.css v2.1.0 | MIT License | git.io/normalize */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n[hidden] {\n  display: none;\n}\n\nhtml {\n  font-family: sans-serif;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\nbody {\n  margin: 0;\n}\n\na:focus {\n  outline: thin dotted;\n}\n\na:active,\na:hover {\n  outline: 0;\n}\n\nh1 {\n  margin: 0.67em 0;\n  font-size: 2em;\n}\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\nb,\nstrong {\n  font-weight: bold;\n}\n\ndfn {\n  font-style: italic;\n}\n\nhr {\n  height: 0;\n  -moz-box-sizing: content-box;\n       box-sizing: content-box;\n}\n\nmark {\n  color: #000;\n  background: #ff0;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n\npre {\n  white-space: pre-wrap;\n}\n\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n\nsmall {\n  font-size: 80%;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  border: 0;\n}\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\nfigure {\n  margin: 0;\n}\n\nfieldset {\n  padding: 0.35em 0.625em 0.75em;\n  margin: 0 2px;\n  border: 1px solid #c0c0c0;\n}\n\nlegend {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: 100%;\n}\n\nbutton,\ninput {\n  line-height: normal;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  padding: 0;\n  box-sizing: border-box;\n}\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}\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\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  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\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  @page  {\n    margin: 2cm .5cm;\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  .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* {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #333333;\n  background-color: #ffffff;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\na {\n  color: #428bca;\n  text-decoration: none;\n}\n\na:hover,\na:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\nimg {\n  vertical-align: middle;\n}\n\n.img-responsive {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n}\n\n.img-rounded {\n  border-radius: 6px;\n}\n\n.img-circle {\n  border-radius: 500px;\n}\n\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 16.099999999999998px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\n\nsmall {\n  font-size: 85%;\n}\n\ncite {\n  font-style: normal;\n}\n\n.text-muted {\n  color: #999999;\n}\n\n.text-primary {\n  color: #428bca;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\n.text-danger {\n  color: #b94a48;\n}\n\n.text-success {\n  color: #468847;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\n.text-left {\n  text-align: left;\n}\n\n.text-right {\n  text-align: right;\n}\n\n.text-center {\n  text-align: center;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 500;\n  line-height: 1.1;\n}\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 {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\n\nh4,\nh5,\nh6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\nh1,\n.h1 {\n  font-size: 38px;\n}\n\nh2,\n.h2 {\n  font-size: 32px;\n}\n\nh3,\n.h3 {\n  font-size: 24px;\n}\n\nh4,\n.h4 {\n  font-size: 18px;\n}\n\nh5,\n.h5 {\n  font-size: 14px;\n}\n\nh6,\n.h6 {\n  font-size: 12px;\n}\n\nh1 small,\n.h1 small {\n  font-size: 24px;\n}\n\nh2 small,\n.h2 small {\n  font-size: 18px;\n}\n\nh3 small,\n.h3 small,\nh4 small,\n.h4 small {\n  font-size: 14px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\n\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 1.428571429;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 0;\n}\n\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\n.dl-horizontal dd {\n  margin-left: 180px;\n}\n\n.dl-horizontal dd:before,\n.dl-horizontal dd:after {\n  display: table;\n  content: \" \";\n}\n\n.dl-horizontal dd:after {\n  clear: both;\n}\n\n.dl-horizontal dd:before,\n.dl-horizontal dd:after {\n  display: table;\n  content: \" \";\n}\n\n.dl-horizontal dd:after {\n  clear: both;\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\n\nblockquote p:last-child {\n  margin-bottom: 0;\n}\n\nblockquote small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\n\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.428571429;\n}\n\ncode,\npre {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n}\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}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.428571429;\n  color: #333333;\n  word-break: break-all;\n  word-wrap: break-word;\n  background-color: #f5f5f5;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n\npre.prettyprint {\n  margin-bottom: 20px;\n}\n\npre code {\n  padding: 0;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\n.container {\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .row {\n    margin-right: -15px;\n    margin-left: -15px;\n  }\n}\n\n.row .row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.col-1,\n.col-2,\n.col-3,\n.col-4,\n.col-5,\n.col-6,\n.col-7,\n.col-8,\n.col-9,\n.col-10,\n.col-11,\n.col-12,\n.col-sm-1,\n.col-sm-2,\n.col-sm-3,\n.col-sm-4,\n.col-sm-5,\n.col-sm-6,\n.col-sm-7,\n.col-sm-8,\n.col-sm-9,\n.col-sm-10,\n.col-sm-11,\n.col-sm-12,\n.col-lg-1,\n.col-lg-2,\n.col-lg-3,\n.col-lg-4,\n.col-lg-5,\n.col-lg-6,\n.col-lg-7,\n.col-lg-8,\n.col-lg-9,\n.col-lg-10,\n.col-lg-11,\n.col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col-1,\n.col-2,\n.col-3,\n.col-4,\n.col-5,\n.col-6,\n.col-7,\n.col-8,\n.col-9,\n.col-10,\n.col-11,\n.col-12 {\n  float: left;\n}\n\n.col-1 {\n  width: 8.333333333333332%;\n}\n\n.col-2 {\n  width: 16.666666666666664%;\n}\n\n.col-3 {\n  width: 25%;\n}\n\n.col-4 {\n  width: 33.33333333333333%;\n}\n\n.col-5 {\n  width: 41.66666666666667%;\n}\n\n.col-6 {\n  width: 50%;\n}\n\n.col-7 {\n  width: 58.333333333333336%;\n}\n\n.col-8 {\n  width: 66.66666666666666%;\n}\n\n.col-9 {\n  width: 75%;\n}\n\n.col-10 {\n  width: 83.33333333333334%;\n}\n\n.col-11 {\n  width: 91.66666666666666%;\n}\n\n.col-12 {\n  width: 100%;\n}\n\n@media (min-width: 768px) {\n  .container {\n    max-width: 728px;\n  }\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11,\n  .col-sm-12 {\n    float: left;\n  }\n  .col-sm-1 {\n    width: 8.333333333333332%;\n  }\n  .col-sm-2 {\n    width: 16.666666666666664%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-4 {\n    width: 33.33333333333333%;\n  }\n  .col-sm-5 {\n    width: 41.66666666666667%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-7 {\n    width: 58.333333333333336%;\n  }\n  .col-sm-8 {\n    width: 66.66666666666666%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-10 {\n    width: 83.33333333333334%;\n  }\n  .col-sm-11 {\n    width: 91.66666666666666%;\n  }\n  .col-sm-12 {\n    width: 100%;\n  }\n  .col-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-push-3 {\n    left: 25%;\n  }\n  .col-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-push-6 {\n    left: 50%;\n  }\n  .col-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-push-9 {\n    left: 75%;\n  }\n  .col-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-pull-3 {\n    right: 25%;\n  }\n  .col-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-pull-6 {\n    right: 50%;\n  }\n  .col-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-pull-9 {\n    right: 75%;\n  }\n  .col-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-pull-11 {\n    right: 91.66666666666666%;\n  }\n}\n\n@media (min-width: 992px) {\n  .container {\n    max-width: 940px;\n  }\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11,\n  .col-lg-12 {\n    float: left;\n  }\n  .col-lg-1 {\n    width: 8.333333333333332%;\n  }\n  .col-lg-2 {\n    width: 16.666666666666664%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-4 {\n    width: 33.33333333333333%;\n  }\n  .col-lg-5 {\n    width: 41.66666666666667%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-7 {\n    width: 58.333333333333336%;\n  }\n  .col-lg-8 {\n    width: 66.66666666666666%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-10 {\n    width: 83.33333333333334%;\n  }\n  .col-lg-11 {\n    width: 91.66666666666666%;\n  }\n  .col-lg-12 {\n    width: 100%;\n  }\n  .col-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-offset-3 {\n    margin-left: 25%;\n  }\n  .col-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-offset-6 {\n    margin-left: 50%;\n  }\n  .col-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-offset-9 {\n    margin-left: 75%;\n  }\n  .col-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container {\n    max-width: 1170px;\n  }\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n}\n\nth {\n  text-align: left;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\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.428571429;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table thead > tr > th {\n  vertical-align: bottom;\n}\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\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\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\n.table-bordered {\n  border: 1px solid #dddddd;\n}\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 #dddddd;\n}\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\n.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n  background-color: #f5f5f5;\n}\n\ntable col[class^=\"col-\"] {\n  display: table-column;\n  float: none;\n}\n\ntable td[class^=\"col-\"],\ntable th[class^=\"col-\"] {\n  display: table-cell;\n  float: none;\n}\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\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  border-color: #d6e9c6;\n}\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  border-color: #eed3d7;\n}\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  border-color: #fbeed5;\n}\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  background-color: #d0e9c6;\n  border-color: #c9e2b3;\n}\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  background-color: #ebcccc;\n  border-color: #e6c1c7;\n}\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  background-color: #faf2cc;\n  border-color: #f8e5be;\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\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: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n\n  line-height: normal;\n}\n\ninput[type=\"file\"] {\n  display: block;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect optgroup {\n  font-family: inherit;\n  font-size: inherit;\n  font-style: inherit;\n}\n\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\n\n.form-control:-moz-placeholder {\n  color: #999999;\n}\n\n.form-control::-moz-placeholder {\n  color: #999999;\n}\n\n.form-control:-ms-input-placeholder {\n  color: #999999;\n}\n\n.form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: 38px;\n  padding: 8px 12px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n          transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n\n.form-control:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\n\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ntextarea.form-control {\n  height: auto;\n}\n\n.form-group {\n  margin-bottom: 15px;\n}\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  vertical-align: middle;\n}\n\n.radio label,\n.checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\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\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\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\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\n\n.input-large {\n  height: 56px;\n  padding: 14px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.input-small {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n\nselect.input-large {\n  height: 56px;\n  line-height: 56px;\n}\n\nselect.input-small {\n  height: 30px;\n  line-height: 30px;\n}\n\ntextarea.input-large,\ntextarea.input-small {\n  height: auto;\n}\n\n.has-warning .help-block,\n.has-warning .control-label {\n  color: #c09853;\n}\n\n.has-warning .form-control {\n  padding-right: 32px;\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-warning .form-control:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.has-warning .input-group-addon {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.has-error .help-block,\n.has-error .control-label {\n  color: #b94a48;\n}\n\n.has-error .form-control {\n  padding-right: 32px;\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-error .form-control:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.has-error .input-group-addon {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.has-success .help-block,\n.has-success .control-label {\n  color: #468847;\n}\n\n.has-success .form-control {\n  padding-right: 32px;\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-success .form-control:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.has-success .input-group-addon {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n\n.btn {\n  display: inline-block;\n  padding: 8px 12px;\n  margin-bottom: 0;\n  font-size: 14px;\n  font-weight: 500;\n  line-height: 1.428571429;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  cursor: pointer;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n       -o-user-select: none;\n          user-select: none;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn:hover,\n.btn:focus {\n  color: #ffffff;\n  text-decoration: none;\n}\n\n.btn:active,\n.btn.active {\n  outline: 0;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  pointer-events: none;\n  cursor: default;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-default {\n  color: #ffffff;\n  background-color: #474949;\n  border-color: #474949;\n}\n\n.btn-default:hover,\n.btn-default:focus,\n.btn-default:active,\n.btn-default.active {\n  background-color: #3a3c3c;\n  border-color: #2e2f2f;\n}\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: #474949;\n  border-color: #474949;\n}\n\n.btn-primary {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #357ebd;\n  border-color: #3071a9;\n}\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: #428bca;\n}\n\n.btn-warning {\n  color: #ffffff;\n  background-color: #f0ad4e;\n  border-color: #f0ad4e;\n}\n\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #eea236;\n  border-color: #ec971f;\n}\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: #f0ad4e;\n}\n\n.btn-danger {\n  color: #ffffff;\n  background-color: #d9534f;\n  border-color: #d9534f;\n}\n\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #d43f3a;\n  border-color: #c9302c;\n}\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: #d9534f;\n}\n\n.btn-success {\n  color: #ffffff;\n  background-color: #5cb85c;\n  border-color: #5cb85c;\n}\n\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active {\n  background-color: #4cae4c;\n  border-color: #449d44;\n}\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: #5cb85c;\n}\n\n.btn-info {\n  color: #ffffff;\n  background-color: #5bc0de;\n  border-color: #5bc0de;\n}\n\n.btn-info:hover,\n.btn-info:focus,\n.btn-info:active,\n.btn-info.active {\n  background-color: #46b8da;\n  border-color: #31b0d5;\n}\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: #5bc0de;\n}\n\n.btn-link {\n  font-weight: normal;\n  color: #428bca;\n  cursor: pointer;\n  border-radius: 0;\n}\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\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n\n.btn-link:hover,\n.btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn-large {\n  padding: 14px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.btn-small,\n.btn-mini {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-mini {\n  padding: 3px 5px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  display: none;\n}\n\n.collapse.in {\n  display: block;\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n.input-group {\n  display: table;\n  border-collapse: separate;\n}\n\n.input-group.col {\n  float: none;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.input-group .form-control {\n  width: 100%;\n  margin-bottom: 0;\n}\n\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n}\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\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n\n.input-group-addon {\n  padding: 8px 12px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1.428571429;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\n.input-group-addon.input-small {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n\n.input-group-addon.input-large {\n  padding: 14px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\n}\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 > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group-addon:first-child {\n  border-right: 0;\n}\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 > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n.input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n\n.input-group-btn > .btn {\n  position: relative;\n}\n\n.input-group-btn > .btn + .btn {\n  margin-left: -4px;\n}\n\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:active {\n  z-index: 2;\n}\n\n.form-inline .form-control,\n.form-inline .radio,\n.form-inline .checkbox {\n  display: inline-block;\n}\n\n.form-inline .radio,\n.form-inline .checkbox {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.form-horizontal .control-label {\n  padding-top: 9px;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .form-horizontal .form-group {\n    margin-right: -15px;\n    margin-left: -15px;\n  }\n}\n\n.form-horizontal .form-group .row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\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 #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\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  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 4px;\n  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n          box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n  background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 1.428571429;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #357ebd;\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);\n}\n\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #357ebd;\n  background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));\n  background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);\n  background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);\n  background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);\n  background-repeat: repeat-x;\n  outline: 0;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);\n}\n\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #999999;\n}\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\n.open > .dropdown-menu {\n  display: block;\n}\n\n.open > a {\n  outline: 0;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.428571429;\n  color: #999999;\n}\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\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n.list-group {\n  padding-left: 0;\n  margin-bottom: 20px;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 30px 10px 15px;\n  margin-bottom: -1px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n}\n\n.list-group-item:first-child {\n  border-top-right-radius: 4px;\n  border-top-left-radius: 4px;\n}\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\n.list-group-item > .badge {\n  float: right;\n  margin-right: -15px;\n}\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n\na.list-group-item .list-group-item-heading {\n  color: #333333;\n}\n\na.list-group-item .list-group-item-text {\n  color: #555555;\n}\n\na.list-group-item:hover,\na.list-group-item:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\na.list-group-item.active {\n  z-index: 2;\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\na.list-group-item.active .list-group-item-heading {\n  color: inherit;\n}\n\na.list-group-item.active .list-group-item-text {\n  color: #e1edf7;\n}\n\n.panel {\n  padding: 15px;\n  margin-bottom: 20px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.panel-heading {\n  padding: 10px 15px;\n  margin: -15px -15px 15px;\n  background-color: #f5f5f5;\n  border-bottom: 1px solid #dddddd;\n  border-top-right-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 17.5px;\n  font-weight: 500;\n}\n\n.panel-footer {\n  padding: 10px 15px;\n  margin: 15px -15px -15px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dddddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n\n.panel-primary {\n  border-color: #428bca;\n}\n\n.panel-primary .panel-heading {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.panel-success {\n  border-color: #d6e9c6;\n}\n\n.panel-success .panel-heading {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.panel-warning {\n  border-color: #fbeed5;\n}\n\n.panel-warning .panel-heading {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #fbeed5;\n}\n\n.panel-danger {\n  border-color: #eed3d7;\n}\n\n.panel-danger .panel-heading {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.panel-info {\n  border-color: #bce8f1;\n}\n\n.panel-info .panel-heading {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.list-group-flush {\n  margin: 15px -15px -15px;\n}\n\n.list-group-flush .list-group-item {\n  border-width: 1px 0;\n}\n\n.list-group-flush .list-group-item:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.list-group-flush .list-group-item:last-child {\n  border-bottom: 0;\n}\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, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-large {\n  padding: 24px;\n  border-radius: 6px;\n}\n\n.well-small {\n  padding: 9px;\n  border-radius: 3px;\n}\n\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover,\n.close:focus {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.nav {\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav > li {\n  position: relative;\n  display: block;\n}\n\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li.disabled > a {\n  color: #999999;\n}\n\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n}\n\n.nav.open > a,\n.nav.open > a:hover,\n.nav.open > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.nav.open > a .caret,\n.nav.open > a:hover .caret,\n.nav.open > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.nav > .pull-right {\n  float: right;\n}\n\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.428571429;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee;\n}\n\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-bottom-color: transparent;\n}\n\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-justified > li {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.nav-tabs.nav-justified > li > a {\n  text-align: center;\n}\n\n.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs.nav-justified > .active > a {\n  border-bottom-color: #ffffff;\n}\n\n.nav-pills > li {\n  float: left;\n}\n\n.nav-pills > li > a {\n  border-radius: 5px;\n}\n\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n\n.nav-justified {\n  width: 100%;\n}\n\n.nav-justified > li {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.nav-justified > li > a {\n  text-align: center;\n}\n\n.nav-tabs-justified {\n  border-bottom: 0;\n}\n\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs-justified > .active > a {\n  border-bottom-color: #ffffff;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  content: \" \";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  content: \" \";\n}\n\n.tabbable:after {\n  clear: both;\n}\n\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n\n.nav .caret {\n  border-top-color: #428bca;\n  border-bottom-color: #428bca;\n}\n\n.nav a:hover .caret {\n  border-top-color: #2a6496;\n  border-bottom-color: #2a6496;\n}\n\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar {\n  position: relative;\n  min-height: 50px;\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-bottom: 20px;\n  background-color: #eeeeee;\n  border-radius: 4px;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n.navbar-nav {\n  margin-top: 10px;\n  margin-bottom: 15px;\n}\n\n.navbar-nav > li > a {\n  padding-top: 15px;\n  padding-bottom: 15px;\n  line-height: 20px;\n  color: #777777;\n  border-radius: 4px;\n}\n\n.navbar-nav > li > a:hover,\n.navbar-nav > li > a:focus {\n  color: #333333;\n  background-color: transparent;\n}\n\n.navbar-nav > .active > a,\n.navbar-nav > .active > a:hover,\n.navbar-nav > .active > a:focus {\n  color: #555555;\n  background-color: #d5d5d5;\n}\n\n.navbar-nav > .disabled > a,\n.navbar-nav > .disabled > a:hover,\n.navbar-nav > .disabled > a:focus {\n  color: #cccccc;\n  background-color: transparent;\n}\n\n.navbar-nav.pull-right {\n  width: 100%;\n}\n\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  border-radius: 0;\n}\n\n.navbar-fixed-top {\n  top: 0;\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n}\n\n.navbar-brand {\n  display: block;\n  max-width: 200px;\n  padding: 15px 15px;\n  margin-right: auto;\n  margin-left: auto;\n  font-size: 18px;\n  font-weight: 500;\n  line-height: 20px;\n  color: #777777;\n  text-align: center;\n}\n\n.navbar-brand:hover,\n.navbar-brand:focus {\n  color: #5e5e5e;\n  text-decoration: none;\n  background-color: transparent;\n}\n\n.navbar-toggle {\n  position: absolute;\n  top: 9px;\n  right: 10px;\n  width: 48px;\n  height: 32px;\n  padding: 8px 12px;\n  background-color: transparent;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n}\n\n.navbar-toggle:hover,\n.navbar-toggle:focus {\n  background-color: #dddddd;\n}\n\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  background-color: #cccccc;\n  border-radius: 1px;\n}\n\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n\n.navbar-form {\n  margin-top: 6px;\n  margin-bottom: 6px;\n}\n\n.navbar-form .form-control,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  display: inline-block;\n}\n\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.navbar-nav > .dropdown > a:hover .caret,\n.navbar-nav > .dropdown > a:focus .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n\n.navbar-nav > .open > a,\n.navbar-nav > .open > a:hover,\n.navbar-nav > .open > a:focus {\n  color: #555555;\n  background-color: #d5d5d5;\n}\n\n.navbar-nav > .open > a .caret,\n.navbar-nav > .open > a:hover .caret,\n.navbar-nav > .open > a:focus .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar-nav > .dropdown > a .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar-inverse {\n  background-color: #222222;\n}\n\n.navbar-inverse .navbar-brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\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: #ffffff;\n  background-color: #080808;\n}\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: #444444;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-toggle {\n  border-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #ffffff;\n}\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: #ffffff;\n  background-color: #080808;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .navbar-nav > .open > a .caret,\n.navbar-inverse .navbar-nav > .open > a:hover .caret,\n.navbar-inverse .navbar-nav > .open > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n@media screen and (min-width: 768px) {\n  .navbar-brand {\n    float: left;\n    margin-right: 5px;\n    margin-left: -15px;\n  }\n  .navbar-nav {\n    float: left;\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n  .navbar-nav > li {\n    float: left;\n  }\n  .navbar-nav > li > a {\n    border-radius: 0;\n  }\n  .navbar-nav.pull-right {\n    float: right;\n    width: auto;\n  }\n  .navbar-toggle {\n    position: relative;\n    top: auto;\n    left: auto;\n    display: none;\n  }\n  .nav-collapse.collapse {\n    display: block !important;\n    height: auto !important;\n    overflow: visible !important;\n  }\n}\n\n.navbar-btn {\n  margin-top: 6px;\n}\n\n.navbar-text {\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n\n.navbar-link {\n  color: #777777;\n}\n\n.navbar-link:hover {\n  color: #333333;\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.btn .caret {\n  border-top-color: #ffffff;\n}\n\n.dropup .btn .caret {\n  border-bottom-color: #ffffff;\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\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  z-index: 2;\n}\n\n.btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar .btn-group {\n  float: left;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group,\n.btn-toolbar > .btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n}\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\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group > .btn-group {\n  float: left;\n}\n\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\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\n.btn-group > .btn-group:last-child > .btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  padding-right: 8px;\n  padding-left: 8px;\n}\n\n.btn-group > .btn-large + .dropdown-toggle {\n  padding-right: 12px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn .caret {\n  margin-left: 0;\n}\n\n.btn-large .caret {\n  border-width: 5px;\n}\n\n.dropup .btn-large .caret {\n  border-bottom-width: 5px;\n}\n\n.btn-group-vertical > .btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n\n.btn-group-vertical > .btn + .btn {\n  margin-top: -1px;\n}\n\n.btn-group-vertical .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n\n.btn-group-vertical .btn:first-child {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical .btn:last-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n}\n\n.btn-group-justified .btn {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.btn-group[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n.btn-group[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\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\n.breadcrumb > li {\n  display: inline-block;\n}\n\n.breadcrumb > li + li:before {\n  padding: 0 5px;\n  color: #cccccc;\n  content: \"/\\00a0\";\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n\n.pagination > li {\n  display: inline;\n}\n\n.pagination > li > a,\n.pagination > li > span {\n  float: left;\n  padding: 4px 12px;\n  line-height: 1.428571429;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  border-left-width: 1px;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n}\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\n.pagination > li > a:hover,\n.pagination > li > a:focus,\n.pagination > .active > a,\n.pagination > .active > span {\n  background-color: #f5f5f5;\n}\n\n.pagination > .active > a,\n.pagination > .active > span {\n  color: #999999;\n  cursor: default;\n}\n\n.pagination > .disabled > span,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n}\n\n.pagination-large > li > a,\n.pagination-large > li > span {\n  padding: 14px 16px;\n  font-size: 18px;\n}\n\n.pagination-large > li:first-child > a,\n.pagination-large > li:first-child > span {\n  border-bottom-left-radius: 6px;\n  border-top-left-radius: 6px;\n}\n\n.pagination-large > li:last-child > a,\n.pagination-large > li:last-child > span {\n  border-top-right-radius: 6px;\n  border-bottom-right-radius: 6px;\n}\n\n.pagination-small > li > a,\n.pagination-small > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n\n.pagination-small > li:first-child > a,\n.pagination-small > li:first-child > span {\n  border-bottom-left-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.pagination-small > li:last-child > a,\n.pagination-small > li:last-child > span {\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n\n.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 15px;\n}\n\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n}\n\n.modal-open {\n  overflow: hidden;\n}\n\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n}\n\n.modal.fade .modal-dialog {\n  -webkit-transform: translate(0, -25%);\n      -ms-transform: translate(0, -25%);\n          transform: translate(0, -25%);\n  -webkit-transition: -webkit-transform 0.3s ease-out;\n     -moz-transition: -moz-transform 0.3s ease-out;\n       -o-transition: -o-transform 0.3s ease-out;\n          transition: transform 0.3s ease-out;\n}\n\n.modal.fade.in .modal-dialog {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n\n.modal-dialog {\n  z-index: 1050;\n  width: auto;\n  padding: 10px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.modal-content {\n  position: relative;\n  background-color: #ffffff;\n  border: 1px solid #999999;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n          box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n  background-clip: padding-box;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n\n.modal-backdrop.fade.in {\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.modal-header {\n  min-height: 16.428571429px;\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n}\n\n.modal-header .close {\n  margin-top: -2px;\n}\n\n.modal-title {\n  margin: 0;\n  line-height: 1.428571429;\n}\n\n.modal-body {\n  position: relative;\n  padding: 20px;\n}\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\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n@media screen and (min-width: 768px) {\n  .modal-dialog {\n    right: auto;\n    left: 50%;\n    width: 600px;\n    padding-top: 30px;\n    padding-bottom: 30px;\n  }\n  .modal-content {\n    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n  }\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 12px;\n  line-height: 1.4;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: rgba(0, 0, 0, 0.9);\n  border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-top-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-right .tooltip-arrow {\n  right: 5px;\n  bottom: 0;\n  border-top-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: rgba(0, 0, 0, 0.9);\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: rgba(0, 0, 0, 0.9);\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-bottom-color: rgba(0, 0, 0, 0.9);\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-bottom-color: rgba(0, 0, 0, 0.9);\n  border-width: 0 5px 5px;\n}\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: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  background-clip: padding-box;\n  -webkit-bg-clip: padding-box;\n     -moz-bg-clip: padding;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\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\n.popover-content {\n  padding: 9px 14px;\n}\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\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n  content: \" \";\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n  content: \" \";\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n  content: \" \";\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n  content: \" \";\n}\n\n.alert {\n  padding: 10px 35px 10px 15px;\n  margin-bottom: 20px;\n  color: #c09853;\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  border-radius: 4px;\n}\n\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n\n.alert hr {\n  border-top-color: #f8e5be;\n}\n\n.alert .alert-link {\n  font-weight: 500;\n  color: #a47e3c;\n}\n\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n\n.alert-success .alert-link {\n  color: #356635;\n}\n\n.alert-danger {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #eed3d7;\n}\n\n.alert-danger hr {\n  border-top-color: #e6c1c7;\n}\n\n.alert-danger .alert-link {\n  color: #953b39;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n\n.alert-info .alert-link {\n  color: #2d6987;\n}\n\n.alert-block {\n  padding-top: 15px;\n  padding-bottom: 15px;\n}\n\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n\n.alert-block p + p {\n  margin-top: 5px;\n}\n\n.thumbnail,\n.img-thumbnail {\n  padding: 4px;\n  line-height: 1.428571429;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\n.thumbnail {\n  display: block;\n}\n\n.thumbnail > img,\n.img-thumbnail {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n}\n\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: #428bca;\n}\n\n.thumbnail > img {\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #333333;\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media > .pull-left {\n  margin-right: 10px;\n}\n\n.media > .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n\n.label {\n  display: inline;\n  padding: .25em .6em;\n  font-size: 75%;\n  font-weight: 500;\n  line-height: 1;\n  color: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  background-color: #999999;\n  border-radius: .25em;\n}\n\n.label[href]:hover,\n.label[href]:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n  background-color: #808080;\n}\n\n.label-danger {\n  background-color: #d9534f;\n}\n\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\n}\n\n.label-success {\n  background-color: #5cb85c;\n}\n\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n\n.label-warning {\n  background-color: #f0ad4e;\n}\n\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n\n.label-info {\n  background-color: #5bc0de;\n}\n\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\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: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  background-color: #999999;\n  border-radius: 10px;\n}\n\n.badge:empty {\n  display: none;\n}\n\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #ffffff;\n}\n\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\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\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\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\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, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  color: #ffffff;\n  text-align: center;\n  background-color: #428bca;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress-striped .progress-bar {\n  background-color: #428bca;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-size: 40px 40px;\n}\n\n.progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n\n.progress-striped .progress-bar-danger {\n  background-color: #d9534f;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-success {\n  background-color: #5cb85c;\n}\n\n.progress-striped .progress-bar-success {\n  background-color: #5cb85c;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n\n.progress-striped .progress-bar-warning {\n  background-color: #f0ad4e;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n\n.progress-striped .progress-bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.accordion {\n  margin-bottom: 20px;\n}\n\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  border-radius: 4px;\n}\n\n.accordion-heading {\n  border-bottom: 0;\n}\n\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n  cursor: pointer;\n}\n\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\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: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.left {\n  background-color: rgba(0, 0, 0, 0.0001);\n  background-color: transparent;\n  background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%));\n  background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n\n.carousel-control.right {\n  right: 0;\n  left: auto;\n  background-color: rgba(0, 0, 0, 0.5);\n  background-color: transparent;\n  background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%));\n  background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-control .glyphicon,\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  z-index: 5;\n  display: inline-block;\n  width: 20px;\n  height: 20px;\n  margin-top: -10px;\n  margin-left: -10px;\n  font-family: serif;\n}\n\n.carousel-control .icon-prev:before {\n  content: '\\2039';\n}\n\n.carousel-control .icon-next:before {\n  content: '\\203a';\n}\n\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 120px;\n  padding-left: 0;\n  margin-left: -60px;\n  text-align: center;\n  list-style: none;\n}\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  border: 1px solid #ffffff;\n  border-radius: 10px;\n}\n\n.carousel-indicators .active {\n  width: 12px;\n  height: 12px;\n  margin: 0;\n  background-color: #ffffff;\n}\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: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n\n.carousel-caption .btn {\n  text-shadow: none;\n}\n\n@media screen and (min-width: 768px) {\n  .carousel-control .glyphicon,\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\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 2.1428571435;\n  color: inherit;\n  background-color: #eeeeee;\n}\n\n.jumbotron h1 {\n  line-height: 1;\n  color: inherit;\n}\n\n.jumbotron p {\n  line-height: 1.4;\n}\n\n@media screen and (min-width: 768px) {\n  .jumbotron {\n    padding: 50px 60px;\n    border-radius: 6px;\n  }\n  .jumbotron h1 {\n    font-size: 63px;\n  }\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  content: \" \";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.pull-right {\n  float: right;\n}\n\n.pull-left {\n  float: left;\n}\n\n.hide {\n  display: none !important;\n}\n\n.show {\n  display: block !important;\n}\n\n.invisible {\n  visibility: hidden;\n}\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\n.affix {\n  position: fixed;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\n@media screen and (max-width: 400px) {\n  @-ms-viewport {\n    width: 320px;\n  }\n}\n\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n.visible-sm {\n  display: block !important;\n}\n\ntr.visible-sm {\n  display: table-row !important;\n}\n\nth.visible-sm,\ntd.visible-sm {\n  display: table-cell !important;\n}\n\n.visible-md {\n  display: none !important;\n}\n\ntr.visible-md {\n  display: none !important;\n}\n\nth.visible-md,\ntd.visible-md {\n  display: none !important;\n}\n\n.visible-lg {\n  display: none !important;\n}\n\ntr.visible-lg {\n  display: none !important;\n}\n\nth.visible-lg,\ntd.visible-lg {\n  display: none !important;\n}\n\n.hidden-sm {\n  display: none !important;\n}\n\ntr.hidden-sm {\n  display: none !important;\n}\n\nth.hidden-sm,\ntd.hidden-sm {\n  display: none !important;\n}\n\n.hidden-md {\n  display: block !important;\n}\n\ntr.hidden-md {\n  display: table-row !important;\n}\n\nth.hidden-md,\ntd.hidden-md {\n  display: table-cell !important;\n}\n\n.hidden-lg {\n  display: block !important;\n}\n\ntr.hidden-lg {\n  display: table-row !important;\n}\n\nth.hidden-lg,\ntd.hidden-lg {\n  display: table-cell !important;\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm {\n    display: none !important;\n  }\n  tr.visible-sm {\n    display: none !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: none !important;\n  }\n  .visible-md {\n    display: block !important;\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  .visible-lg {\n    display: none !important;\n  }\n  tr.visible-lg {\n    display: none !important;\n  }\n  th.visible-lg,\n  td.visible-lg {\n    display: none !important;\n  }\n  .hidden-sm {\n    display: block !important;\n  }\n  tr.hidden-sm {\n    display: table-row !important;\n  }\n  th.hidden-sm,\n  td.hidden-sm {\n    display: table-cell !important;\n  }\n  .hidden-md {\n    display: none !important;\n  }\n  tr.hidden-md {\n    display: none !important;\n  }\n  th.hidden-md,\n  td.hidden-md {\n    display: none !important;\n  }\n  .hidden-lg {\n    display: block !important;\n  }\n  tr.hidden-lg {\n    display: table-row !important;\n  }\n  th.hidden-lg,\n  td.hidden-lg {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) {\n  .visible-sm {\n    display: none !important;\n  }\n  tr.visible-sm {\n    display: none !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: none !important;\n  }\n  .visible-md {\n    display: none !important;\n  }\n  tr.visible-md {\n    display: none !important;\n  }\n  th.visible-md,\n  td.visible-md {\n    display: none !important;\n  }\n  .visible-lg {\n    display: block !important;\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  .hidden-sm {\n    display: block !important;\n  }\n  tr.hidden-sm {\n    display: table-row !important;\n  }\n  th.hidden-sm,\n  td.hidden-sm {\n    display: table-cell !important;\n  }\n  .hidden-md {\n    display: block !important;\n  }\n  tr.hidden-md {\n    display: table-row !important;\n  }\n  th.hidden-md,\n  td.hidden-md {\n    display: table-cell !important;\n  }\n  .hidden-lg {\n    display: none !important;\n  }\n  tr.hidden-lg {\n    display: none !important;\n  }\n  th.hidden-lg,\n  td.hidden-lg {\n    display: none !important;\n  }\n}\n\n.visible-print {\n  display: none !important;\n}\n\ntr.visible-print {\n  display: none !important;\n}\n\nth.visible-print,\ntd.visible-print {\n  display: none !important;\n}\n\n@media print {\n  .visible-print {\n    display: block !important;\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  .hidden-print {\n    display: none !important;\n  }\n  tr.hidden-print {\n    display: none !important;\n  }\n  th.hidden-print,\n  td.hidden-print {\n    display: none !important;\n  }\n}"
  },
  {
    "path": "site/examples/todo/index.html",
    "content": "<!DOCTYPE html>\n\n<html>\n<head>\n  <title>Grocery To Do List</title>\n  <meta charset=\"UTF-8\">\n  <meta name=\"description\" content=\"\">\n  <meta name=\"author\" content=\"\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <!-- Bootstrap -->\n  <link href=\"css/bootstrap.min.css\" rel=\"stylesheet\" media=\"screen\">\n\n  <style type=\"text/css\" media=\"screen\">\n    .main{\n      padding: 80px 15px;\n    }\n\n    h1 {\n      color: #e74c3c;\n    }\n\n    .navbar {\n      background: #fa6374;\n    }\n\n    .navbar-inverse .navbar-brand {\n      color: #fff;\n    }\n\n    .form-control {\n      padding: 0 12px;\n    }\n\n    /*reset Twitter Bootstrap*/\n    @media screen {\n      * {\n        -webkit-box-sizing: content-box !important;\n        -moz-box-sizing: content-box !important;\n        box-sizing: content-box !important;\n      }\n    }\n\n    .container a img {\n      width: 135px;\n      height: 34px;\n    }\n\n  </style>\n\n</head>\n  <body>\n\n    <div class=\"navbar navbar-inverse navbar-fixed-top\">\n      <div class=\"container\">\n        <a class=\"navbar-brand pull-left\" href=\"#\">Grocery To Do List</a>\n        <a href=\"#\" class=\"navbar-btn pull-right\" onclick=\"TogetherJS(this); return false;\"><img src=\"/images/start-togetherjs-blue.png\"></a>\n      </div>\n    </div>\n\n\n    <div class=\"container\">\n\n      <div class=\"main\">\n\n        <div class=\"row\">\n          <div id=\"form\" class=\"navbar-form pull-left\">\n            <input id=\"description\" name=\"description\" type=\"text\" class=\"form-control\" style=\"width: 200px;\" placeholder=\"Add a grocery item\" />\n            <input id=\"add\" type=\"submit\" value=\"Add\" class=\"btn btn-primary\" />\n            <button id=\"clear\" type=\"button\" class=\"btn btn-danger\">Clear All</button>\n          </div>\n        </div>\n\n        <div class=\"row\">\n          <div id=\"alert\"></div>\n          <h4>Our groceries:</h4>\n          <ul id=\"todos\" class=\"list-group\"></ul>\n        </div>\n\n      </div>\n\n    </div>\n\n    <!-- togetherjs -->\n    <script>\n      TogetherJSConfig_findRoom = {prefix: \"togetherjstodo\", max: 5};\n      TogetherJSConfig_autoStart = true;\n      TogetherJSConfig_suppressJoinConfirmation = true;\n      TogetherJSConfig_storagePrefix = \"tjs_todo\";\n    </script>\n    <script src=\"/togetherjs.js\"></script>\n\n    <!-- JavaScript plugins (requires jQuery) -->\n    <script src=\"js/jquery-1.10.2.min.js\"></script>\n    <!-- Include all compiled plugins (below), or include individual files as needed -->\n    <script src=\"js/bootstrap.min.js\"></script>\n\n    <script type=\"text/javascript\" charset=\"utf-8\" src=\"js/app.js\"></script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "site/examples/todo/js/app.js",
    "content": "$('#add').click( function() {\n  var Description = $('#description').val();\n  if (! $(\"#description\").val()) {\n    $('#alert').html(\"<strong>Oops!</strong> Please enter an item above.\");\n    $('#alert').fadeIn().delay(1000).fadeOut();\n    return false;\n  }\n  var id = \"item-\" + Date.now();\n  $('#description').val(\"\").change();\n  addItem(Description, id);\n  save();\n  if (TogetherJS.running) {\n    TogetherJS.send({type: \"new-item\", description: Description, id: id});\n  }\n  return false;\n});\n\n$(\"#description\").on(\"keyup\", function (event) {\n  if (event.which == 13) {\n    $(\"#add\").click();\n  }\n});\n\nfunction addItem(description, id) {\n  var existing = $(\"#\" + id);\n  if (existing.length) {\n    // Already exists...\n    existing.closest(\"li\").find(\".description\").text(description);\n    return;\n  }\n  var li = $('<li class=\"list-group-item\"><input type=\"checkbox\"> <span class=\"description\"></span></li>');\n  li.find(\"input\").attr(\"id\", id);\n  li.find(\".description\").text(description);\n  $(\"#todos\").append(li);\n}\n\nTogetherJS.hub.on(\"new-item\", function (msg) {\n  addItem(msg.description, msg.id);\n  save();\n});\n\nTogetherJS.hub.on(\"init-items\", function (msg) {\n  $(\"#todos\").empty();\n  msg.items.forEach(function (item) {\n    addItem(item.description, item.id);\n  });\n  save();\n});\n\nTogetherJS.hub.on(\"togetherjs.hello togetherjs.hello-back\", function () {\n  TogetherJS.send({type: \"init-items\", items: getItems()});\n});\n\nfunction getItems() {\n  var result = [];\n  $(\"#todos li.list-group-item\").each(function () {\n    var $this = $(this);\n    result.push({\n      id: $this.find(\"input\").attr(\"id\"),\n      description: $this.find(\".description\").text()\n    });\n  });\n  return result;\n}\n\nif (localStorage.getItem('todos')) {\n  JSON.parse(localStorage.getItem('todos')).forEach(function (item) {\n    addItem(item.description, item.id);\n  });\n}\n\nfunction save() {\n  localStorage.setItem('todos', JSON.stringify(getItems()));\n}\n\n$('#clear').click(function() {\n  $(\"#todos\").empty();\n  save();\n  if (TogetherJS.running) {\n    TogetherJS.send({type: \"init-items\", items: []});\n  }\n  return false;\n});\n"
  },
  {
    "path": "site/examples/todo/js/bootstrap.js",
    "content": "/**\n* bootstrap.js v3.0.0 by @fat and @mdo\n* Copyright 2013 Twitter Inc.\n* http://www.apache.org/licenses/LICENSE-2.0\n*/\nif (!jQuery) { throw new Error(\"Bootstrap requires jQuery\") }\n\n/* ========================================================================\n * Bootstrap: transition.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#transitions\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)\n  // ============================================================\n\n  function transitionEnd() {\n    var el = document.createElement('bootstrap')\n\n    var transEndEventNames = {\n      'WebkitTransition' : 'webkitTransitionEnd'\n    , 'MozTransition'    : 'transitionend'\n    , 'OTransition'      : 'oTransitionEnd otransitionend'\n    , 'transition'       : 'transitionend'\n    }\n\n    for (var name in transEndEventNames) {\n      if (el.style[name] !== undefined) {\n        return { end: transEndEventNames[name] }\n      }\n    }\n  }\n\n  // http://blog.alexmaccaw.com/css-transitions\n  $.fn.emulateTransitionEnd = function (duration) {\n    var called = false, $el    = this\n    $(this).one($.support.transition.end, function () { called = true })\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\n    setTimeout(callback, duration)\n    return this\n  }\n\n  $(function () {\n    $.support.transition = transitionEnd()\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: alert.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#alerts\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // ALERT CLASS DEFINITION\n  // ======================\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n  var Alert   = function (el) {\n    $(el).on('click', dismiss, this.close)\n  }\n\n  Alert.prototype.close = function (e) {\n    var $this    = $(this)\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = $(selector)\n\n    if (e) e.preventDefault()\n\n    if (!$parent.length) {\n      $parent = $this.hasClass('alert') ? $this : $this.parent()\n    }\n\n    $parent.trigger(e = $.Event('close.bs.alert'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      $parent.trigger('closed.bs.alert').remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent\n        .one($.support.transition.end, removeElement)\n        .emulateTransitionEnd(150) :\n      removeElement()\n  }\n\n\n  // ALERT PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.alert\n\n  $.fn.alert = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.alert')\n\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.alert.Constructor = Alert\n\n\n  // ALERT NO CONFLICT\n  // =================\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n  // ALERT DATA-API\n  // ==============\n\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: button.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#buttons\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // BUTTON PUBLIC CLASS DEFINITION\n  // ==============================\n\n  var Button = function (element, options) {\n    this.$element = $(element)\n    this.options  = $.extend({}, Button.DEFAULTS, options)\n  }\n\n  Button.DEFAULTS = {\n    loadingText: 'loading...'\n  }\n\n  Button.prototype.setState = function (state) {\n    var d    = 'disabled'\n    var $el  = this.$element\n    var val  = $el.is('input') ? 'val' : 'html'\n    var data = $el.data()\n\n    state = state + 'Text'\n\n    if (!data.resetText) $el.data('resetText', $el[val]())\n\n    $el[val](data[state] || this.options[state])\n\n    // push to event loop to allow forms to submit\n    setTimeout(function () {\n      state == 'loadingText' ?\n        $el.addClass(d).attr(d, d) :\n        $el.removeClass(d).removeAttr(d);\n    }, 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input').prop('checked', !this.$element.hasClass('active'))\n      if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')\n    }\n\n    this.$element.toggleClass('active')\n  }\n\n\n  // BUTTON PLUGIN DEFINITION\n  // ========================\n\n  var old = $.fn.button\n\n  $.fn.button = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('button')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  $.fn.button.Constructor = Button\n\n\n  // BUTTON NO CONFLICT\n  // ==================\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n  // BUTTON DATA-API\n  // ===============\n\n  $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {\n    var $btn = $(e.target)\n    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\n    $btn.button('toggle')\n    e.preventDefault()\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: carousel.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#carousel\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CAROUSEL CLASS DEFINITION\n  // =========================\n\n  var Carousel = function (element, options) {\n    this.$element    = $(element)\n    this.$indicators = this.$element.find('.carousel-indicators')\n    this.options     = options\n    this.paused      =\n    this.sliding     =\n    this.interval    =\n    this.$active     =\n    this.$items      = null\n\n    this.options.pause == 'hover' && this.$element\n      .on('mouseenter', $.proxy(this.pause, this))\n      .on('mouseleave', $.proxy(this.cycle, this))\n  }\n\n  Carousel.DEFAULTS = {\n    interval: 5000\n  , pause: 'hover'\n  }\n\n  Carousel.prototype.cycle =  function (e) {\n    e || (this.paused = false)\n\n    this.interval && clearInterval(this.interval)\n\n    this.options.interval\n      && !this.paused\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n\n    return this\n  }\n\n  Carousel.prototype.getActiveIndex = function () {\n    this.$active = this.$element.find('.item.active')\n    this.$items  = this.$active.parent().children()\n\n    return this.$items.index(this.$active)\n  }\n\n  Carousel.prototype.to = function (pos) {\n    var that        = this\n    var activeIndex = this.getActiveIndex()\n\n    if (pos > (this.$items.length - 1) || pos < 0) return\n\n    if (this.sliding)       return this.$element.one('slid', function () { that.to(pos) })\n    if (activeIndex == pos) return this.pause().cycle()\n\n    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))\n  }\n\n  Carousel.prototype.pause = function (e) {\n    e || (this.paused = true)\n\n    if (this.$element.find('.next, .prev').length && $.support.transition.end) {\n      this.$element.trigger($.support.transition.end)\n      this.cycle(true)\n    }\n\n    this.interval = clearInterval(this.interval)\n\n    return this\n  }\n\n  Carousel.prototype.next = function () {\n    if (this.sliding) return\n    return this.slide('next')\n  }\n\n  Carousel.prototype.prev = function () {\n    if (this.sliding) return\n    return this.slide('prev')\n  }\n\n  Carousel.prototype.slide = function (type, next) {\n    var $active   = this.$element.find('.item.active')\n    var $next     = next || $active[type]()\n    var isCycling = this.interval\n    var direction = type == 'next' ? 'left' : 'right'\n    var fallback  = type == 'next' ? 'first' : 'last'\n    var that      = this\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    $next = $next.length ? $next : this.$element.find('.item')[fallback]()\n\n    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })\n\n    if ($next.hasClass('active')) return\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      this.$element.one('slid', function () {\n        var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])\n        $nextIndicator && $nextIndicator.addClass('active')\n      })\n    }\n\n    if ($.support.transition && this.$element.hasClass('slide')) {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $next.addClass(type)\n      $next[0].offsetWidth // force reflow\n      $active.addClass(direction)\n      $next.addClass(direction)\n      $active\n        .one($.support.transition.end, function () {\n          $next.removeClass([type, direction].join(' ')).addClass('active')\n          $active.removeClass(['active', direction].join(' '))\n          that.sliding = false\n          setTimeout(function () { that.$element.trigger('slid') }, 0)\n        })\n        .emulateTransitionEnd(600)\n    } else {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger('slid')\n    }\n\n    isCycling && this.cycle()\n\n    return this\n  }\n\n\n  // CAROUSEL PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.carousel\n\n  $.fn.carousel = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.carousel')\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\n      var action  = typeof option == 'string' ? option : options.slide\n\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\n      if (typeof option == 'number') data.to(option)\n      else if (action) data[action]()\n      else if (options.interval) data.pause().cycle()\n    })\n  }\n\n  $.fn.carousel.Constructor = Carousel\n\n\n  // CAROUSEL NO CONFLICT\n  // ====================\n\n  $.fn.carousel.noConflict = function () {\n    $.fn.carousel = old\n    return this\n  }\n\n\n  // CAROUSEL DATA-API\n  // =================\n\n  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {\n    var $this   = $(this), href\n    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n    var options = $.extend({}, $target.data(), $this.data())\n    var slideIndex = $this.attr('data-slide-to')\n    if (slideIndex) options.interval = false\n\n    $target.carousel(options)\n\n    if (slideIndex = $this.attr('data-slide-to')) {\n      $target.data('bs.carousel').to(slideIndex)\n    }\n\n    e.preventDefault()\n  })\n\n  $(window).on('load', function () {\n    $('[data-ride=\"carousel\"]').each(function () {\n      var $carousel = $(this)\n      $carousel.carousel($carousel.data())\n    })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: collapse.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#collapse\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // COLLAPSE PUBLIC CLASS DEFINITION\n  // ================================\n\n  var Collapse = function (element, options) {\n    this.$element      = $(element)\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\n    this.transitioning = null\n\n    if (this.options.parent) this.$parent = $(this.options.parent)\n    if (this.options.toggle) this.toggle()\n  }\n\n  Collapse.DEFAULTS = {\n    toggle: true\n  }\n\n  Collapse.prototype.dimension = function () {\n    var hasWidth = this.$element.hasClass('width')\n    return hasWidth ? 'width' : 'height'\n  }\n\n  Collapse.prototype.show = function () {\n    if (this.transitioning || this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('show.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var actives   = this.$parent && this.$parent.find('> .accordion-group > .in')\n\n    if (actives && actives.length) {\n      var hasData = actives.data('bs.collapse')\n      if (hasData && hasData.transitioning) return\n      actives.collapse('hide')\n      hasData || actives.data('bs.collapse', null)\n    }\n\n    var dimension = this.dimension()\n\n    this.$element\n      .removeClass('collapse')\n      .addClass('collapsing')\n      [dimension](0)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.$element\n        .removeClass('collapsing')\n        .addClass('in')\n        [dimension]('auto')\n      this.transitioning = 0\n      this.$element.trigger('shown.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\n\n    this.$element\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n      [dimension](this.$element[0][scrollSize])\n  }\n\n  Collapse.prototype.hide = function () {\n    if (this.transitioning || !this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('hide.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var dimension = this.dimension()\n\n    this.$element\n      [dimension](this.$element[dimension]())\n      [0].offsetHeight\n\n    this.$element\n      .addClass('collapsing')\n      .removeClass('collapse')\n      .removeClass('in')\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.transitioning = 0\n      this.$element\n        .trigger('hidden.bs.collapse')\n        .removeClass('collapsing')\n        .addClass('collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    this.$element\n      [dimension](0)\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n  }\n\n  Collapse.prototype.toggle = function () {\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\n  }\n\n\n  // COLLAPSE PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.collapse\n\n  $.fn.collapse = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.collapse')\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.collapse.Constructor = Collapse\n\n\n  // COLLAPSE NO CONFLICT\n  // ====================\n\n  $.fn.collapse.noConflict = function () {\n    $.fn.collapse = old\n    return this\n  }\n\n\n  // COLLAPSE DATA-API\n  // =================\n\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {\n    var $this   = $(this), href\n    var target  = $this.attr('data-target')\n        || e.preventDefault()\n        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') //strip for ie7\n    var $target = $(target)\n    var data    = $target.data('bs.collapse')\n    var option  = data ? 'toggle' : $this.data()\n    var parent  = $this.attr('data-parent')\n    var $parent = parent && $(parent)\n\n    if (!data || !data.transitioning) {\n      if ($parent) $parent.find('[data-toggle=collapse][data-parent=' + parent + ']').not($this).addClass('collapsed')\n      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')\n    }\n\n    $target.collapse(option)\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: dropdown.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#dropdowns\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // DROPDOWN CLASS DEFINITION\n  // =========================\n\n  var backdrop = '.dropdown-backdrop'\n  var toggle   = '[data-toggle=dropdown]'\n  var Dropdown = function (element) {\n    var $el = $(element).on('click.bs.dropdown', this.toggle)\n  }\n\n  Dropdown.prototype.toggle = function (e) {\n    var $this = $(this)\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    clearMenus()\n\n    if (!isActive) {\n      if ('ontouchstart' in document.documentElement) {\n        // if mobile we we use a backdrop because click events don't delegate\n        $('<div class=\"dropdown-backdrop\"/>').insertAfter($(this)).on('click', clearMenus)\n      }\n\n      $parent.trigger(e = $.Event('show.bs.dropdown'))\n\n      if (e.isDefaultPrevented()) return\n\n      $parent\n        .toggleClass('open')\n        .trigger('shown.bs.dropdown')\n    }\n\n    $this.focus()\n\n    return false\n  }\n\n  Dropdown.prototype.keydown = function (e) {\n    if (!/(38|40|27)/.test(e.keyCode)) return\n\n    var $this = $(this)\n\n    e.preventDefault()\n    e.stopPropagation()\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    if (!isActive || (isActive && e.keyCode == 27)) {\n      if (e.which == 27) $parent.find(toggle).focus()\n      return $this.click()\n    }\n\n    var $items = $('[role=menu] li:not(.divider):visible a', $parent)\n\n    if (!$items.length) return\n\n    var index = $items.index($items.filter(':focus'))\n\n    if (e.keyCode == 38 && index > 0)                 index--                        // up\n    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down\n    if (!~index)                                      index=0\n\n    $items.eq(index).focus()\n  }\n\n  function clearMenus() {\n    $(backdrop).remove()\n    $(toggle).each(function (e) {\n      var $parent = getParent($(this))\n      if (!$parent.hasClass('open')) return\n      $parent.trigger(e = $.Event('hide.bs.dropdown'))\n      if (e.isDefaultPrevented()) return\n      $parent.removeClass('open').trigger('hidden.bs.dropdown')\n    })\n  }\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    var $parent = selector && $(selector)\n\n    return $parent && $parent.length ? $parent : $this.parent()\n  }\n\n\n  // DROPDOWN PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('dropdown')\n\n      if (!data) $this.data('dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.dropdown.Constructor = Dropdown\n\n\n  // DROPDOWN NO CONFLICT\n  // ====================\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\n  // ===================================\n\n  $(document)\n    .on('click.bs.dropdown.data-api', clearMenus)\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.bs.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\n    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: modal.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#modals\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // MODAL CLASS DEFINITION\n  // ======================\n\n  var Modal = function (element, options) {\n    this.options   = options\n    this.$element  = $(element).on('click.dismiss.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this))\n    this.$backdrop =\n    this.isShown   = null\n\n    if (this.options.remote) this.$element.find('.modal-body').load(this.options.remote)\n  }\n\n  Modal.DEFAULTS = {\n      backdrop: true\n    , keyboard: true\n    , show: true\n  }\n\n  Modal.prototype.toggle = function () {\n    return this[!this.isShown ? 'show' : 'hide']()\n  }\n\n  Modal.prototype.show = function () {\n    var that = this\n    var e    = $.Event('show.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = true\n\n    this.escape()\n\n    this.backdrop(function () {\n      var transition = $.support.transition && that.$element.hasClass('fade')\n\n      if (!that.$element.parent().length) {\n        that.$element.appendTo(document.body) // don't move modals dom position\n      }\n\n      that.$element.show()\n\n      if (transition) {\n        that.$element[0].offsetWidth // force reflow\n      }\n\n      that.$element\n        .addClass('in')\n        .attr('aria-hidden', false)\n\n      that.enforceFocus()\n\n      transition ?\n        that.$element\n          .one($.support.transition.end, function () {\n            that.$element.focus().trigger('shown.bs.modal')\n          })\n          .emulateTransitionEnd(300) :\n        that.$element.focus().trigger('shown.bs.modal')\n    })\n  }\n\n  Modal.prototype.hide = function (e) {\n    if (e) e.preventDefault()\n\n    e = $.Event('hide.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (!this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = false\n\n    this.escape()\n\n    $(document).off('focusin.bs.modal')\n\n    this.$element\n      .removeClass('in')\n      .attr('aria-hidden', true)\n\n    $.support.transition && this.$element.hasClass('fade') ?\n      this.$element\n        .one($.support.transition.end, $.proxy(this.hideModal, this))\n        .emulateTransitionEnd(300) :\n      this.hideModal()\n  }\n\n  Modal.prototype.enforceFocus = function () {\n    $(document)\n      .off('focusin.bs.modal') // guard against infinite focus loop\n      .on('focusin.bs.modal', $.proxy(function (e) {\n        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\n          this.$element.focus()\n        }\n      }, this))\n  }\n\n  Modal.prototype.escape = function () {\n    if (this.isShown && this.options.keyboard) {\n      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {\n        e.which == 27 && this.hide()\n      }, this))\n    } else if (!this.isShown) {\n      this.$element.off('keyup.dismiss.bs.modal')\n    }\n  }\n\n  Modal.prototype.hideModal = function () {\n    var that = this\n    this.$element.hide()\n    this.backdrop(function () {\n      that.removeBackdrop()\n      that.$element.trigger('hidden.bs.modal')\n    })\n  }\n\n  Modal.prototype.removeBackdrop = function () {\n    this.$backdrop && this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  Modal.prototype.backdrop = function (callback) {\n    var that    = this\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n    if (this.isShown && this.options.backdrop) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n        .appendTo(document.body)\n\n      this.$element.on('click', $.proxy(function (e) {\n        if (e.target !== e.currentTarget) return\n        this.options.backdrop == 'static'\n          ? this.$element[0].focus.call(this.$element[0])\n          : this.hide.call(this)\n      }, this))\n\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n      this.$backdrop.addClass('in')\n\n      if (!callback) return\n\n      doAnimate ?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (!this.isShown && this.$backdrop) {\n      this.$backdrop.removeClass('in')\n\n      $.support.transition && this.$element.hasClass('fade')?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (callback) {\n      callback()\n    }\n  }\n\n\n  // MODAL PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.modal\n\n  $.fn.modal = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.modal')\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option]()\n      else if (options.show) data.show()\n    })\n  }\n\n  $.fn.modal.Constructor = Modal\n\n\n  // MODAL NO CONFLICT\n  // =================\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n  // MODAL DATA-API\n  // ==============\n\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this   = $(this)\n    var href    = $this.attr('href')\n    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) //strip for ie7\n    var option  = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())\n\n    e.preventDefault()\n\n    $target\n      .modal(option)\n      .one('hide', function () {\n        $this.is(':visible') && $this.focus()\n      })\n  })\n\n  $(function () {\n    var $body = $(document.body)\n      .on('shown.bs.modal',  '.modal', function () { $body.addClass('modal-open') })\n      .on('hidden.bs.modal', '.modal', function () { $body.removeClass('modal-open') })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: tooltip.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#affix\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // TOOLTIP PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Tooltip = function (element, options) {\n    this.type       =\n    this.options    =\n    this.enabled    =\n    this.timeout    =\n    this.hoverState =\n    this.$element   = null\n\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.DEFAULTS = {\n    animation: true\n  , placement: 'top'\n  , selector: false\n  , template: '<div class=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n  , trigger: 'hover focus'\n  , title: ''\n  , delay: 0\n  , html: false\n  , container: false\n  }\n\n  Tooltip.prototype.init = function (type, element, options) {\n    this.enabled  = true\n    this.type     = type\n    this.$element = $(element)\n    this.options  = this.getOptions(options)\n\n    var triggers = this.options.trigger.split(' ')\n\n    for (var i = triggers.length; i--;) {\n      var trigger = triggers[i]\n\n      if (trigger == 'click') {\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n      } else if (trigger != 'manual') {\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\n\n        this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n      }\n    }\n\n    this.options.selector ?\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n      this.fixTitle()\n  }\n\n  Tooltip.prototype.getDefaults = function () {\n    return Tooltip.DEFAULTS\n  }\n\n  Tooltip.prototype.getOptions = function (options) {\n    options = $.extend({}, this.getDefaults(), this.$element.data(), options)\n\n    if (options.delay && typeof options.delay == 'number') {\n      options.delay = {\n        show: options.delay\n      , hide: options.delay\n      }\n    }\n\n    return options\n  }\n\n  Tooltip.prototype.enter = function (obj) {\n    var defaults = this.getDefaults()\n    var options  = {}\n\n    this._options && $.each(this._options, function (key, value) {\n      if (defaults[key] != value) options[key] = value\n    })\n\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](options).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    if (!self.options.delay || !self.options.delay.show) return self.show()\n\n    self.hoverState = 'in'\n    self.timeout    = setTimeout(function () {\n      if (self.hoverState == 'in') self.show()\n    }, self.options.delay.show)\n  }\n\n  Tooltip.prototype.leave = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this._options).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n    self.hoverState = 'out'\n    self.timeout    = setTimeout(function () {\n      if (self.hoverState == 'out') self.hide()\n    }, self.options.delay.hide)\n  }\n\n  Tooltip.prototype.show = function () {\n    var e = $.Event('show.bs.'+ this.type)\n\n    if (this.hasContent() && this.enabled) {\n      this.$element.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      var $tip = this.tip()\n\n      this.setContent()\n\n      if (this.options.animation) $tip.addClass('fade')\n\n      var placement = typeof this.options.placement == 'function' ?\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\n        this.options.placement\n\n      var autoToken = /\\s?auto?\\s?/i\n      var autoPlace = autoToken.test(placement)\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\n\n      $tip\n        .detach()\n        .css({ top: 0, left: 0, display: 'block' })\n        .addClass(placement)\n\n      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n\n      var pos          = this.getPosition()\n      var actualWidth  = $tip[0].offsetWidth\n      var actualHeight = $tip[0].offsetHeight\n\n      if (autoPlace) {\n        var $parent = this.$element.parent()\n\n        var orgPlacement = placement\n        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop\n        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()\n        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()\n        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left\n\n        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :\n                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :\n                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :\n                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :\n                    placement\n\n        $tip\n          .removeClass(orgPlacement)\n          .addClass(placement)\n      }\n\n      var tp = placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :\n               placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :\n               placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\n            /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }\n\n      this.applyPlacement(tp, placement)\n      this.$element.trigger('shown.bs.' + this.type)\n    }\n  }\n\n  Tooltip.prototype.applyPlacement = function(offset, placement) {\n    var replace\n    var $tip   = this.tip()\n    var width  = $tip[0].offsetWidth\n    var height = $tip[0].offsetHeight\n\n    // manually read margins because getBoundingClientRect includes difference\n    offset.top  = offset.top  + parseInt($tip.css('margin-top'), 10)\n    offset.left = offset.left + parseInt($tip.css('margin-left'), 10)\n\n    $tip\n      .offset(offset)\n      .addClass('in')\n\n    var actualWidth  = $tip[0].offsetWidth\n    var actualHeight = $tip[0].offsetHeight\n\n    if (placement == 'top' && actualHeight != height) {\n      replace = true\n      offset.top  = offset.top + height - actualHeight\n    }\n\n    if (placement == 'bottom' || placement == 'top') {\n      var delta = 0\n\n      if (offset.left < 0){\n        delta       = offset.left * -2\n        offset.left = 0\n\n        $tip.offset(offset)\n\n        actualWidth  = $tip[0].offsetWidth\n        actualHeight = $tip[0].offsetHeight\n      }\n\n      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')\n    } else {\n      this.replaceArrow(actualHeight - height, actualHeight, 'top')\n    }\n\n    if (replace) $tip.offset(offset)\n  }\n\n  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {\n    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + \"%\") : '')\n  }\n\n  Tooltip.prototype.setContent = function () {\n    var $tip  = this.tip()\n    var title = this.getTitle()\n\n    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\n    $tip.removeClass('fade in top bottom left right')\n  }\n\n  Tooltip.prototype.hide = function () {\n    var that = this\n    var $tip = this.tip()\n    var e    = $.Event('hide.bs.' + this.type)\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    $tip.removeClass('in')\n\n    $.support.transition && this.$tip.hasClass('fade') ?\n      $tip\n        .one($.support.transition.end, $tip.detach)\n        .emulateTransitionEnd(150) :\n      $tip.detach()\n\n    this.$element.trigger('hidden.bs.' + this.type)\n\n    return this\n  }\n\n  Tooltip.prototype.fixTitle = function () {\n    var $e = this.$element\n    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n    }\n  }\n\n  Tooltip.prototype.hasContent = function () {\n    return this.getTitle()\n  }\n\n  Tooltip.prototype.getPosition = function () {\n    var el = this.$element[0]\n    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {\n      width: el.offsetWidth\n    , height: el.offsetHeight\n    }, this.$element.offset())\n  }\n\n  Tooltip.prototype.getTitle = function () {\n    var title\n    var $e = this.$element\n    var o  = this.options\n\n    title = $e.attr('data-original-title')\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n    return title\n  }\n\n  Tooltip.prototype.tip = function () {\n    return this.$tip = this.$tip || $(this.options.template)\n  }\n\n  Tooltip.prototype.arrow =function(){\n    return this.$arrow = this.$arrow || this.tip().find(\".tooltip-arrow\")\n  }\n\n  Tooltip.prototype.validate = function () {\n    if (!this.$element[0].parentNode) {\n      this.hide()\n      this.$element = null\n      this.options  = null\n    }\n  }\n\n  Tooltip.prototype.enable = function () {\n    this.enabled = true\n  }\n\n  Tooltip.prototype.disable = function () {\n    this.enabled = false\n  }\n\n  Tooltip.prototype.toggleEnabled = function () {\n    this.enabled = !this.enabled\n  }\n\n  Tooltip.prototype.toggle = function (e) {\n    var self = e ? $(e.currentTarget)[this.type](this._options).data('bs.' + this.type) : this\n    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n  }\n\n  Tooltip.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)\n  }\n\n\n  // TOOLTIP PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.tooltip')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n\n  // TOOLTIP NO CONFLICT\n  // ===================\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: popover.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#popovers\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // POPOVER PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\n\n  Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {\n    placement: 'right'\n  , trigger: 'click'\n  , content: ''\n  , template: '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n  // NOTE: POPOVER EXTENDS tooltip.js\n  // ================================\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\n\n  Popover.prototype.constructor = Popover\n\n  Popover.prototype.getDefaults = function () {\n    return Popover.DEFAULTS\n  }\n\n  Popover.prototype.setContent = function () {\n    var $tip    = this.tip()\n    var title   = this.getTitle()\n    var content = this.getContent()\n\n    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\n    $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)\n\n    $tip.removeClass('fade top bottom left right in')\n\n    $tip.find('.popover-title:empty').hide()\n  }\n\n  Popover.prototype.hasContent = function () {\n    return this.getTitle() || this.getContent()\n  }\n\n  Popover.prototype.getContent = function () {\n    var $e = this.$element\n    var o  = this.options\n\n    return $e.attr('data-content')\n      || (typeof o.content == 'function' ?\n            o.content.call($e[0]) :\n            o.content)\n  }\n\n  Popover.prototype.tip = function () {\n    if (!this.$tip) this.$tip = $(this.options.template)\n    return this.$tip\n  }\n\n  Popover.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData(this.type)\n  }\n\n\n  // POPOVER PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.popover\n\n  $.fn.popover = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.popover')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n\n  // POPOVER NO CONFLICT\n  // ===================\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: scrollspy.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#scrollspy\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    var href\n    var process  = $.proxy(this.process, this)\n\n    this.$element       = $(element).is('body') ? $(window) : $(element)\n    this.$body          = $('body')\n    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.offsets        = $([])\n    this.targets        = $([])\n    this.activeTarget   = null\n\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'\n\n    this.offsets = $([])\n    this.targets = $([])\n\n    var self     = this\n    var $targets = this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#\\w/.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        self.offsets.push(this[0])\n        self.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n    var maxScroll    = scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets.last()[0]) && this.activate(i)\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\n        && this.activate( targets[i] )\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    $(this.selector)\n      .parents('.active')\n      .removeClass('active')\n\n    var selector = this.selector\n      + '[data-target=\"' + target + '\"],'\n      + this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length)  {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      $spy.scrollspy($spy.data())\n    })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: tab.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#tabs\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // TAB CLASS DEFINITION\n  // ====================\n\n  var Tab = function (element) {\n    this.element = $(element)\n  }\n\n  Tab.prototype.show = function () {\n    var $this    = this.element\n    var $ul      = $this.closest('ul:not(.dropdown-menu)')\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    if ($this.parent('li').hasClass('active')) return\n\n    var previous = $ul.find('.active:last a')[0]\n    var e        = $.Event('show.bs.tab', {\n      relatedTarget: previous\n    })\n\n    $this.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    var $target = $(selector)\n\n    this.activate($this.parent('li'), $ul)\n    this.activate($target, $target.parent(), function () {\n      $this.trigger({\n        type: 'shown.bs.tab'\n      , relatedTarget: previous\n      })\n    })\n  }\n\n  Tab.prototype.activate = function (element, container, callback) {\n    var $active    = container.find('> .active')\n    var transition = callback\n      && $.support.transition\n      && $active.hasClass('fade')\n\n    function next() {\n      $active\n        .removeClass('active')\n        .find('> .dropdown-menu > .active')\n        .removeClass('active')\n\n      element.addClass('active')\n\n      if (transition) {\n        element[0].offsetWidth // reflow for transition\n        element.addClass('in')\n      } else {\n        element.removeClass('fade')\n      }\n\n      if (element.parent('.dropdown-menu')) {\n        element.closest('li.dropdown').addClass('active')\n      }\n\n      callback && callback()\n    }\n\n    transition ?\n      $active\n        .one($.support.transition.end, next)\n        .emulateTransitionEnd(150) :\n      next()\n\n    $active.removeClass('in')\n  }\n\n\n  // TAB PLUGIN DEFINITION\n  // =====================\n\n  var old = $.fn.tab\n\n  $.fn.tab = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.tab')\n\n      if (!data) $this.data('bs.tab', (data = new Tab(this)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tab.Constructor = Tab\n\n\n  // TAB NO CONFLICT\n  // ===============\n\n  $.fn.tab.noConflict = function () {\n    $.fn.tab = old\n    return this\n  }\n\n\n  // TAB DATA-API\n  // ============\n\n  $(document).on('click.bs.tab.data-api', '[data-toggle=\"tab\"], [data-toggle=\"pill\"]', function (e) {\n    e.preventDefault()\n    $(this).tab('show')\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: affix.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#affix\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // AFFIX CLASS DEFINITION\n  // ======================\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, Affix.DEFAULTS, options)\n    this.$window = $(window)\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\n\n    this.$element = $(element)\n    this.affixed  =\n    this.unpin    = null\n\n    this.checkPosition()\n  }\n\n  Affix.RESET = 'affix affix-top affix-bottom'\n\n  Affix.DEFAULTS = {\n    offset: 0\n  }\n\n  Affix.prototype.checkPositionWithEventLoop = function () {\n    setTimeout($.proxy(this.checkPosition, this), 1)\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var scrollHeight = $(document).height()\n    var scrollTop    = this.$window.scrollTop()\n    var position     = this.$element.offset()\n    var offset       = this.options.offset\n    var offsetTop    = offset.top\n    var offsetBottom = offset.bottom\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top()\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()\n\n    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :\n                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :\n                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false\n\n    if (this.affixed === affix) return\n    if (this.unpin) this.$element.css('top', '')\n\n    this.affixed = affix\n    this.unpin   = affix == 'bottom' ? position.top - scrollTop : null\n\n    this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))\n\n    if (affix == 'bottom') {\n      this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })\n    }\n  }\n\n\n  // AFFIX PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.affix\n\n  $.fn.affix = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.affix')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.affix.Constructor = Affix\n\n\n  // AFFIX NO CONFLICT\n  // =================\n\n  $.fn.affix.noConflict = function () {\n    $.fn.affix = old\n    return this\n  }\n\n\n  // AFFIX DATA-API\n  // ==============\n\n  $(window).on('load', function () {\n    $('[data-spy=\"affix\"]').each(function () {\n      var $spy = $(this)\n      var data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      if (data.offsetBottom) data.offset.bottom = data.offsetBottom\n      if (data.offsetTop)    data.offset.top    = data.offsetTop\n\n      $spy.affix(data)\n    })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "site/examples/youtube/css/application.css",
    "content": ".youtube-container {\n\tmargin: 0 auto;\n\t//width: 560px;\n}\n\n.youtube-embed-link {\n\tmargin: 0;\n}\n\n.youtube-embed-link {\n\tmargin-top: 0px;\n}\n\n.embed-submit-button {\n  margin-top: 0px;\n}\n\n.youtube-embed-label {\n  padding-bottom: 0px;\n}\n\n#youtube-example .row {\n  margin-top: 0px;\n  margin-bottom: 0px;\n}\n\n#youtube-example .row .labelarea {\n  padding-bottom: 0px;\n  padding-top: 0px;\n}\n\n#youtube-example .row .linkarea {\n  padding-top: 0px\n}\n\n#youtube-example h1 {\n  margin-bottom: 30px;\n}\n\n#youtube-example h4 {\n  margin-top: 20px;\n  font-family: openSansBold,sans-serif;\n  text-transform: uppercase;\n  font-size: 12px;\n  font-weight: 600;\n  letter-spacing: 1px;\n  line-height: 16px;\n}\n\n#youtube-example .tjsbutton {\n  margin-top: 10px;\n}\n\n@media (min-width: 1200px) {\n  h1 {\n    font-size: 48px !important;\n  }\n\n}\n\n@media (min-width: 992px) {\n  h1 {\n    font-size: 48px !important;\n  }\n}\n\n@media (min-width: 768px) {\n  h1 {\n    font-size: 38px !important;\n  }\n}\n\n@media (min-width: 480px) {\n  h1 {\n    font-size: 38px;\n  }\n}\n\n@media (max-width: 480px) {\n  #youtube-example .tjsbutton img {\n    width: 100px !important;\n  }\n}\n"
  },
  {
    "path": "site/examples/youtube/index.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block title %} Mozilla Labs : YouTube example {% endblock %}\n{% block configs %}\n  <script>\n    var TogetherJSConfig_autoStart = true;\n    var TogetherJSConfig_suppressJoinConfirmation = true;\n    var TogetherJSConfig_dontShowClicks = true;\n    var TogetherJSConfig_youtube = true;\n  </script>\n{% endblock %}\n\n{% block body %}\n  {% block styles %}\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/application.css\" />\n  {% endblock %}\n\n  <div class=\"container\"> <!-- container -->\n    <div class=\"body-content row\" id=\"youtube-example\">\n      <div class=\"col-md-6 col-md-offset-3\">\n        <div id=\"introduction\">\n          <h1>\n            YouTube Together\n            <a class=\"pull-right tjsbutton\" onclick=\"TogetherJS(this); return false;\">\n              <img src=\"https://togetherjs.com/images/start-togetherjs-blue.png\" style=\"width: 125px\"></img>\n            </a>\n          </h1>\n        </div>\n        <div id=\"initial-video\">\n          <div class=\"embed-code flex-video\"><iframe width=\"100%\" height=\"325\" src=\"//www.youtube.com/embed/9bZkp7q19f0\" frameborder=\"0\" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></div>\n        </div>\n        <form role=\"form\">\n          <div class=\"row\">\n            <div class=\"col-xs-12 labelarea\">\n              <div class=\"youtube-embed-link\">\n                <h4>Invite someone to watch a YouTube video together.</h4>\n                <p class=\"youtube-embed-label\">Watch a different YouTube video together! (http://youtu.be/<b>9bZkp7q19f0)</b></p>\n              </div>\n            </div>\n          </div>\n          <div class=\"row\">\n            <div class=\"col-xs-7 col-md-7 linkarea\">\n              <input type=\"text\" class=\"form-control\" id=\"video-id-input\" placeholder='9bZkp7q19f0 (enter a video id)'>\n            </div>\n          </div>\n          <button type=\"button\" class=\"embed-submit-button btn btn-primary\">Submit</button>\n        </form>\n      </div> <!-- // youtube container -->\n    </div> <!-- //body-content -->\n  <script type=\"text/javascript\" src=\"js/application.js\"></script>\n  <script type=\"text/javascript\" src=\"js/jquery-2.0.3.min.js\"></script>\n\n{% endblock %}\n"
  },
  {
    "path": "site/examples/youtube/js/application.js",
    "content": "$(function () {\n  $('.embed-submit-button').click(function() {\n    // FIXME: uncaught exception: [CannotFind #video-id-input(:nth-child(1)): container only has 0 elements in #video-id-input]\n    // I am not sure where this exception is generated. Maybe it is caused by togetherJS?\n    var newVideoId = $('#video-id-input').val();\n    var $youTubeIframe = $(\"iframe[src*='youtube']\");\n    var player = $youTubeIframe.data('togetherjs-player');\n    player.loadVideoById(newVideoId);\n\n    // If the iframe's src is changed, the saved youtube player malfunctions\n    \n    // $(youTubeIframe).attr(\"src\", newSrc);\n    // console.log(\"gonna run reinitailize now...\");\n    // //reinitialize to configure youtube players again\n    // TogetherJS.reinitialize();\n  });\n  $('video-id-input').keypress(function(event) {\n    if (event.keyCode == 13)\n      $('.embed-submit-button').click();\n  });\n});\n"
  },
  {
    "path": "site/faq.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block body %}\n\n    <div class=\"container\">\n      <section class=\"body-content\" id=\"main-section\" data-speed=\"4\" data-type=\"background\">\n        <section class=\"row\" id=\"tour\">\n          <div class=\"col-xs-12\">\n            <h1>FAQ</h1>\n            <h3>What is TogetherJS?</h3>\n            <p>TogetherJS is a JavaScript library that adds collaboration features and tools to your website or app.</p>\n            <h3>If I'm using TogetherJS with people, can they see the current webpage I'm on?</h3>\n            <p>Yup! TogetherJS allows another user to see the content on your screen.  So just be careful and do not show sensitive information.</p>\n            <h3>Does TogetherJS work on Internet Explorer?</h3>\n            <p>Not really, but we really need your help to make it better on IE!  Please help us to improve TogetherJS on IE by taking on a bug in GitHub <a href=\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\" target=\"_blank\">here</a>.</p>\n            <!-- <h3>Section header</h3>\n            <p>text goes here.</p> -->\n          </div>\n        </section>\n\n{% endblock %}\n"
  },
  {
    "path": "site/generic-markdown.tmpl",
    "content": "{% extends \"base.tmpl\" %}\n{# set enableMarkdown true #}\n{% block body %}\n\n<div class=\"container\">\n  <section class=\"row\" id=\"markdownpages\">\n    <div class=\"col-md-9\">\n      <h1>{{ title }}</h1>\n      {{ markdownBody }}\n    </div>\n  </section>\n\n{% endblock %}\n"
  },
  {
    "path": "site/index.html",
    "content": "{% extends \"base.tmpl\" %}\n{% block body %}\n{# set enableHome true #}\n\n    <section id=\"hero\" data-speed=\"10\" data-type=\"background\">\n\n      <section id=\"marketing-video\">\n\n        <div class=\"container\" id=\"frame-video\">\n          <p class=\"text-center\" data-loading-text=\"Loading...\">\n          <div class=\"flex-video widescreen\">\n            <div class=\"video-closebtn\">&#x2716;</div>\n            <iframe id=\"youtubevid\" width=\"100%\" height=\"390px\" src=\"//www.youtube.com/embed/4cqyEhhL15Q?rel=0\" frameborder=\"0\" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>\n          </div>\n          </p>\n        </div>\n      </section>\n\n      <div class=\"container\">\n        <div class=\"row\" id=\"hero-section\">\n          <div class=\"col-md-5\" id=\"box-left\">\n            <h1 class=\"hero-header-text large\">Collaboration made easy.</h1>\n            <h4 class=\"hero-tagline\">Add real time collaboration features to your website today!\n            </h4>\n            <p>\n              <a class=\"btn btn-primary btn-lg main-get-started scrollnav\" href=\"#tryitout-section\">Get Started</a>\n            </p>\n          </div>\n          <div class=\"col-md-7\" id=\"video-area\">\n            <img src=\"images/site-hero-image@2x.png\" class=\"swap1 img-responsive\">\n          </div>\n        </div>\n      </div>\n    </section>\n\n    <div class=\"container\">\n      <section class=\"body-content\" id=\"main-section\" data-speed=\"4\" data-type=\"background\">\n        <section class=\"row\" id=\"tour\">\n          <h3 class=\"text-center\">What is TogetherJS?</h3>\n          <div class=\"col-xs-12 text-center\">\n            <p class=\"text-center\" id=\"text-descrip\">TogetherJS is a <strong>free</strong>, <strong>open source</strong> JavaScript library by <strong>Mozilla</strong> that adds collaboration features and tools to your website.  By adding TogetherJS to your site, your users can help each other out on a website in real time!\n            </p>\n          </div>\n          <hr>\n          <h3 class=\"text-center\">Why use TogetherJS?</h3>\n          <div class=\"col-xs-12 col-sm-4 why-connect-02\">\n            <img src=\"images/site-tour-why-create@2x.png\" alt=\"create with connect\" class=\"img-circle img-responsive why-section\">\n            <h4 class=\"text-center\">Create together.</h4>\n            <p class=\"text-center\"> TogetherJS makes it easy for users on your site to collaborate in real time.</p>\n          </div>\n          <div class=\"col-xs-12 col-sm-4 why-connect-03\">\n            <img src=\"images/site-tour-why-web@2x.png\" alt=\"built for the web icon\" class=\"img-circle img-responsive why-section\">\n            <h4 class=\"text-center\">Built for the web.</h4>\n            <p class=\"text-center\">TogetherJS is implemented in JavaScript; no software or plugins to install, and it's friendly with existing web pages, while still letting developers customize the experience.</p>\n          </div>\n          <div class=\"col-xs-12 col-sm-4 text-center why-connect-01\">\n            <img src=\"images/site-tour-why-moz@2x.png\" alt=\"mozilla logo\" class=\"img-circle img-responsive why-section\">\n            <h4 class=\"text-center\">By someone you trust.</h4>\n            <p class=\"text-center\">TogetherJS is built and hosted by Mozilla, so you know it's safe to use.</p>\n          </div>\n          <div class=\"clearfix\"></div>\n          <hr>\n          <h3 class=\"text-center\">How does TogetherJS work?</h3>\n\n          <div class=\"table-responsive\">\n            <table class=\"table\" id=\"howto-table\">\n              <tbody>\n                <tr class=\"howto-animation-01\">\n                  <td class=\"col-xs-6 col-sm-6\" style=\"vertical-align:middle\">\n                    <h4 class=\"text-right\">Add TogetherJS JavaScript and HTML to your site.</h4>\n                    <p class=\"text-right smtextright\">Just copy and paste TogetherJS's JS library and HTML snippet into your site or app to give it out-of-the-box collaboration tools and features.</p>\n                  </td>\n                  <td class=\"col-xs-6 col-sm-6\">\n                    <!-- FIREFOX FIX -->\n                    <div style=\"position:relative;\" class=\"imagearea\">\n                      <img src=\"images/togetherjs-how-01-addit-file-connecthtml.png\" alt=\"...\" class=\"img-responsive how-section-imganim-01\">\n                      <img src=\"images/togetherjs-how-01-addit-file-connectjs.png\" alt=\"...\" class=\"img-responsive how-section-imganim-02\">\n                      <img src=\"images/togetherjs-how-01-addit-btn-collaborate.png\" alt=\"...\" class=\"img-responsive how-section-imganim-03\">\n                      <p><img src=\"images/togetherjs-how-01-addit-noplus.png\" alt=\"...\" class=\"img-rounded img-responsive how-section\"></p>\n                    </div>\n                  </td>\n                </tr>\n                <tr class=\"howto-animation-02\">\n                  <td class=\"col-xs-12 col-sm-6\">\n                    <div style=\"position:relative;\" class=\"imagearea\">\n                      <img src=\"images/togetherjs-how-02-maindockpiece.png\" alt=\"...\" class=\"img-responsive how-section-dockplacement\">\n                      <img src=\"images/togetherjs-how-02-dock-btn-collaborate-pressed.png\" alt=\"...\" class=\"img-responsive how-section-btncollabpressed\">\n                      <img src=\"images/togetherjs-how-01-addit-btn-collaborate.png\" alt=\"...\" class=\"img-responsive how-section-btncollab\">\n                      <p><img src=\"images/togetherjs-how-02-dock.png\" alt=\"...\" class=\"img-rounded img-responsive how-section\"></p>\n                    </div>\n                  </td>\n                  <td class=\"col-xs-12 col-sm-6\" style=\"vertical-align:middle\">\n                    <h4 class=\"text-left\">Your site is now TogetherJS enabled.</h4>\n                    <p class=\"text-left smtextleft\">If your users want to collaborate with a friend, they can click the TogetherJS button on your site.</p>\n                  </td>\n                </tr>\n                <tr class=\"howto-animation-03\">\n                  <td class=\"col-xs-12 col-sm-6\" style=\"vertical-align:middle\">\n                    <h4 class=\"text-right\">Your users can then collaborate in real time!</h4>\n                    <p class=\"text-right smtextright\">Your users can send a unique TogetherJS url to a friend.  When the friend opens the link, each user sees the same page and can interact with it together in real time.</p>\n                  </td>\n                  <td class=\"col-xs-12 col-sm-6\">\n                    <div style=\"position:relative;\" class=\"imagearea\">\n                      <img src=\"images/togetherjs-how-03-cursor1.png\" alt=\"...\" class=\"img-responsive cursor-placement-01\">\n                      <img src=\"images/togetherjs-how-03-cursor2.png\" alt=\"...\" class=\"img-responsive cursor-placement-02\">\n                      <img src=\"images/togetherjs-how-03-cursor1.png\" alt=\"...\" class=\"img-responsive cursor-placement-03\">\n                      <img src=\"images/togetherjs-how-03-cursor2.png\" alt=\"...\" class=\"img-responsive cursor-placement-04\">\n                      <p><img src=\"images/togetherjs-how-03-collaborate.png\" alt=\"...\" class=\"img-rounded img-responsive how-section\"></p>\n                    </div>\n                  </td>\n                </tr>\n              </tbody>\n            </table>\n          </div>\n          <div class=\"clearfix\"></div>\n          <div class=\"col-xs-12\">\n            <h4 class=\"text-center\">Want to learn more about how it works?</h4>\n            <p class=\"text-center\">\n              See how the technology architecture works <a href=\"docs/#technology-overview\">here</a>.\n            </p>\n          </div>\n        </section>\n\n        <hr id=\"examples-section\">\n\n        <section class=\"row\" id=\"examples\">\n          <h3 class=\"text-center\">Try TogetherJS on these sample apps.</h3>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a data-toggle=\"modal\" href=\"#example-todoapp\"><img src=\"images/site-examples-todo.png\" alt=\"to do app examples\" class=\"img-responsive img-rounded\"></a>\n            <h4 class=\"text-center ex-title\">Grocery To Do app</h4>\n            <p class=\"text-center ex-description\">Try out TogetherJS on this sample grocery app with a friend.</p>\n            <p class=\"text-center\"><button data-toggle=\"modal\" href=\"#example-todoapp\" class=\"btn btn-primary\">Launch</button></p>\n          </div>\n          <!-- <div class=\"col-xs-4\">\n            <a data-toggle=\"modal\" href=\"#example-friendlycode\"><img src=\"images/site-examples-friendlycode.png\" alt=\"friendly code example\" class=\"img-responsive img-rounded\"></a>\n            <h4 class=\"text-center ex-title\">Friendly Code</h4>\n            <p class=\"text-center ex-description\">Code together with your friend.</p>\n            <p class=\"text-center\"><button data-toggle=\"modal\" href=\"#example-friendlycode\" class=\"btn btn-primary\">Launch</button></p>\n          </div> -->\n          <div class=\"col-xs-12 col-sm-4\">\n            <a data-toggle=\"modal\" href=\"#example-madlibs\"><img src=\"images/site-examples-madlibs.png\" alt=\"mad libs example\" class=\"img-responsive img-rounded\"></a>\n            <h4 class=\"text-center ex-title\">Mad Libs</h4>\n            <p class=\"text-center ex-description\">Play Mad Libs with a friend using TogetherJS.</p>\n            <p class=\"text-center\"><button data-toggle=\"modal\" href=\"#example-madlibs\" class=\"btn btn-primary\">Launch</button></p>\n          </div>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a href=\"/examples/drawing/\" target=\"_blank\"><img src=\"images/site-examples-drawing.png\" alt=\"drawing example\" class=\"img-responsive img-rounded\"></a>\n            <h4 class=\"text-center ex-title\">Drawing</h4>\n            <p class=\"text-center ex-description\">Draw with a friend using TogetherJS.</p>\n            <p class=\"text-center\"><a href=\"/examples/drawing/\" class=\"btn btn-primary\" target=\"_blank\">Launch</a></p>\n          </div>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a href=\"/examples/youtube/\" target=\"_blank\"><img src=\"images/site-examples-youtube.png\" alt=\"youtube example\" class=\"img-responsive img-rounded\"></a>\n            <h4 class=\"text-center ex-title\">YouTube</h4>\n            <p class=\"text-center ex-description\">Watch videos with a friend using TogetherJS.</p>\n            <p class=\"text-center\"><a href=\"/examples/youtube/\" class=\"btn btn-primary\" target=\"_blank\">Launch</a></p>\n          </div>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a href=\"/examples/tinymce/\" target=\"_blank\"><img src=\"images/site-examples-tinymce.png\" alt=\"youtube example\" class=\"img-responsive img-rounded\"></a>\n            <h4 class=\"text-center ex-title\">Writing</h4>\n            <p class=\"text-center ex-description\">Write with a friend using TogetherJS.</p>\n            <p class=\"text-center\"><a href=\"/examples/tinymce/\" class=\"btn btn-primary\" target=\"_blank\">Launch</a></p>\n          </div>\n        </section>\n\n        <!-- TO DO APP -->\n         <div class=\"modal fade app-example\" id=\"example-todoapp\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n           <div class=\"modal-dialog\">\n             <div class=\"modal-content\">\n               <div class=\"modal-header\">\n                 <div class=\"top-bar\">\n                   <button type=\"button\" class=\"close pull-right red-circle\" data-dismiss=\"modal\" aria-hidden=\"true\">&times;</button>\n                   <button class=\"yellow-circle pull-left\"></button>\n                   <button class=\"green-circle pull-left\"></button>\n                 </div>\n                 <div class=\"address-bar\">\n                  <input type=\"text\" class=\"form-control\" placeholder=\"http://example.com/todoapp\" readonly>\n                 </div>\n               </div>\n               <div class=\"modal-body\">\n                 <iframe class=\"col-xs-12 delay-open\"\n                          data-delay-src=\"examples/todo/index.html\">\n                 </iframe>\n               </div>\n             </div><!-- /.modal-content -->\n           </div><!-- /.modal-dialog -->\n         </div><!-- /.modal -->\n\n        <!-- FRIENDLY CODE APP -->\n        <div class=\"modal fade app-example\" id=\"example-friendlycode\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n          <div class=\"modal-dialog\">\n            <div class=\"modal-content\">\n              <div class=\"modal-header\">\n                <div class=\"top-bar\">\n                  <button type=\"button\" class=\"close pull-right red-circle\" data-dismiss=\"modal\" aria-hidden=\"true\">&times;</button>\n                  <button class=\"yellow-circle pull-left\"></button>\n                  <button class=\"green-circle pull-left\"></button>\n                </div>\n                <div class=\"address-bar\">\n                 <input type=\"text\" class=\"form-control\" placeholder=\"http://example.com/friendlycode\" readonly>\n                </div>\n              </div>\n              <div class=\"modal-body\">\n                <iframe class=\"col-xs-12 delay-open\"\n                         data-delay-src=\"examples/friendlycode/index.html\">\n                </iframe>\n              </div>\n            </div><!-- /.modal-content -->\n          </div><!-- /.modal-dialog -->\n        </div><!-- /.modal -->\n\n         <!-- MADLIBS APP -->\n         <div class=\"modal fade app-example\" id=\"example-madlibs\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n           <div class=\"modal-dialog\">\n             <div class=\"modal-content\">\n               <div class=\"modal-header\">\n                 <div class=\"top-bar\">\n                   <button type=\"button\" class=\"close pull-right red-circle\" data-dismiss=\"modal\" aria-hidden=\"true\">&times;</button>\n                   <button class=\"yellow-circle pull-left\"></button>\n                   <button class=\"green-circle pull-left\"></button>\n                 </div>\n                 <div class=\"address-bar\">\n                  <input type=\"text\" class=\"form-control\" placeholder=\"http://example.com/madlibs\" readonly>\n                 </div>\n               </div>\n               <div class=\"modal-body\">\n                 <iframe class=\"col-xs-12 delay-open\"\n                          data-delay-src=\"examples/madlibs/index.html\">\n                 </iframe>\n               </div>\n             </div><!-- /.modal-content -->\n           </div><!-- /.modal-dialog -->\n         </div><!-- /.modal -->\n\n        <hr id=\"customers-section\">\n\n        <section class=\"row\" id=\"customers\">\n          <h3 class=\"text-center\">Who is using TogetherJS?</h3>\n          <p class=\"text-center\">\n            TogetherJS is for developers like you.  Whether if you have an <strong>education site</strong>, <strong>coding environment</strong> or <strong>CMS</strong>, TogetherJS can help your users collaborate in real time to accomplish their tasks and work together.\n          </p>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a href=\"https://thimble.webmaker.org/\" target=\"_blank\">\n              <img src=\"images/site-customers-thimble.png\" alt=\"Thimble\" class=\"img-responsive img-rounded\">\n            </a>\n            <h4 class=\"text-center\">Mozilla Thimble</h4>\n            <p class=\"text-center\">Log into Thimble, then click the 'Collaborate' button to start collaborating with a friend!</p>\n          </div>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a href=\"http://jsfiddle.net\" target=\"_blank\">\n              <img src=\"images/site-customers-jsfiddle.png\" alt=\"JSFiddle\" class=\"img-responsive img-rounded\">\n            </a>\n            <h4 class=\"text-center\">JSFiddle</h4>\n            <p class=\"text-center\">Press Control + K on your keyboard to activate TogetherJS.</p>\n          </div>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a href=\"http://wordpress.org/plugins/tags/togetherjs\" target=\"_blank\">\n              <img src=\"images/site-customers-wordpress.png\" alt=\"Wordpress\" class=\"img-responsive img-rounded\">\n            </a>\n            <h4 class=\"text-center\">WordPress Plugins</h4>\n            <p class=\"text-center\">Add a WordPress plugin to your site for real time multi-authoring.</p>\n          </div>\n          <div class=\"clearfix\"></div>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a href=\"https://popcorn.webmaker.org/\" target=\"_blank\">\n              <img src=\"images/site-customers-popcorn.png\" alt=\"Popcorn\" class=\"img-responsive img-rounded\">\n            </a>\n            <h4 class=\"text-center\">Mozilla Popcorn</h4>\n            <p class=\"text-center\">Log into Popcorn, then click the 'Collaborate' button to make a video with a friend!</p>\n          </div>\n          <div class=\"col-xs-12 col-sm-4\">\n            <a href=\"http://dotnetfiddle.net/\" target=\"_blank\">\n              <img src=\"images/site-customers-netfiddle.png\" alt=\".NET Fiddle\" class=\"img-responsive img-rounded\">\n            </a>\n            <h4 class=\"text-center\">.NET Fiddle</h4>\n            <p class=\"text-center\">Code together with a friend in a real time authoring environment.</p>\n          </div>\n          <div class=\"clearfix\"></div>\n          <!-- <h3 class=\"text-center\">Testimonials</h3>\n          <p class=\"text-center\">\n            See what people are saying about ConnectJS.\n          </p>\n          <blockquote class=\"text-center\">\n            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>\n              <small>John Doe from <cite title=\"Source Title\">JSFiddle</cite></small>\n          </blockquote> -->\n        </section>\n\n        <hr id=\"features-section\">\n\n        <section class=\"row\" id=\"features\">\n          <h3 class=\"text-center\">Here are some built-in features!</h3>\n          <div class=\"col-xs-12 col-sm-6\">\n            <ul class=\"media-list\">\n              <li class=\"media\">\n                <div class=\"pull-left\">\n                  <img class=\"media-object\" src=\"images/site-features-audiovideo@2x.png\" alt=\"audio video chat\" class=\"img-responsive\">\n                </div>\n                <div class=\"media-body\">\n                  <h4 class=\"media-heading\">Audio chat</h4>\n                  <p>TogetherJS uses Web RTC technology to enhance communication for your users.</p>\n                </div>\n              </li>\n              <li class=\"media\">\n                <div class=\"pull-left\">\n                  <img class=\"media-object\" src=\"images/site-features-user-focus@2x.png\" alt=\"user focus\" class=\"img-responsive\">\n                </div>\n                <div class=\"media-body\">\n                  <h4 class=\"media-heading\">User focus</h4>\n                  <p>Your users see each other's mouse cursors and clicks.</p>\n                </div>\n              </li>\n              <li class=\"media\">\n                <div class=\"pull-left\">\n                  <img class=\"media-object\" src=\"images/site-features-user-presence@2x.png\" alt=\"user presence\" class=\"img-responsive\">\n                </div>\n                <div class=\"media-body\">\n                  <h4 class=\"media-heading\">User presence</h4>\n                  <p>TogetherJS enables your users to see each other in real time.</p>\n                </div>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-xs-12 col-sm-6\">\n            <ul class=\"media-list\">\n              <li class=\"media\">\n                <div class=\"pull-left\">\n                  <img class=\"media-object\" src=\"images/site-features-text-chat@2x.png\" alt=\"text chat\" class=\"img-responsive\">\n                </div>\n                <div class=\"media-body\">\n                  <h4 class=\"media-heading\">Text chat</h4>\n                  <p>Your users can chat with each other with familiar instant messaging.</p>\n                </div>\n              </li>\n              <li class=\"media\">\n                <div class=\"pull-left\">\n                  <img class=\"media-object\" src=\"images/site-features-cobrowsing@2x.png\" alt=\"co browsing\" class=\"img-responsive\">\n                </div>\n                <div class=\"media-body\">\n                  <h4 class=\"media-heading\">Co-browsing</h4>\n                  <p>Your users can follow each other to different pages on the same domain.</p>\n                </div>\n              </li>\n              <li class=\"media\">\n                <div class=\"pull-left\">\n                  <img class=\"media-object\" src=\"images/site-features-realtimesync@2x.png\" alt=\"real time sync\" class=\"img-responsive\">\n                </div>\n                <div class=\"media-body\">\n                  <h4 class=\"media-heading\">Real time content sync</h4>\n                  <p>Your users can see content on a site or app dynamically change together.</p>\n                </div>\n              </li>\n            </ul>\n          </div>\n          <div class=\"clearfix\"></div>\n        </section>\n\n        <hr id=\"tryitout-section\">\n\n        <section class=\"row\" id=\"tryitout\">\n          <h3 class=\"text-center\">Try out TogetherJS today!</h3>\n            <div class=\"col-xs-12 col-sm-5\">\n              <h4>Add the JavaScript snippet</h4>\n              <p>Simply copy and paste the TogetherJS JavaScript snippet below into your site.</p>\n            </div>\n            <div class=\"col-xs-12 col-sm-7\">\n              <p><pre class=\"pre-scrollable text-center\">&lt;script src=\"https://togetherjs.com/togetherjs-min.js\"&gt;&lt;/script&gt;</pre></p>\n            </div>\n            <div class=\"clearfix\"></div>\n            <div class=\"col-xs-12 col-sm-5\">\n              <h4>Add the HTML button</h4>\n              <p>After you've included the TogetherJS JavaScript snippet, copy and paste this anywhere onto your site!</p>\n            </div>\n            <div class=\"col-xs-12 col-sm-7\">\n              <p><pre class=\"pre-scrollable text-center\">&lt;button onclick=\"TogetherJS(this); return false;\"&gt;Start TogetherJS&lt;/button&gt;</pre></p>\n            </div>\n        </section>\n\n        <script src=\"js/frontpage.js\"></script>\n\n{% endblock %}\n"
  },
  {
    "path": "site/js/bootstrap.js",
    "content": "/**\n* bootstrap.js v3.0.0 by @fat and @mdo\n* Copyright 2013 Twitter Inc.\n* http://www.apache.org/licenses/LICENSE-2.0\n*/\nif (!jQuery) { throw new Error(\"Bootstrap requires jQuery\") }\n\n/* ========================================================================\n * Bootstrap: transition.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#transitions\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)\n  // ============================================================\n\n  function transitionEnd() {\n    var el = document.createElement('bootstrap')\n\n    var transEndEventNames = {\n      'WebkitTransition' : 'webkitTransitionEnd'\n    , 'MozTransition'    : 'transitionend'\n    , 'OTransition'      : 'oTransitionEnd otransitionend'\n    , 'transition'       : 'transitionend'\n    }\n\n    for (var name in transEndEventNames) {\n      if (el.style[name] !== undefined) {\n        return { end: transEndEventNames[name] }\n      }\n    }\n  }\n\n  // http://blog.alexmaccaw.com/css-transitions\n  $.fn.emulateTransitionEnd = function (duration) {\n    var called = false, $el    = this\n    $(this).one($.support.transition.end, function () { called = true })\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\n    setTimeout(callback, duration)\n    return this\n  }\n\n  $(function () {\n    $.support.transition = transitionEnd()\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: alert.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#alerts\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // ALERT CLASS DEFINITION\n  // ======================\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n  var Alert   = function (el) {\n    $(el).on('click', dismiss, this.close)\n  }\n\n  Alert.prototype.close = function (e) {\n    var $this    = $(this)\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = $(selector)\n\n    if (e) e.preventDefault()\n\n    if (!$parent.length) {\n      $parent = $this.hasClass('alert') ? $this : $this.parent()\n    }\n\n    $parent.trigger(e = $.Event('close.bs.alert'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      $parent.trigger('closed.bs.alert').remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent\n        .one($.support.transition.end, removeElement)\n        .emulateTransitionEnd(150) :\n      removeElement()\n  }\n\n\n  // ALERT PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.alert\n\n  $.fn.alert = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.alert')\n\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.alert.Constructor = Alert\n\n\n  // ALERT NO CONFLICT\n  // =================\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n  // ALERT DATA-API\n  // ==============\n\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: button.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#buttons\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // BUTTON PUBLIC CLASS DEFINITION\n  // ==============================\n\n  var Button = function (element, options) {\n    this.$element = $(element)\n    this.options  = $.extend({}, Button.DEFAULTS, options)\n  }\n\n  Button.DEFAULTS = {\n    loadingText: 'loading...'\n  }\n\n  Button.prototype.setState = function (state) {\n    var d    = 'disabled'\n    var $el  = this.$element\n    var val  = $el.is('input') ? 'val' : 'html'\n    var data = $el.data()\n\n    state = state + 'Text'\n\n    if (!data.resetText) $el.data('resetText', $el[val]())\n\n    $el[val](data[state] || this.options[state])\n\n    // push to event loop to allow forms to submit\n    setTimeout(function () {\n      state == 'loadingText' ?\n        $el.addClass(d).attr(d, d) :\n        $el.removeClass(d).removeAttr(d);\n    }, 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input').prop('checked', !this.$element.hasClass('active'))\n      if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')\n    }\n\n    this.$element.toggleClass('active')\n  }\n\n\n  // BUTTON PLUGIN DEFINITION\n  // ========================\n\n  var old = $.fn.button\n\n  $.fn.button = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('button')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  $.fn.button.Constructor = Button\n\n\n  // BUTTON NO CONFLICT\n  // ==================\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n  // BUTTON DATA-API\n  // ===============\n\n  $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {\n    var $btn = $(e.target)\n    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\n    $btn.button('toggle')\n    e.preventDefault()\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: carousel.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#carousel\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // CAROUSEL CLASS DEFINITION\n  // =========================\n\n  var Carousel = function (element, options) {\n    this.$element    = $(element)\n    this.$indicators = this.$element.find('.carousel-indicators')\n    this.options     = options\n    this.paused      =\n    this.sliding     =\n    this.interval    =\n    this.$active     =\n    this.$items      = null\n\n    this.options.pause == 'hover' && this.$element\n      .on('mouseenter', $.proxy(this.pause, this))\n      .on('mouseleave', $.proxy(this.cycle, this))\n  }\n\n  Carousel.DEFAULTS = {\n    interval: 5000\n  , pause: 'hover'\n  }\n\n  Carousel.prototype.cycle =  function (e) {\n    e || (this.paused = false)\n\n    this.interval && clearInterval(this.interval)\n\n    this.options.interval\n      && !this.paused\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n\n    return this\n  }\n\n  Carousel.prototype.getActiveIndex = function () {\n    this.$active = this.$element.find('.item.active')\n    this.$items  = this.$active.parent().children()\n\n    return this.$items.index(this.$active)\n  }\n\n  Carousel.prototype.to = function (pos) {\n    var that        = this\n    var activeIndex = this.getActiveIndex()\n\n    if (pos > (this.$items.length - 1) || pos < 0) return\n\n    if (this.sliding)       return this.$element.one('slid', function () { that.to(pos) })\n    if (activeIndex == pos) return this.pause().cycle()\n\n    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))\n  }\n\n  Carousel.prototype.pause = function (e) {\n    e || (this.paused = true)\n\n    if (this.$element.find('.next, .prev').length && $.support.transition.end) {\n      this.$element.trigger($.support.transition.end)\n      this.cycle(true)\n    }\n\n    this.interval = clearInterval(this.interval)\n\n    return this\n  }\n\n  Carousel.prototype.next = function () {\n    if (this.sliding) return\n    return this.slide('next')\n  }\n\n  Carousel.prototype.prev = function () {\n    if (this.sliding) return\n    return this.slide('prev')\n  }\n\n  Carousel.prototype.slide = function (type, next) {\n    var $active   = this.$element.find('.item.active')\n    var $next     = next || $active[type]()\n    var isCycling = this.interval\n    var direction = type == 'next' ? 'left' : 'right'\n    var fallback  = type == 'next' ? 'first' : 'last'\n    var that      = this\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    $next = $next.length ? $next : this.$element.find('.item')[fallback]()\n\n    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })\n\n    if ($next.hasClass('active')) return\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      this.$element.one('slid', function () {\n        var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])\n        $nextIndicator && $nextIndicator.addClass('active')\n      })\n    }\n\n    if ($.support.transition && this.$element.hasClass('slide')) {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $next.addClass(type)\n      $next[0].offsetWidth // force reflow\n      $active.addClass(direction)\n      $next.addClass(direction)\n      $active\n        .one($.support.transition.end, function () {\n          $next.removeClass([type, direction].join(' ')).addClass('active')\n          $active.removeClass(['active', direction].join(' '))\n          that.sliding = false\n          setTimeout(function () { that.$element.trigger('slid') }, 0)\n        })\n        .emulateTransitionEnd(600)\n    } else {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger('slid')\n    }\n\n    isCycling && this.cycle()\n\n    return this\n  }\n\n\n  // CAROUSEL PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.carousel\n\n  $.fn.carousel = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.carousel')\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\n      var action  = typeof option == 'string' ? option : options.slide\n\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\n      if (typeof option == 'number') data.to(option)\n      else if (action) data[action]()\n      else if (options.interval) data.pause().cycle()\n    })\n  }\n\n  $.fn.carousel.Constructor = Carousel\n\n\n  // CAROUSEL NO CONFLICT\n  // ====================\n\n  $.fn.carousel.noConflict = function () {\n    $.fn.carousel = old\n    return this\n  }\n\n\n  // CAROUSEL DATA-API\n  // =================\n\n  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {\n    var $this   = $(this), href\n    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n    var options = $.extend({}, $target.data(), $this.data())\n    var slideIndex = $this.attr('data-slide-to')\n    if (slideIndex) options.interval = false\n\n    $target.carousel(options)\n\n    if (slideIndex = $this.attr('data-slide-to')) {\n      $target.data('bs.carousel').to(slideIndex)\n    }\n\n    e.preventDefault()\n  })\n\n  $(window).on('load', function () {\n    $('[data-ride=\"carousel\"]').each(function () {\n      var $carousel = $(this)\n      $carousel.carousel($carousel.data())\n    })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: collapse.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#collapse\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // COLLAPSE PUBLIC CLASS DEFINITION\n  // ================================\n\n  var Collapse = function (element, options) {\n    this.$element      = $(element)\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\n    this.transitioning = null\n\n    if (this.options.parent) this.$parent = $(this.options.parent)\n    if (this.options.toggle) this.toggle()\n  }\n\n  Collapse.DEFAULTS = {\n    toggle: true\n  }\n\n  Collapse.prototype.dimension = function () {\n    var hasWidth = this.$element.hasClass('width')\n    return hasWidth ? 'width' : 'height'\n  }\n\n  Collapse.prototype.show = function () {\n    if (this.transitioning || this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('show.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var actives   = this.$parent && this.$parent.find('> .accordion-group > .in')\n\n    if (actives && actives.length) {\n      var hasData = actives.data('bs.collapse')\n      if (hasData && hasData.transitioning) return\n      actives.collapse('hide')\n      hasData || actives.data('bs.collapse', null)\n    }\n\n    var dimension = this.dimension()\n\n    this.$element\n      .removeClass('collapse')\n      .addClass('collapsing')\n      [dimension](0)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.$element\n        .removeClass('collapsing')\n        .addClass('in')\n        [dimension]('auto')\n      this.transitioning = 0\n      this.$element.trigger('shown.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\n\n    this.$element\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n      [dimension](this.$element[0][scrollSize])\n  }\n\n  Collapse.prototype.hide = function () {\n    if (this.transitioning || !this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('hide.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var dimension = this.dimension()\n\n    this.$element\n      [dimension](this.$element[dimension]())\n      [0].offsetHeight\n\n    this.$element\n      .addClass('collapsing')\n      .removeClass('collapse')\n      .removeClass('in')\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.transitioning = 0\n      this.$element\n        .trigger('hidden.bs.collapse')\n        .removeClass('collapsing')\n        .addClass('collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    this.$element\n      [dimension](0)\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n  }\n\n  Collapse.prototype.toggle = function () {\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\n  }\n\n\n  // COLLAPSE PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.collapse\n\n  $.fn.collapse = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.collapse')\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.collapse.Constructor = Collapse\n\n\n  // COLLAPSE NO CONFLICT\n  // ====================\n\n  $.fn.collapse.noConflict = function () {\n    $.fn.collapse = old\n    return this\n  }\n\n\n  // COLLAPSE DATA-API\n  // =================\n\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {\n    var $this   = $(this), href\n    var target  = $this.attr('data-target')\n        || e.preventDefault()\n        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') //strip for ie7\n    var $target = $(target)\n    var data    = $target.data('bs.collapse')\n    var option  = data ? 'toggle' : $this.data()\n    var parent  = $this.attr('data-parent')\n    var $parent = parent && $(parent)\n\n    if (!data || !data.transitioning) {\n      if ($parent) $parent.find('[data-toggle=collapse][data-parent=' + parent + ']').not($this).addClass('collapsed')\n      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')\n    }\n\n    $target.collapse(option)\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: dropdown.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#dropdowns\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // DROPDOWN CLASS DEFINITION\n  // =========================\n\n  var backdrop = '.dropdown-backdrop'\n  var toggle   = '[data-toggle=dropdown]'\n  var Dropdown = function (element) {\n    var $el = $(element).on('click.bs.dropdown', this.toggle)\n  }\n\n  Dropdown.prototype.toggle = function (e) {\n    var $this = $(this)\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    clearMenus()\n\n    if (!isActive) {\n      if ('ontouchstart' in document.documentElement) {\n        // if mobile we we use a backdrop because click events don't delegate\n        $('<div class=\"dropdown-backdrop\"/>').insertAfter($(this)).on('click', clearMenus)\n      }\n\n      $parent.trigger(e = $.Event('show.bs.dropdown'))\n\n      if (e.isDefaultPrevented()) return\n\n      $parent\n        .toggleClass('open')\n        .trigger('shown.bs.dropdown')\n    }\n\n    $this.focus()\n\n    return false\n  }\n\n  Dropdown.prototype.keydown = function (e) {\n    if (!/(38|40|27)/.test(e.keyCode)) return\n\n    var $this = $(this)\n\n    e.preventDefault()\n    e.stopPropagation()\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    if (!isActive || (isActive && e.keyCode == 27)) {\n      if (e.which == 27) $parent.find(toggle).focus()\n      return $this.click()\n    }\n\n    var $items = $('[role=menu] li:not(.divider):visible a', $parent)\n\n    if (!$items.length) return\n\n    var index = $items.index($items.filter(':focus'))\n\n    if (e.keyCode == 38 && index > 0)                 index--                        // up\n    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down\n    if (!~index)                                      index=0\n\n    $items.eq(index).focus()\n  }\n\n  function clearMenus() {\n    $(backdrop).remove()\n    $(toggle).each(function (e) {\n      var $parent = getParent($(this))\n      if (!$parent.hasClass('open')) return\n      $parent.trigger(e = $.Event('hide.bs.dropdown'))\n      if (e.isDefaultPrevented()) return\n      $parent.removeClass('open').trigger('hidden.bs.dropdown')\n    })\n  }\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    var $parent = selector && $(selector)\n\n    return $parent && $parent.length ? $parent : $this.parent()\n  }\n\n\n  // DROPDOWN PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('dropdown')\n\n      if (!data) $this.data('dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.dropdown.Constructor = Dropdown\n\n\n  // DROPDOWN NO CONFLICT\n  // ====================\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\n  // ===================================\n\n  $(document)\n    .on('click.bs.dropdown.data-api', clearMenus)\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.bs.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\n    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: modal.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#modals\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // MODAL CLASS DEFINITION\n  // ======================\n\n  var Modal = function (element, options) {\n    this.options   = options\n    this.$element  = $(element).on('click.dismiss.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this))\n    this.$backdrop =\n    this.isShown   = null\n\n    if (this.options.remote) this.$element.find('.modal-body').load(this.options.remote)\n  }\n\n  Modal.DEFAULTS = {\n      backdrop: true\n    , keyboard: true\n    , show: true\n  }\n\n  Modal.prototype.toggle = function () {\n    return this[!this.isShown ? 'show' : 'hide']()\n  }\n\n  Modal.prototype.show = function () {\n    var that = this\n    var e    = $.Event('show.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = true\n\n    this.escape()\n\n    this.backdrop(function () {\n      var transition = $.support.transition && that.$element.hasClass('fade')\n\n      if (!that.$element.parent().length) {\n        that.$element.appendTo(document.body) // don't move modals dom position\n      }\n\n      that.$element.show()\n\n      if (transition) {\n        that.$element[0].offsetWidth // force reflow\n      }\n\n      that.$element\n        .addClass('in')\n        .attr('aria-hidden', false)\n\n      that.enforceFocus()\n\n      transition ?\n        that.$element\n          .one($.support.transition.end, function () {\n            that.$element.focus().trigger('shown.bs.modal')\n          })\n          .emulateTransitionEnd(300) :\n        that.$element.focus().trigger('shown.bs.modal')\n    })\n  }\n\n  Modal.prototype.hide = function (e) {\n    if (e) e.preventDefault()\n\n    e = $.Event('hide.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (!this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = false\n\n    this.escape()\n\n    $(document).off('focusin.bs.modal')\n\n    this.$element\n      .removeClass('in')\n      .attr('aria-hidden', true)\n\n    $.support.transition && this.$element.hasClass('fade') ?\n      this.$element\n        .one($.support.transition.end, $.proxy(this.hideModal, this))\n        .emulateTransitionEnd(300) :\n      this.hideModal()\n  }\n\n  Modal.prototype.enforceFocus = function () {\n    $(document)\n      .off('focusin.bs.modal') // guard against infinite focus loop\n      .on('focusin.bs.modal', $.proxy(function (e) {\n        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\n          this.$element.focus()\n        }\n      }, this))\n  }\n\n  Modal.prototype.escape = function () {\n    if (this.isShown && this.options.keyboard) {\n      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {\n        e.which == 27 && this.hide()\n      }, this))\n    } else if (!this.isShown) {\n      this.$element.off('keyup.dismiss.bs.modal')\n    }\n  }\n\n  Modal.prototype.hideModal = function () {\n    var that = this\n    this.$element.hide()\n    this.backdrop(function () {\n      that.removeBackdrop()\n      that.$element.trigger('hidden.bs.modal')\n    })\n  }\n\n  Modal.prototype.removeBackdrop = function () {\n    this.$backdrop && this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  Modal.prototype.backdrop = function (callback) {\n    var that    = this\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n    if (this.isShown && this.options.backdrop) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n        .appendTo(document.body)\n\n      this.$element.on('click', $.proxy(function (e) {\n        if (e.target !== e.currentTarget) return\n        this.options.backdrop == 'static'\n          ? this.$element[0].focus.call(this.$element[0])\n          : this.hide.call(this)\n      }, this))\n\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n      this.$backdrop.addClass('in')\n\n      if (!callback) return\n\n      doAnimate ?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (!this.isShown && this.$backdrop) {\n      this.$backdrop.removeClass('in')\n\n      $.support.transition && this.$element.hasClass('fade')?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (callback) {\n      callback()\n    }\n  }\n\n\n  // MODAL PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.modal\n\n  $.fn.modal = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.modal')\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option]()\n      else if (options.show) data.show()\n    })\n  }\n\n  $.fn.modal.Constructor = Modal\n\n\n  // MODAL NO CONFLICT\n  // =================\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n  // MODAL DATA-API\n  // ==============\n\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this   = $(this)\n    var href    = $this.attr('href')\n    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) //strip for ie7\n    var option  = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())\n\n    e.preventDefault()\n\n    $target\n      .modal(option)\n      .one('hide', function () {\n        $this.is(':visible') && $this.focus()\n      })\n  })\n\n  $(function () {\n    var $body = $(document.body)\n      .on('shown.bs.modal',  '.modal', function () { $body.addClass('modal-open') })\n      .on('hidden.bs.modal', '.modal', function () { $body.removeClass('modal-open') })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: tooltip.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#affix\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // TOOLTIP PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Tooltip = function (element, options) {\n    this.type       =\n    this.options    =\n    this.enabled    =\n    this.timeout    =\n    this.hoverState =\n    this.$element   = null\n\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.DEFAULTS = {\n    animation: true\n  , placement: 'top'\n  , selector: false\n  , template: '<div class=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n  , trigger: 'hover focus'\n  , title: ''\n  , delay: 0\n  , html: false\n  , container: false\n  }\n\n  Tooltip.prototype.init = function (type, element, options) {\n    this.enabled  = true\n    this.type     = type\n    this.$element = $(element)\n    this.options  = this.getOptions(options)\n\n    var triggers = this.options.trigger.split(' ')\n\n    for (var i = triggers.length; i--;) {\n      var trigger = triggers[i]\n\n      if (trigger == 'click') {\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n      } else if (trigger != 'manual') {\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\n\n        this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n      }\n    }\n\n    this.options.selector ?\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n      this.fixTitle()\n  }\n\n  Tooltip.prototype.getDefaults = function () {\n    return Tooltip.DEFAULTS\n  }\n\n  Tooltip.prototype.getOptions = function (options) {\n    options = $.extend({}, this.getDefaults(), this.$element.data(), options)\n\n    if (options.delay && typeof options.delay == 'number') {\n      options.delay = {\n        show: options.delay\n      , hide: options.delay\n      }\n    }\n\n    return options\n  }\n\n  Tooltip.prototype.enter = function (obj) {\n    var defaults = this.getDefaults()\n    var options  = {}\n\n    this._options && $.each(this._options, function (key, value) {\n      if (defaults[key] != value) options[key] = value\n    })\n\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](options).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    if (!self.options.delay || !self.options.delay.show) return self.show()\n\n    self.hoverState = 'in'\n    self.timeout    = setTimeout(function () {\n      if (self.hoverState == 'in') self.show()\n    }, self.options.delay.show)\n  }\n\n  Tooltip.prototype.leave = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this._options).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n    self.hoverState = 'out'\n    self.timeout    = setTimeout(function () {\n      if (self.hoverState == 'out') self.hide()\n    }, self.options.delay.hide)\n  }\n\n  Tooltip.prototype.show = function () {\n    var e = $.Event('show.bs.'+ this.type)\n\n    if (this.hasContent() && this.enabled) {\n      this.$element.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      var $tip = this.tip()\n\n      this.setContent()\n\n      if (this.options.animation) $tip.addClass('fade')\n\n      var placement = typeof this.options.placement == 'function' ?\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\n        this.options.placement\n\n      var autoToken = /\\s?auto?\\s?/i\n      var autoPlace = autoToken.test(placement)\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\n\n      $tip\n        .detach()\n        .css({ top: 0, left: 0, display: 'block' })\n        .addClass(placement)\n\n      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n\n      var pos          = this.getPosition()\n      var actualWidth  = $tip[0].offsetWidth\n      var actualHeight = $tip[0].offsetHeight\n\n      if (autoPlace) {\n        var $parent = this.$element.parent()\n\n        var orgPlacement = placement\n        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop\n        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()\n        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()\n        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left\n\n        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :\n                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :\n                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :\n                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :\n                    placement\n\n        $tip\n          .removeClass(orgPlacement)\n          .addClass(placement)\n      }\n\n      var tp = placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :\n               placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :\n               placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\n            /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }\n\n      this.applyPlacement(tp, placement)\n      this.$element.trigger('shown.bs.' + this.type)\n    }\n  }\n\n  Tooltip.prototype.applyPlacement = function(offset, placement) {\n    var replace\n    var $tip   = this.tip()\n    var width  = $tip[0].offsetWidth\n    var height = $tip[0].offsetHeight\n\n    // manually read margins because getBoundingClientRect includes difference\n    offset.top  = offset.top  + parseInt($tip.css('margin-top'), 10)\n    offset.left = offset.left + parseInt($tip.css('margin-left'), 10)\n\n    $tip\n      .offset(offset)\n      .addClass('in')\n\n    var actualWidth  = $tip[0].offsetWidth\n    var actualHeight = $tip[0].offsetHeight\n\n    if (placement == 'top' && actualHeight != height) {\n      replace = true\n      offset.top  = offset.top + height - actualHeight\n    }\n\n    if (placement == 'bottom' || placement == 'top') {\n      var delta = 0\n\n      if (offset.left < 0){\n        delta       = offset.left * -2\n        offset.left = 0\n\n        $tip.offset(offset)\n\n        actualWidth  = $tip[0].offsetWidth\n        actualHeight = $tip[0].offsetHeight\n      }\n\n      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')\n    } else {\n      this.replaceArrow(actualHeight - height, actualHeight, 'top')\n    }\n\n    if (replace) $tip.offset(offset)\n  }\n\n  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {\n    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + \"%\") : '')\n  }\n\n  Tooltip.prototype.setContent = function () {\n    var $tip  = this.tip()\n    var title = this.getTitle()\n\n    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\n    $tip.removeClass('fade in top bottom left right')\n  }\n\n  Tooltip.prototype.hide = function () {\n    var that = this\n    var $tip = this.tip()\n    var e    = $.Event('hide.bs.' + this.type)\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    $tip.removeClass('in')\n\n    $.support.transition && this.$tip.hasClass('fade') ?\n      $tip\n        .one($.support.transition.end, $tip.detach)\n        .emulateTransitionEnd(150) :\n      $tip.detach()\n\n    this.$element.trigger('hidden.bs.' + this.type)\n\n    return this\n  }\n\n  Tooltip.prototype.fixTitle = function () {\n    var $e = this.$element\n    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n    }\n  }\n\n  Tooltip.prototype.hasContent = function () {\n    return this.getTitle()\n  }\n\n  Tooltip.prototype.getPosition = function () {\n    var el = this.$element[0]\n    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {\n      width: el.offsetWidth\n    , height: el.offsetHeight\n    }, this.$element.offset())\n  }\n\n  Tooltip.prototype.getTitle = function () {\n    var title\n    var $e = this.$element\n    var o  = this.options\n\n    title = $e.attr('data-original-title')\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n    return title\n  }\n\n  Tooltip.prototype.tip = function () {\n    return this.$tip = this.$tip || $(this.options.template)\n  }\n\n  Tooltip.prototype.arrow =function(){\n    return this.$arrow = this.$arrow || this.tip().find(\".tooltip-arrow\")\n  }\n\n  Tooltip.prototype.validate = function () {\n    if (!this.$element[0].parentNode) {\n      this.hide()\n      this.$element = null\n      this.options  = null\n    }\n  }\n\n  Tooltip.prototype.enable = function () {\n    this.enabled = true\n  }\n\n  Tooltip.prototype.disable = function () {\n    this.enabled = false\n  }\n\n  Tooltip.prototype.toggleEnabled = function () {\n    this.enabled = !this.enabled\n  }\n\n  Tooltip.prototype.toggle = function (e) {\n    var self = e ? $(e.currentTarget)[this.type](this._options).data('bs.' + this.type) : this\n    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n  }\n\n  Tooltip.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)\n  }\n\n\n  // TOOLTIP PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.tooltip')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n\n  // TOOLTIP NO CONFLICT\n  // ===================\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: popover.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#popovers\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // POPOVER PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\n\n  Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {\n    placement: 'right'\n  , trigger: 'click'\n  , content: ''\n  , template: '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n  // NOTE: POPOVER EXTENDS tooltip.js\n  // ================================\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\n\n  Popover.prototype.constructor = Popover\n\n  Popover.prototype.getDefaults = function () {\n    return Popover.DEFAULTS\n  }\n\n  Popover.prototype.setContent = function () {\n    var $tip    = this.tip()\n    var title   = this.getTitle()\n    var content = this.getContent()\n\n    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\n    $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)\n\n    $tip.removeClass('fade top bottom left right in')\n\n    $tip.find('.popover-title:empty').hide()\n  }\n\n  Popover.prototype.hasContent = function () {\n    return this.getTitle() || this.getContent()\n  }\n\n  Popover.prototype.getContent = function () {\n    var $e = this.$element\n    var o  = this.options\n\n    return $e.attr('data-content')\n      || (typeof o.content == 'function' ?\n            o.content.call($e[0]) :\n            o.content)\n  }\n\n  Popover.prototype.tip = function () {\n    if (!this.$tip) this.$tip = $(this.options.template)\n    return this.$tip\n  }\n\n  Popover.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData(this.type)\n  }\n\n\n  // POPOVER PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.popover\n\n  $.fn.popover = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.popover')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n\n  // POPOVER NO CONFLICT\n  // ===================\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: scrollspy.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#scrollspy\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    var href\n    var process  = $.proxy(this.process, this)\n\n    this.$element       = $(element).is('body') ? $(window) : $(element)\n    this.$body          = $('body')\n    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.offsets        = $([])\n    this.targets        = $([])\n    this.activeTarget   = null\n\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'\n\n    this.offsets = $([])\n    this.targets = $([])\n\n    var self     = this\n    var $targets = this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#\\w/.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        self.offsets.push(this[0])\n        self.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n    var maxScroll    = scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets.last()[0]) && this.activate(i)\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\n        && this.activate( targets[i] )\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    $(this.selector)\n      .parents('.active')\n      .removeClass('active')\n\n    var selector = this.selector\n      + '[data-target=\"' + target + '\"],'\n      + this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length)  {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      $spy.scrollspy($spy.data())\n    })\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: tab.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#tabs\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // TAB CLASS DEFINITION\n  // ====================\n\n  var Tab = function (element) {\n    this.element = $(element)\n  }\n\n  Tab.prototype.show = function () {\n    var $this    = this.element\n    var $ul      = $this.closest('ul:not(.dropdown-menu)')\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    if ($this.parent('li').hasClass('active')) return\n\n    var previous = $ul.find('.active:last a')[0]\n    var e        = $.Event('show.bs.tab', {\n      relatedTarget: previous\n    })\n\n    $this.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    var $target = $(selector)\n\n    this.activate($this.parent('li'), $ul)\n    this.activate($target, $target.parent(), function () {\n      $this.trigger({\n        type: 'shown.bs.tab'\n      , relatedTarget: previous\n      })\n    })\n  }\n\n  Tab.prototype.activate = function (element, container, callback) {\n    var $active    = container.find('> .active')\n    var transition = callback\n      && $.support.transition\n      && $active.hasClass('fade')\n\n    function next() {\n      $active\n        .removeClass('active')\n        .find('> .dropdown-menu > .active')\n        .removeClass('active')\n\n      element.addClass('active')\n\n      if (transition) {\n        element[0].offsetWidth // reflow for transition\n        element.addClass('in')\n      } else {\n        element.removeClass('fade')\n      }\n\n      if (element.parent('.dropdown-menu')) {\n        element.closest('li.dropdown').addClass('active')\n      }\n\n      callback && callback()\n    }\n\n    transition ?\n      $active\n        .one($.support.transition.end, next)\n        .emulateTransitionEnd(150) :\n      next()\n\n    $active.removeClass('in')\n  }\n\n\n  // TAB PLUGIN DEFINITION\n  // =====================\n\n  var old = $.fn.tab\n\n  $.fn.tab = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.tab')\n\n      if (!data) $this.data('bs.tab', (data = new Tab(this)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tab.Constructor = Tab\n\n\n  // TAB NO CONFLICT\n  // ===============\n\n  $.fn.tab.noConflict = function () {\n    $.fn.tab = old\n    return this\n  }\n\n\n  // TAB DATA-API\n  // ============\n\n  $(document).on('click.bs.tab.data-api', '[data-toggle=\"tab\"], [data-toggle=\"pill\"]', function (e) {\n    e.preventDefault()\n    $(this).tab('show')\n  })\n\n}(window.jQuery);\n\n/* ========================================================================\n * Bootstrap: affix.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#affix\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // AFFIX CLASS DEFINITION\n  // ======================\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, Affix.DEFAULTS, options)\n    this.$window = $(window)\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\n\n    this.$element = $(element)\n    this.affixed  =\n    this.unpin    = null\n\n    this.checkPosition()\n  }\n\n  Affix.RESET = 'affix affix-top affix-bottom'\n\n  Affix.DEFAULTS = {\n    offset: 0\n  }\n\n  Affix.prototype.checkPositionWithEventLoop = function () {\n    setTimeout($.proxy(this.checkPosition, this), 1)\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var scrollHeight = $(document).height()\n    var scrollTop    = this.$window.scrollTop()\n    var position     = this.$element.offset()\n    var offset       = this.options.offset\n    var offsetTop    = offset.top\n    var offsetBottom = offset.bottom\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top()\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()\n\n    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :\n                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :\n                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false\n\n    if (this.affixed === affix) return\n    if (this.unpin) this.$element.css('top', '')\n\n    this.affixed = affix\n    this.unpin   = affix == 'bottom' ? position.top - scrollTop : null\n\n    this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))\n\n    if (affix == 'bottom') {\n      this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })\n    }\n  }\n\n\n  // AFFIX PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.affix\n\n  $.fn.affix = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.affix')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.affix.Constructor = Affix\n\n\n  // AFFIX NO CONFLICT\n  // =================\n\n  $.fn.affix.noConflict = function () {\n    $.fn.affix = old\n    return this\n  }\n\n\n  // AFFIX DATA-API\n  // ==============\n\n  $(window).on('load', function () {\n    $('[data-spy=\"affix\"]').each(function () {\n      var $spy = $(this)\n      var data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      if (data.offsetBottom) data.offset.bottom = data.offsetBottom\n      if (data.offsetTop)    data.offset.top    = data.offsetTop\n\n      $spy.affix(data)\n    })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "site/js/custom.js",
    "content": "!function ($) {\n    $(function(){\n\n        // hero image swap\n        // $(\"img.swap1\")\n        //      .mouseover(function() {\n        //          $(this).fadeIn(\"slow\", function(){\n        //            var src = $(this).attr(\"src\").match(/[^\\.]+/) + \"-overlay.png\";\n        //            $(this).attr(\"src\", src);\n        //          });\n        //      })\n        //      .mouseout(function() {\n        //          var src = $(this).attr(\"src\").replace(\"-overlay.png\", \".png\");\n        //          $(this).attr(\"src\", src);\n        //      });\n\n\n        // stop youtube from playing on btn close\n        $('.video-closebtn').click(function(){\n          //alert(\"tset\");\n          var myPlayer = document.getElementById('youtubevid');\n          myPlayer.stopVideo();\n        });\n\n        \n\n        // detect a mobile device\n        var isMobile = {\n            Android: function() {\n                return navigator.userAgent.match(/Android/i);\n            },\n            BlackBerry: function() {\n                return navigator.userAgent.match(/BlackBerry/i);\n            },\n            iOS: function() {\n                return navigator.userAgent.match(/iPhone|iPad|iPod/i);\n            },\n            Opera: function() {\n                return navigator.userAgent.match(/Opera Mini/i);\n            },\n            Windows: function() {\n                return navigator.userAgent.match(/IEMobile/i);\n            },\n            any: function() {\n                return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());\n            }\n        };\n\n          // open up video url\n          if(isMobile.any()){\n\n            //play video on mobile a device\n             $(\"#video-area\").html('<a href=\"http://www.youtube.com/embed/hJEq4W0FZQ0?autoplay=1\"><img src=\"images/site-hero-image@2x.png\" class=\"img-responsive\"></a>');\n\n            // turn off animations\n            jQuery.fx.off = true;\n            \n            $('#video-area').css(\"-webkit-animation\", \"none\");\n            $('#video-area').css(\"-moz-animation\", \"none\");\n            $('#video-area').css(\"-ms-animation\", \"none\");\n            $('#video-area').css(\"animation\", \"none\");\n            \n            $('.hero-header-text').css(\"-webkit-animation\", \"none\");\n            $('.hero-header-text').css(\"-moz-animation\", \"none\");\n            $('.hero-header-text').css(\"-ms-animation\", \"none\");\n            $('.hero-header-text').css(\"animation\", \"none\");\n            \n            $('.hero-tagline').css(\"-webkit-animation\", \"none\");\n            $('.hero-tagline').css(\"-moz-animation\", \"none\");\n            $('.hero-tagline').css(\"-ms-animation\", \"none\");\n            $('.hero-tagline').css(\"animation\", \"none\");\n            \n            $('.main-get-started').css(\"-webkit-animation\", \"none\");\n            $('.main-get-started').css(\"-moz-animation\", \"none\");\n            $('.main-get-started').css(\"-ms-animation\", \"none\");\n            $('.main-get-started').css(\"animation\", \"none\");\n            \n            $( \".howto-animation-01\" ).replaceWith( \"<div class='col-xs-12'><p><img src='images/togetherjs-how-01-addit.png' alt='...' class='img-rounded img-responsive how-section'></p><h4 class='text-left' style='margin-top:0px'>Add TogetherJS Javascript and HTML to your site.</h4><p class='text-left smtextright'>Just copy and paste TogetherJS's JS library and HTML snippet into your site or app to give it out-of-the-box collaboration tools and features.</p></div>\" );\n            $( \".howto-animation-02\" ).replaceWith( \"<div class='col-xs-12'><p><img src='images/togetherjs-how-02-dock-sm@2x.png' alt='...' class='img-rounded img-responsive how-section'></p><h4 class='text-left' style='margin-top:0px'>Your site is now TogetherJS enabled.</h4><p class='text-left smtextleft'>If your users want to collaborate with a friend, they can click the TogetherJS button on your site.</p></div>\" );\n            $( \".howto-animation-03\" ).replaceWith( \"<div class='col-xs-12'><p><img src='images/togetherjs-how-03-collaborate-cursors@2x.png' alt='...' class='img-rounded img-responsive how-section'></p><h4 class='text-left' style='margin-top:0px'>Your users can then collaborate in real time!</h4><p class='text-left smtextright'>Your users can send a unique TogetherJS url to a friend.  When the friend opens the link, each user sees the same page and can interact with it together in real time.</p></div>\" );\n            \n            $(\"#features .col-xs-12.col-sm-6\").first().css({\n              marginBottom: \"-8px\",\n              paddingBottom: \"0px\"\n            });\n            //\n            \n          }\n\n          else {\n            \n            \n            \n            //Video player\n            $( \"#video-area\" ).click(function() {\n              $( \"#marketing-video\" ).fadeIn();\n            });\n\n            $( \"#marketing-video\" ).click(function() {\n              $( \"#marketing-video\" ).fadeOut();\n            });\n\n            $( \".video-closebtn\" ).click(function() {\n              $( \"#marketing-video\" ).fadeOut();\n            });\n\n          }\n\n    })\n}(window.jQuery)\n\n\n\n\n\n// hover effect over video player\n  // $('#main-image').on('mouseenter', function() {\n  //         $(this).fadeOut('slow');\n  //         $('#main-image-overlay').fadeIn('slow');\n  // });\n  //\n  // $('#main-image-overlay').css({left: $('#main-image').position().left, top: $('#main-image').position().top})\n  //            .on('mouseleave', function() {\n  //         $(this).fadeOut('slow');\n  //         $('#main-image').fadeIn('slow');\n  // });\n\n\n// press Escape to close the video player\n// $(document).keyup(function(e) {\n//\n//   if (e.keyCode == 27) {\n//     $( \"#marketing-video\" ).fadeOut();\n//   }   // esc\n//\n// });\n\n// Handler for the Get Help button, to check that help is actually available\n$(function () {\n  var inviteChannel = \"https://hub.togetherjs.com/hub/developers\";\n  var $help = $(\"#get-help\");\n  if (! $help.length) {\n    // No button on this page\n    return;\n  }\n  $help.click(TogetherJS);\n  TogetherJS.checkForUsersOnChannel(inviteChannel, function (n) {\n    if (n === 0) {\n      $help.prop(\"disabled\", true);\n      $help.attr(\"title\", \"Sorry, no one is currently available\");\n      // FIXME: should grey out the invite text too\n      $(\"#nobody-home\").show();\n    }\n  });\n  TogetherJS.on(\"ready\", function () {\n    TogetherJS.require([\"who\", \"session\"], function (who, session) {\n      if (session.firstRun) {\n        who.invite(inviteChannel, null);\n      }\n    });\n  });\n});\n\n// Keeps the invite popup from happening, since the invite will automatically\n// be sent to the Get Help developers\nwindow.TogetherJSConfig_suppressInvite = true;\n"
  },
  {
    "path": "site/js/frontpage.js",
    "content": "$(function () {\n  $(\".modal\").on(\"show.bs.modal\", function () {\n    var iframes = $(this).find(\".delay-open\");\n    iframes.each(function () {\n      $(this).attr(\"src\", $(this).attr(\"data-delay-src\"));\n    });\n  });\n});\n"
  },
  {
    "path": "site/js/how-animations.js",
    "content": "!function ($) {\n    $(function(){\n      \n      function jsUpdateSize(){\n          // Get the dimensions of the viewport\n          var width = window.innerWidth ||\n                      document.documentElement.clientWidth ||\n                      document.body.clientWidth;\n          var height = window.innerHeight ||\n                       document.documentElement.clientHeight ||\n                       document.body.clientHeight;\n\n          //document.getElementById('jsWidth').innerHTML = width;  // Display the width\n          //document.getElementById('jsHeight').innerHTML = height;// Display the height\n          \n          if(width <= 480){\n            //disable animations\n          }\n          else{\n            //play animations\n          }\n          \n      };\n      window.onload = jsUpdateSize;       // When the page first loads\n      window.onresize = jsUpdateSize;     // When the browser changes size\n\n      //animate Why use ConnectJS?\n      $('#tour').waypoint(function() {\n          setTimeout(function() {\n            $( \".why-connect-01 img\" ).animate({\n                top: \"0\",\n                opacity: 1\n              }, 300);\n          }, 0);\n\n          setTimeout(function() {\n            $( \".why-connect-02 img\" ).animate({\n                top: \"0\",\n                opacity: 1\n              }, 300);\n          }, 100);\n          \n          setTimeout(function() {\n            $( \".why-connect-03 img\" ).animate({\n                top: \"0\",\n                opacity: 1\n              }, 300);\n          }, 200);\n\n        }, { offset: 300, triggerOnce: true });\n  \n        //animate How does ConnectJS work?\n        $('.howto-animation-01').waypoint(function() {\n \n          \n          // 1. Add ConnectJS JavaScript and HTML to your site.\n          // animate in first \n          startFirstAnimation();\n          function startFirstAnimation() {\n            $('.how-section-imganim-01').animate({\n              left: \"60%\"\n            }, 800).animate({\n                opacity: \"0\"\n              }, 800).animate({\n                left: \"11%\"\n                }, 7000).animate({\n                  opacity: \"1\"\n                  }, startFirstAnimation);\n          }\n          // animate in second\n          startSecondAnimation();\n          function startSecondAnimation() {\n            $('.how-section-imganim-02').animate({\n              left: \"60%\"\n            }, 800).animate({\n                opacity: \"0\"\n              }, 800).animate({\n                left: \"9%\"\n              }, 7000).animate({\n                opacity: \"1\"\n              }, startSecondAnimation);\n          \n            startFadeInOut();\n            function startFadeInOut(){\n              $('.how-section-imganim-03').delay(1000).fadeIn().delay(6000).fadeOut(); \n            }\n\n          }\n          \n        }, { offset: 300, triggerOnce: false });\n        \n        // 2. Your site is now ConnectJS enabled.\n        $('.howto-animation-02').waypoint(function() {   \n          \n          //startHowAnimation2();\n          \n          function fadeinDock() {\n            $(\".how-section-btncollab\").fadeOut();  \n            $(\".how-section-btncollabpressed\").fadeIn();\n            $(\".how-section-dockplacement\").fadeIn();\n            \n          }\n            \n          function fadeoutDock() {\n            $(\".how-section-dockplacement\").fadeOut();   \n            $(\".how-section-btncollabpressed\").fadeOut();  \n            $(\".how-section-btncollab\").fadeIn(); \n          }\n          \n          function startit(){\n            fadeinDock();\n            setTimeout(function () {\n              fadeoutDock(); \n              setTimeout(startit, 5000);\n              }, 5000)\n          }\n          \n          startit();\n          \n        }, { offset: 200, triggerOnce: false });\n        \n        // 3. Your site is now ConnectJS enabled.        \n        $('.howto-animation-03').waypoint(function() {\n          \n          function startCursorAnimation(){\n            $('.cursor-placement-01').animate({\n              left: \"76%\"\n            }, 800);\n            $('.cursor-placement-03').animate({\n              left: \"40%\"\n            }, 800);\n            setTimeout(function() {\n               $('.cursor-placement-02').animate({\n                 top: \"60%\"\n               }, 800);\n               $('.cursor-placement-04').animate({\n                 top: \"29%\"\n               }, 800);  \n             }, 1000);\n            setTimeout(function() {\n                $('.cursor-placement-01').animate({\n                  left: \"78%\"\n                }, 800);\n                $('.cursor-placement-03').animate({\n                  left: \"44%\"\n                }, 800);  \n              }, 1000);\n              setTimeout(function() {\n                 $('.cursor-placement-02').animate({\n                   top: \"57%\"\n                 }, 800);\n                 $('.cursor-placement-04').animate({\n                   top: \"27%\"\n                 }, 800);  \n               }, 1000);\n            setTimeout(startCursorAnimation, 7000);\n            \n          }\n          startCursorAnimation();\n          console.log(\"animation 3\");\n          \n        }, { offset: 200, triggerOnce: true });\n          \n    })\n}(window.jQuery)\n\n"
  },
  {
    "path": "site/js/imageresizer.js",
    "content": "// check for retina - NOT IN USE\n// if (window.devicePixelRatio > 1){\n//   $(\"img.retina-ready\").each(function(i, img){\n//     // images/thing.png -> images/thing-retina.png\n//     img.src = img.src.split(\".\").join(\"-retina.\");\n//   });\n// }"
  },
  {
    "path": "site/js/parallax.js",
    "content": "$(document).ready(function(){\n  \n  // detect a mobile device\n  var isMobile = {\n      Android: function() {\n          return navigator.userAgent.match(/Android/i);\n      },\n      BlackBerry: function() {\n          return navigator.userAgent.match(/BlackBerry/i);\n      },\n      iOS: function() {\n          return navigator.userAgent.match(/iPhone|iPad|iPod/i);\n      },\n      Opera: function() {\n          return navigator.userAgent.match(/Opera Mini/i);\n      },\n      Windows: function() {\n          return navigator.userAgent.match(/IEMobile/i);\n      },\n      any: function() {\n          return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());\n      }\n  };\n  \n\t// Cache the Window object\n\t$window = $(window);\n                \n   $('section[data-type=\"background\"]').each(function(){\n     var $bgobj = $(this); // assigning the object\n                    \n      $(window).scroll(function() {\n                    \n\t\t// Scroll the background at var speed\n\t\t// the yPos is a negative value because we're scrolling it UP!\t\t\t\t\t\t\t\t\n\t\tvar yPos = -($window.scrollTop() / $bgobj.data('speed')); \n\t\t\n\t\t// Put together our final background position\n\t\tvar coords = '50% '+ yPos + 'px';\n\t\t\n\t\tif (isMobile.any()) {\n\t\t  //remove parallax\n\t\t  var coords = '';\n\t\t}\n\t\t\n\t\t\n\n\t\t// Move the background\n\t\t$bgobj.css({ backgroundPosition: coords });\n\t\t\n}); // window scroll Ends\n\n });\t\n\n}); \n"
  },
  {
    "path": "site/js/retina.js",
    "content": "// retina.js, a high-resolution image swapper (http://retinajs.com), v0.0.2\n\n(function(){function t(e){this.path=e;var t=this.path.split(\".\"),n=t.slice(0,t.length-1).join(\".\"),r=t[t.length-1];this.at_2x_path=n+\"@2x.\"+r}function n(e){this.el=e,this.path=new t(this.el.getAttribute(\"src\"));var n=this;this.path.check_2x_variant(function(e){e&&n.swap()})}var e=typeof exports==\"undefined\"?window:exports;e.RetinaImagePath=t,t.confirmed_paths=[],t.prototype.is_external=function(){return!!this.path.match(/^https?\\:/i)&&!this.path.match(\"//\"+document.domain)},t.prototype.check_2x_variant=function(e){var n,r=this;if(this.is_external())return e(!1);if(this.at_2x_path in t.confirmed_paths)return e(!0);n=new XMLHttpRequest,n.open(\"HEAD\",this.at_2x_path),n.onreadystatechange=function(){return n.readyState!=4?e(!1):n.status>=200&&n.status<=399?(t.confirmed_paths.push(r.at_2x_path),e(!0)):e(!1)},n.send()},e.RetinaImage=n,n.prototype.swap=function(e){function n(){t.el.complete?(t.el.setAttribute(\"width\",t.el.offsetWidth),t.el.setAttribute(\"height\",t.el.offsetHeight),t.el.setAttribute(\"src\",e)):setTimeout(n,5)}typeof e==\"undefined\"&&(e=this.path.at_2x_path);var t=this;n()},e.devicePixelRatio>1&&(window.onload=function(){var e=document.getElementsByTagName(\"img\"),t=[],r,i;for(r=0;r<e.length;r++)i=e[r],t.push(new n(i))})})();"
  },
  {
    "path": "site/js/scrollTo.js",
    "content": "!function ($) {\n    $(function(){\n      \n      \n      //var position = p.position();\n      //$(\"#sidenav\").position.top;\n      //alert($(\"#sidenav\").position().left);\n      \n      //side nav bar\n      $('#sidenav').affix({\n          offset: {\n            top: 100\n          , bottom: 100\n          }\n        })\n      \n\n        var $root = $('html, body');\n\n        // unique nav tag here for HOME PAGE\n        $('a.scrollnav').click(function() {\n            var href = $.attr(this, 'href');\n            $root.animate({\n                scrollTop: $(href).offset().top - 50\n            }, 500, function () {\n                window.location.hash = href;\n            });\n            return false;\n        });\n        \n        // unique nav tag here for DOCUMENATION page\n        $('a.scrollnavdocs').click(function() {\n            var href = $.attr(this, 'href');\n            $root.animate({\n                scrollTop: $(href).offset().top - 100\n            }, 500, function () {\n                window.location.hash = href;\n            });\n            return false;\n        });\n        \n    })\n}(window.jQuery)\n\n"
  },
  {
    "path": "site/js/scrollspy.js",
    "content": "/* ========================================================================\n * Bootstrap: scrollspy.js v3.0.0\n * http://twbs.github.com/bootstrap/javascript.html#scrollspy\n * ========================================================================\n * Copyright 2012 Twitter, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ======================================================================== */\n\n\n+function ($) { \"use strict\";\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    var href\n    var process  = $.proxy(this.process, this)\n\n    this.$element       = $(element).is('body') ? $(window) : $(element)\n    this.$body          = $('body')\n    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.offsets        = $([])\n    this.targets        = $([])\n    this.activeTarget   = null\n\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'\n\n    this.offsets = $([])\n    this.targets = $([])\n\n    var self     = this\n    var $targets = this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#\\w/.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        self.offsets.push(this[0])\n        self.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n    var maxScroll    = scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets.last()[0]) && this.activate(i)\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\n        && this.activate( targets[i] )\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    $(this.selector)\n      .parents('.active')\n      .removeClass('active')\n\n    var selector = this.selector\n      + '[data-target=\"' + target + '\"],'\n      + this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length)  {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      $spy.scrollspy($spy.data())\n    })\n  })\n\n}(window.jQuery);\n"
  },
  {
    "path": "site/js/source-code.js",
    "content": "$(function () {\n  var dl = $(\"#source-toc > dl\");\n  var showButton = $(\"#source-toc-show\");\n  var hideButton = $(\"#source-toc-hide\");\n  $(\"#source-toc header\").click(function () {\n    console.log(\"click\");\n    if (dl.is(\":visible\")) {\n      hideDl();\n    } else {\n      showDl();\n    }\n  });\n  function showDl() {\n    dl.show();\n    showButton.hide();\n    hideButton.show();\n    localStorage.setItem(\"site.showing\", \"yes\");\n  }\n  function hideDl() {\n    dl.hide();\n    showButton.show();\n    hideButton.hide();\n    localStorage.removeItem(\"site.showing\");\n  }\n  if (! localStorage.getItem(\"site.showing\")) {\n    hideDl();\n  } else {\n    showDl();\n  }\n});\n"
  },
  {
    "path": "site/less/alerts.less",
    "content": "//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n  padding: @alert-padding;\n  margin-bottom: @line-height-computed;\n  color: @alert-text;\n  background-color: @alert-bg;\n  border: 1px solid @alert-border;\n  border-radius: @alert-border-radius;\n\n  // Headings for larger alerts\n  h4 {\n    margin-top: 0;\n    // Specified for the h4 to prevent conflicts of changing @headingsColor\n    color: inherit;\n  }\n  // Match the hr to the border of the alert\n  hr {\n    border-top-color: darken(@alert-border, 5%);\n  }\n  // Provide class for links that match alerts\n  .alert-link {\n    font-weight: @alert-link-font-weight;\n    color: darken(@alert-text, 10%);\n  }\n\n  // Improve alignment and spacing of inner content\n  > p,\n  > ul {\n    margin-bottom: 0;\n  }\n  > p + p {\n    margin-top: 5px;\n  }\n}\n\n// Dismissable alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable {\n padding-right: (@alert-padding + 20);\n\n  // Adjust close link position\n  .close {\n    position: relative;\n    top: -2px;\n    right: -21px;\n    color: inherit;\n  }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n  .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-danger {\n  .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n.alert-info {\n  .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n"
  },
  {
    "path": "site/less/badges.less",
    "content": "//\n// Badges\n// --------------------------------------------------\n\n\n// Base classes\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: @font-size-small;\n  font-weight: @badge-font-weight;\n  color: @badge-color;\n  line-height: @badge-line-height;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: @badge-bg;\n  border-radius: @badge-border-radius;\n\n  // Empty badges collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n}\n\n// Hover state, but only for links\na.badge {\n  &:hover,\n  &:focus {\n    color: @badge-link-hover-color;\n    text-decoration: none;\n    cursor: pointer;\n  }\n}\n\n// Quick fix for labels/badges in buttons\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\n// Account for counters in navs\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: @badge-active-color;\n  background-color: @badge-active-bg;\n}\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n"
  },
  {
    "path": "site/less/bootstrap.less",
    "content": "/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world by @mdo and @fat.\n */\n\n// Core variables and mixins\n@import \"variables.less\";\n@import \"mixins.less\";\n\n// Reset\n@import \"normalize.less\";\n@import \"print.less\";\n\n// Core CSS\n@import \"scaffolding.less\";\n@import \"type.less\";\n@import \"code.less\";\n@import \"grid.less\";\n\n@import \"tables.less\";\n@import \"forms.less\";\n@import \"buttons.less\";\n\n// Components: common\n@import \"component-animations.less\";\n@import \"input-groups.less\";\n@import \"dropdowns.less\";\n@import \"list-group.less\";\n@import \"panels.less\";\n@import \"wells.less\";\n@import \"close.less\";\n\n// Components: Nav\n@import \"navs.less\";\n@import \"navbar.less\";\n@import \"button-groups.less\";\n@import \"breadcrumbs.less\";\n@import \"pagination.less\";\n@import \"pager.less\";\n\n// Components: Popovers\n@import \"modals.less\";\n@import \"tooltip.less\";\n@import \"popovers.less\";\n\n// Components: Misc\n@import \"alerts.less\";\n@import \"thumbnails.less\";\n@import \"media.less\";\n@import \"labels.less\";\n@import \"badges.less\";\n@import \"progress-bars.less\";\n@import \"carousel.less\";\n@import \"jumbotron.less\";\n\n// Utility classes\n@import \"utilities.less\"; // Has to be last to override when necessary\n@import \"responsive-utilities.less\";\n"
  },
  {
    "path": "site/less/breadcrumbs.less",
    "content": "//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin-bottom: @line-height-computed;\n  list-style: none;\n  background-color: @breadcrumb-bg;\n  border-radius: @border-radius-base;\n  > li {\n    display: inline-block;\n    &+li:before {\n      content: \"/\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n      padding: 0 5px;\n      color: @breadcrumb-color;\n    }\n  }\n  > .active {\n    color: @breadcrumb-active-color;\n  }\n}\n"
  },
  {
    "path": "site/less/button-groups.less",
    "content": "//\n// Button groups\n// --------------------------------------------------\n\n// Button carets\n//\n// Match the button text color to the arrow/caret for indicating dropdown-ness.\n\n.caret {\n  .btn-default & {\n    border-top-color: @btn-default-color;\n  }\n  .btn-primary &,\n  .btn-success &,\n  .btn-warning &,\n  .btn-danger &,\n  .btn-info & {\n    border-top-color: #fff;\n  }\n}\n.dropup {\n  & .btn-default .caret {\n    border-bottom-color: @btn-default-color;\n  }\n  & .btn-primary,\n  & .btn-success,\n  & .btn-warning,\n  & .btn-danger,\n  & .btn-info {\n   .caret {\n      border-bottom-color: #fff;\n    }\n  }\n}\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle; // match .btn alignment given font-size hack above\n  > .btn {\n    position: relative;\n    float: left;\n    // Bring the \"active\" button to the front\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      z-index: 2;\n    }\n    &:focus {\n      // Remove focus outline when dropdown JS adds it after closing the menu\n      outline: none;\n    }\n  }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n  .btn + .btn,\n  .btn + .btn-group,\n  .btn-group + .btn,\n  .btn-group + .btn-group {\n    margin-left: -1px;\n  }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n  .clearfix();\n\n  .btn-group {\n    float: left;\n  }\n  // Space out series of button groups\n  > .btn,\n  > .btn-group {\n    + .btn,\n    + .btn-group {\n      margin-left: 5px;\n    }\n  }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  &:not(:last-child):not(.dropdown-toggle) {\n    .border-right-radius(0);\n  }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\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 {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    .border-right-radius(0);\n  }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n  .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { .btn-xs(); }\n.btn-group-sm > .btn { .btn-sm(); }\n.btn-group-lg > .btn { .btn-lg(); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n  .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n}\n\n\n// Reposition the caret\n.btn .caret {\n  margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n  border-width: @caret-width-large;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n  border-bottom-width: @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n  > .btn,\n  > .btn-group {\n    display: block;\n    float: none;\n    width: 100%;\n    max-width: 100%;\n  }\n\n  // Clear floats so dropdown menus can be properly placed\n  > .btn-group {\n    .clearfix();\n    > .btn {\n      float: none;\n    }\n  }\n\n  > .btn + .btn,\n  > .btn + .btn-group,\n  > .btn-group + .btn,\n  > .btn-group + .btn-group {\n    margin-top: -1px;\n    margin-left: 0;\n  }\n}\n\n.btn-group-vertical > .btn {\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n  &:first-child:not(:last-child) {\n    border-top-right-radius: @border-radius-base;\n    .border-bottom-radius(0);\n  }\n  &:last-child:not(:first-child) {\n    border-bottom-left-radius: @border-radius-base;\n    .border-top-radius(0);\n  }\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 {\n  > .btn:last-child,\n  > .dropdown-toggle {\n    .border-bottom-radius(0);\n  }\n}\n.btn-group-vertical > .btn-group:last-child > .btn:first-child {\n  .border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n  .btn {\n    float: none;\n    display: table-cell;\n    width: 1%;\n  }\n}\n\n\n// Checkbox and radio options\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n"
  },
  {
    "path": "site/less/buttons.less",
    "content": "//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n// Core styles\n.btn {\n  display: inline-block;\n  padding: @padding-base-vertical @padding-base-horizontal;\n  margin-bottom: 0; // For input.btn\n  font-size: @font-size-base;\n  font-weight: @btn-font-weight;\n  line-height: @line-height-base;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  border: 1px solid transparent;\n  border-radius: @border-radius-base;\n  white-space: nowrap;\n  .user-select(none);\n\n  &:focus {\n    .tab-focus();\n  }\n\n  &:hover,\n  &:focus {\n    color: @btn-default-color;\n    text-decoration: none;\n  }\n\n  &:active,\n  &.active {\n    outline: 0;\n    background-image: none;\n    .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n  }\n\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    pointer-events: none; // Future-proof disabling of clicks\n    .opacity(.65);\n    .box-shadow(none);\n  }\n\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n  .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n  .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Warning appears as orange\n.btn-warning {\n  .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n  .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n// Success appears as green\n.btn-success {\n  .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n  .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n  color: @link-color;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n\n  &,\n  &:active,\n  &[disabled],\n  fieldset[disabled] & {\n    background-color: transparent;\n    .box-shadow(none);\n  }\n  &,\n  &:hover,\n  &:focus,\n  &:active {\n    border-color: transparent;\n  }\n  &:hover,\n  &:focus {\n    color: @link-hover-color;\n    text-decoration: underline;\n    background-color: transparent;\n  }\n  &[disabled],\n  fieldset[disabled] & {\n    &:hover,\n    &:focus {\n      color: @btn-link-disabled-color;\n      text-decoration: none;\n    }\n  }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n  // line-height: ensure even-numbered height of button next to large input\n  .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm,\n.btn-xs {\n  // line-height: ensure proper height of button next to small input\n  .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n  padding: 1px 5px;\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n  &.btn-block {\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "site/less/carousel.less",
    "content": "//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  overflow: hidden;\n  width: 100%;\n\n  > .item {\n    display: none;\n    position: relative;\n    .transition(.6s ease-in-out left);\n\n    // Account for jankitude on images\n    > img,\n    > a > img {\n      .img-responsive();\n      line-height: 1;\n    }\n  }\n\n  > .active,\n  > .next,\n  > .prev { display: block; }\n\n  > .active {\n    left: 0;\n  }\n\n  > .next,\n  > .prev {\n    position: absolute;\n    top: 0;\n    width: 100%;\n  }\n\n  > .next {\n    left: 100%;\n  }\n  > .prev {\n    left: -100%;\n  }\n  > .next.left,\n  > .prev.right {\n    left: 0;\n  }\n\n  > .active.left {\n    left: -100%;\n  }\n  > .active.right {\n    left: 100%;\n  }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  width: @carousel-control-width;\n  .opacity(@carousel-control-opacity);\n  font-size: @carousel-control-font-size;\n  color: @carousel-control-color;\n  text-align: center;\n  text-shadow: @carousel-text-shadow;\n  // We can't have this transition here because webkit cancels the carousel\n  // animation if you trip this while in the middle of another animation.\n\n  // Set gradients for backgrounds\n  &.left {\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n  }\n  &.right {\n    left: auto;\n    right: 0;\n    #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n  }\n\n  // Hover/focus state\n  &:hover,\n  &:focus {\n    color: @carousel-control-color;\n    text-decoration: none;\n    .opacity(.9);\n  }\n\n  // Toggles\n  .icon-prev,\n  .icon-next {\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    z-index: 5;\n    display: inline-block;\n    width:  20px;\n    height: 20px;\n    margin-top: -10px;\n    margin-left: -10px;\n    font-family: serif;\n  }\n\n  .icon-prev {\n    &:before {\n      content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n    }\n  }\n  .icon-next {\n    &:before {\n      content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n    }\n  }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 60%;\n  margin-left: -30%;\n  padding-left: 0;\n  list-style: none;\n  text-align: center;\n\n  li {\n    display: inline-block;\n    width:  10px;\n    height: 10px;\n    margin: 1px;\n    text-indent: -999px;\n    border: 1px solid @carousel-indicator-border-color;\n    border-radius: 10px;\n    cursor: pointer;\n  }\n  .active {\n    margin: 0;\n    width:  12px;\n    height: 12px;\n    background-color: @carousel-indicator-active-bg;\n  }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n  position: absolute;\n  left: 15%;\n  right: 15%;\n  bottom: 20px;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: @carousel-caption-color;\n  text-align: center;\n  text-shadow: @carousel-text-shadow;\n  & .btn {\n    text-shadow: none; // No shadow for button elements in carousel-caption\n  }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-tablet) {\n\n  // Scale up the controls a smidge\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\n  // Show and left align the captions\n  .carousel-caption {\n    left: 20%;\n    right: 20%;\n    padding-bottom: 30px;\n  }\n\n  // Move up the indicators\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n"
  },
  {
    "path": "site/less/close.less",
    "content": "//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n  float: right;\n  font-size: (@font-size-base * 1.5);\n  font-weight: @close-font-weight;\n  line-height: 1;\n  color: @close-color;\n  text-shadow: @close-text-shadow;\n  .opacity(.2);\n\n  &:hover,\n  &:focus {\n    color: @close-color;\n    text-decoration: none;\n    cursor: pointer;\n    .opacity(.5);\n  }\n\n  // Additional properties for button version\n  // iOS requires the button element instead of an anchor tag.\n  // If you want the anchor version, it requires `href=\"#\"`.\n  button& {\n    padding: 0;\n    cursor: pointer;\n    background: transparent;\n    border: 0;\n    -webkit-appearance: none;\n  }\n}\n"
  },
  {
    "path": "site/less/code.less",
    "content": "//\n// Code (inline and blocK)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\npre {\n  font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: @code-color;\n  background-color: @code-bg;\n  white-space: nowrap;\n  border-radius: @border-radius-base;\n}\n\n// Blocks of code\npre {\n  display: block;\n  padding: ((@line-height-computed - 1) / 2);\n  margin: 0 0 (@line-height-computed / 2);\n  font-size: (@font-size-base - 1); // 14px to 13px\n  line-height: @line-height-base;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: @pre-color;\n  background-color: @pre-bg;\n  border: 1px solid @pre-border-color;\n  border-radius: @border-radius-base;\n\n  // Make prettyprint styles more spaced out for readability\n  &.prettyprint {\n    margin-bottom: @line-height-computed;\n  }\n\n  // Account for some code outputs that place code tags in pre tags\n  code {\n    padding: 0;\n    font-size: inherit;\n    color: inherit;\n    white-space: pre-wrap;\n    background-color: transparent;\n    border: 0;\n  }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n  max-height: @pre-scrollable-max-height;\n  overflow-y: scroll;\n}\n"
  },
  {
    "path": "site/less/component-animations.less",
    "content": "//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.\n\n.fade {\n  opacity: 0;\n  .transition(opacity .15s linear);\n  &.in {\n    opacity: 1;\n  }\n}\n\n.collapse {\n  display: none;\n  &.in {\n    display: block;\n  }\n}\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  .transition(height .35s ease);\n}\n"
  },
  {
    "path": "site/less/dropdowns.less",
    "content": "//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top:   @caret-width-base solid @dropdown-caret-color;\n  border-right: @caret-width-base solid transparent;\n  border-left:  @caret-width-base solid transparent;\n  content: \"\";\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n  position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n  outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: @zindex-dropdown;\n  display: none; // none by default, but block on \"open\" of the menu\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0; // override default ul\n  list-style: none;\n  font-size: @font-size-base;\n  background-color: @dropdown-bg;\n  border: 1px solid @dropdown-fallback-border; // IE8 fallback\n  border: 1px solid @dropdown-border;\n  border-radius: @border-radius-base;\n  .box-shadow(0 6px 12px rgba(0,0,0,.175));\n  background-clip: padding-box;\n\n  // Aligns the dropdown menu to right\n  &.pull-right {\n    right: 0;\n    left: auto;\n  }\n\n  // Dividers (basically an hr) within the dropdown\n  .divider {\n    .nav-divider(@dropdown-divider-bg);\n  }\n\n  // Links within the dropdown menu\n  > li > a {\n    display: block;\n    padding: 3px 20px;\n    clear: both;\n    font-weight: normal;\n    line-height: @line-height-base;\n    color: @dropdown-link-color;\n    white-space: nowrap; // prevent links from randomly breaking onto new lines\n  }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    color: @dropdown-link-hover-color;\n    background-color: @dropdown-link-hover-bg;\n  }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n  &,\n  &:hover,\n  &:focus {\n    color: @dropdown-link-active-color;\n    text-decoration: none;\n    outline: 0;\n    background-color: @dropdown-link-active-bg;\n  }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n  &,\n  &:hover,\n  &:focus {\n    color: @dropdown-link-disabled-color;\n  }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n  &:hover,\n  &:focus {\n    text-decoration: none;\n    background-color: transparent;\n    background-image: none; // Remove CSS gradient\n    .reset-filter();\n    cursor: not-allowed;\n  }\n}\n\n// Open state for the dropdown\n.open {\n  // Show the menu\n  > .dropdown-menu {\n    display: block;\n  }\n\n  // Remove the outline when :focus is triggered\n  > a {\n    outline: 0;\n  }\n}\n\n// Dropdown section headers\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: @font-size-small;\n  line-height: @line-height-base;\n  color: @dropdown-header-color;\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n  position: fixed;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  top: 0;\n  z-index: @zindex-dropdown - 10;\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n  // Reverse the caret\n  .caret {\n    border-top: 0;\n    border-bottom: 4px solid @dropdown-caret-color;\n    content: \"\";\n  }\n  // Different positioning for bottom up menu\n  .dropdown-menu {\n    top: auto;\n    bottom: 100%;\n    margin-bottom: 1px;\n  }\n}\n"
  },
  {
    "path": "site/less/forms.less",
    "content": "//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: @line-height-computed;\n  font-size: (@font-size-base * 1.5);\n  line-height: inherit;\n  color: @legend-color;\n  border: 0;\n  border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\n\n// Normalize form controls\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n  .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9; /* IE8-9 */\n  line-height: normal;\n}\n\n// Set the height of select and file controls to match text inputs\ninput[type=\"file\"] {\n  display: block;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\n// Fix optgroup Firefox bug per https://github.com/twbs/bootstrap/issues/7611\nselect optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\n\n// Focus for select, file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  .tab-focus();\n}\n\n// Fix for Chrome number input\n// Setting certain font-sizes causes the `I` bar to appear on hover of the bottom increment button.\n// See https://github.com/twbs/bootstrap/issues/8350 for more.\ninput[type=\"number\"] {\n  &::-webkit-outer-spin-button,\n  &::-webkit-inner-spin-button {\n    height: auto;\n  }\n}\n\n\n// Placeholder\n//\n// Placeholder text gets special styles because when browsers invalidate entire\n// lines if it doesn't understand a selector/\n.form-control {\n  .placeholder();\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n  padding: @padding-base-vertical @padding-base-horizontal;\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @input-color;\n  vertical-align: middle;\n  background-color: @input-bg;\n  border: 1px solid @input-border;\n  border-radius: @input-border-radius;\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n  .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n  // Customize the `:focus` state to imitate native WebKit styles.\n  .form-control-focus();\n\n  // Disabled and read-only inputs\n  // Note: HTML5 says that controls under a fieldset > legend:first-child won't\n  // be disabled if the fieldset is disabled. Due to implementation difficulty,\n  // we don't honor that edge case; we style them as disabled anyway.\n  &[disabled],\n  &[readonly],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n    background-color: @input-bg-disabled;\n  }\n\n  // Reset height for `textarea`s\n  textarea& {\n    height: auto;\n  }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n  margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n  display: block;\n  min-height: @line-height-computed; // clear the floating input if there is no label text\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n  label {\n    display: inline;\n    margin-bottom: 0;\n    font-weight: normal;\n    cursor: pointer;\n  }\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; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"],\n.radio,\n.radio-inline,\n.checkbox,\n.checkbox-inline {\n  &[disabled],\n  fieldset[disabled] & {\n    cursor: not-allowed;\n  }\n}\n\n// Form control sizing\n.input-sm {\n  .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n  .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n// Warning\n.has-warning {\n  .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n// Error\n.has-error {\n  .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n// Success\n.has-success {\n  .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n  margin-bottom: 0; // Remove default margin from `p`\n  padding-top: @padding-base-vertical;\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n  display: block; // account for any element using help-block\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n  // Kick in the inline\n  @media (min-width: @screen-tablet) {\n    // Inline-block all the things for \"inline\"\n    .form-group  {\n      display: inline-block;\n      margin-bottom: 0;\n      vertical-align: middle;\n    }\n\n    // In navbar-form, allow folks to *not* use `.form-group`\n    .form-control {\n      display: inline-block;\n    }\n\n    // Remove default margin on radios/checkboxes that were used for stacking, and\n    // then undo the floating of radios and checkboxes to match (which also avoids\n    // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n    .radio,\n    .checkbox {\n      display: inline-block;\n      margin-top: 0;\n      margin-bottom: 0;\n      padding-left: 0;\n    }\n    .radio input[type=\"radio\"],\n    .checkbox input[type=\"checkbox\"] {\n      float: none;\n      margin-left: 0;\n    }\n  }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal .control-label,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n  padding-top: @padding-base-vertical;\n}\n\n.form-horizontal {\n  .form-group {\n    .make-row();\n  }\n}\n\n// Only right align form labels here when the columns stop stacking\n@media (min-width: @screen-tablet) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n"
  },
  {
    "path": "site/less/grid.less",
    "content": "//\n// Grid system\n// --------------------------------------------------\n\n\n// Set the container width, and override it for fixed navbars in media queries\n.container {\n  .container-fixed();\n}\n\n// Mobile-first defaults\n.row {\n  .make-row();\n}\n\n// Common styles for small and large grid columns\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12,\n.col-sm-1,\n.col-sm-2,\n.col-sm-3,\n.col-sm-4,\n.col-sm-5,\n.col-sm-6,\n.col-sm-7,\n.col-sm-8,\n.col-sm-9,\n.col-sm-10,\n.col-sm-11,\n.col-sm-12,\n.col-md-1,\n.col-md-2,\n.col-md-3,\n.col-md-4,\n.col-md-5,\n.col-md-6,\n.col-md-7,\n.col-md-8,\n.col-md-9,\n.col-md-10,\n.col-md-11,\n.col-md-12,\n.col-lg-1,\n.col-lg-2,\n.col-lg-3,\n.col-lg-4,\n.col-lg-5,\n.col-lg-6,\n.col-lg-7,\n.col-lg-8,\n.col-lg-9,\n.col-lg-10,\n.col-lg-11,\n.col-lg-12 {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@grid-gutter-width / 2);\n  padding-right: (@grid-gutter-width / 2);\n}\n\n\n// Extra small grid\n//\n// Grid classes for extra small devices like smartphones. No offset, push, or\n// pull classes are present here due to the size of the target.\n//\n// Note that `.col-xs-12` doesn't get floated on purpose—there's no need since\n// it's full-width.\n\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11 {\n  float: left;\n}\n.col-xs-1  { width: percentage((1 / @grid-columns)); }\n.col-xs-2  { width: percentage((2 / @grid-columns)); }\n.col-xs-3  { width: percentage((3 / @grid-columns)); }\n.col-xs-4  { width: percentage((4 / @grid-columns)); }\n.col-xs-5  { width: percentage((5 / @grid-columns)); }\n.col-xs-6  { width: percentage((6 / @grid-columns)); }\n.col-xs-7  { width: percentage((7 / @grid-columns)); }\n.col-xs-8  { width: percentage((8 / @grid-columns)); }\n.col-xs-9  { width: percentage((9 / @grid-columns)); }\n.col-xs-10 { width: percentage((10/ @grid-columns)); }\n.col-xs-11 { width: percentage((11/ @grid-columns)); }\n.col-xs-12 { width: 100%; }\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n//\n// Note that `.col-sm-12` doesn't get floated on purpose—there's no need since\n// it's full-width.\n\n@media (min-width: @screen-tablet) {\n  .container {\n    max-width: @container-tablet;\n  }\n\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11 {\n    float: left;\n  }\n  .col-sm-1  { width: percentage((1 / @grid-columns)); }\n  .col-sm-2  { width: percentage((2 / @grid-columns)); }\n  .col-sm-3  { width: percentage((3 / @grid-columns)); }\n  .col-sm-4  { width: percentage((4 / @grid-columns)); }\n  .col-sm-5  { width: percentage((5 / @grid-columns)); }\n  .col-sm-6  { width: percentage((6 / @grid-columns)); }\n  .col-sm-7  { width: percentage((7 / @grid-columns)); }\n  .col-sm-8  { width: percentage((8 / @grid-columns)); }\n  .col-sm-9  { width: percentage((9 / @grid-columns)); }\n  .col-sm-10 { width: percentage((10/ @grid-columns)); }\n  .col-sm-11 { width: percentage((11/ @grid-columns)); }\n  .col-sm-12 { width: 100%; }\n\n  // Push and pull columns for source order changes\n  .col-sm-push-1  { left: percentage((1 / @grid-columns)); }\n  .col-sm-push-2  { left: percentage((2 / @grid-columns)); }\n  .col-sm-push-3  { left: percentage((3 / @grid-columns)); }\n  .col-sm-push-4  { left: percentage((4 / @grid-columns)); }\n  .col-sm-push-5  { left: percentage((5 / @grid-columns)); }\n  .col-sm-push-6  { left: percentage((6 / @grid-columns)); }\n  .col-sm-push-7  { left: percentage((7 / @grid-columns)); }\n  .col-sm-push-8  { left: percentage((8 / @grid-columns)); }\n  .col-sm-push-9  { left: percentage((9 / @grid-columns)); }\n  .col-sm-push-10 { left: percentage((10/ @grid-columns)); }\n  .col-sm-push-11 { left: percentage((11/ @grid-columns)); }\n\n  .col-sm-pull-1  { right: percentage((1 / @grid-columns)); }\n  .col-sm-pull-2  { right: percentage((2 / @grid-columns)); }\n  .col-sm-pull-3  { right: percentage((3 / @grid-columns)); }\n  .col-sm-pull-4  { right: percentage((4 / @grid-columns)); }\n  .col-sm-pull-5  { right: percentage((5 / @grid-columns)); }\n  .col-sm-pull-6  { right: percentage((6 / @grid-columns)); }\n  .col-sm-pull-7  { right: percentage((7 / @grid-columns)); }\n  .col-sm-pull-8  { right: percentage((8 / @grid-columns)); }\n  .col-sm-pull-9  { right: percentage((9 / @grid-columns)); }\n  .col-sm-pull-10 { right: percentage((10/ @grid-columns)); }\n  .col-sm-pull-11 { right: percentage((11/ @grid-columns)); }\n\n  // Offsets\n  .col-sm-offset-1  { margin-left: percentage((1 / @grid-columns)); }\n  .col-sm-offset-2  { margin-left: percentage((2 / @grid-columns)); }\n  .col-sm-offset-3  { margin-left: percentage((3 / @grid-columns)); }\n  .col-sm-offset-4  { margin-left: percentage((4 / @grid-columns)); }\n  .col-sm-offset-5  { margin-left: percentage((5 / @grid-columns)); }\n  .col-sm-offset-6  { margin-left: percentage((6 / @grid-columns)); }\n  .col-sm-offset-7  { margin-left: percentage((7 / @grid-columns)); }\n  .col-sm-offset-8  { margin-left: percentage((8 / @grid-columns)); }\n  .col-sm-offset-9  { margin-left: percentage((9 / @grid-columns)); }\n  .col-sm-offset-10 { margin-left: percentage((10/ @grid-columns)); }\n  .col-sm-offset-11 { margin-left: percentage((11/ @grid-columns)); }\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n//\n// Note that `.col-md-12` doesn't get floated on purpose—there's no need since\n// it's full-width.\n\n@media (min-width: @screen-desktop) {\n  .container {\n    max-width: @container-desktop;\n  }\n  .col-md-1,\n  .col-md-2,\n  .col-md-3,\n  .col-md-4,\n  .col-md-5,\n  .col-md-6,\n  .col-md-7,\n  .col-md-8,\n  .col-md-9,\n  .col-md-10,\n  .col-md-11 {\n    float: left;\n  }\n  .col-md-1  { width: percentage((1 / @grid-columns)); }\n  .col-md-2  { width: percentage((2 / @grid-columns)); }\n  .col-md-3  { width: percentage((3 / @grid-columns)); }\n  .col-md-4  { width: percentage((4 / @grid-columns)); }\n  .col-md-5  { width: percentage((5 / @grid-columns)); }\n  .col-md-6  { width: percentage((6 / @grid-columns)); }\n  .col-md-7  { width: percentage((7 / @grid-columns)); }\n  .col-md-8  { width: percentage((8 / @grid-columns)); }\n  .col-md-9  { width: percentage((9 / @grid-columns)); }\n  .col-md-10 { width: percentage((10/ @grid-columns)); }\n  .col-md-11 { width: percentage((11/ @grid-columns)); }\n  .col-md-12 { width: 100%; }\n\n  // Push and pull columns for source order changes\n  .col-md-push-0  { left: auto; }\n  .col-md-push-1  { left: percentage((1 / @grid-columns)); }\n  .col-md-push-2  { left: percentage((2 / @grid-columns)); }\n  .col-md-push-3  { left: percentage((3 / @grid-columns)); }\n  .col-md-push-4  { left: percentage((4 / @grid-columns)); }\n  .col-md-push-5  { left: percentage((5 / @grid-columns)); }\n  .col-md-push-6  { left: percentage((6 / @grid-columns)); }\n  .col-md-push-7  { left: percentage((7 / @grid-columns)); }\n  .col-md-push-8  { left: percentage((8 / @grid-columns)); }\n  .col-md-push-9  { left: percentage((9 / @grid-columns)); }\n  .col-md-push-10 { left: percentage((10/ @grid-columns)); }\n  .col-md-push-11 { left: percentage((11/ @grid-columns)); }\n\n  .col-md-pull-0  { right: auto; }\n  .col-md-pull-1  { right: percentage((1 / @grid-columns)); }\n  .col-md-pull-2  { right: percentage((2 / @grid-columns)); }\n  .col-md-pull-3  { right: percentage((3 / @grid-columns)); }\n  .col-md-pull-4  { right: percentage((4 / @grid-columns)); }\n  .col-md-pull-5  { right: percentage((5 / @grid-columns)); }\n  .col-md-pull-6  { right: percentage((6 / @grid-columns)); }\n  .col-md-pull-7  { right: percentage((7 / @grid-columns)); }\n  .col-md-pull-8  { right: percentage((8 / @grid-columns)); }\n  .col-md-pull-9  { right: percentage((9 / @grid-columns)); }\n  .col-md-pull-10 { right: percentage((10/ @grid-columns)); }\n  .col-md-pull-11 { right: percentage((11/ @grid-columns)); }\n\n  // Offsets\n  .col-md-offset-0  { margin-left: 0; }\n  .col-md-offset-1  { margin-left: percentage((1 / @grid-columns)); }\n  .col-md-offset-2  { margin-left: percentage((2 / @grid-columns)); }\n  .col-md-offset-3  { margin-left: percentage((3 / @grid-columns)); }\n  .col-md-offset-4  { margin-left: percentage((4 / @grid-columns)); }\n  .col-md-offset-5  { margin-left: percentage((5 / @grid-columns)); }\n  .col-md-offset-6  { margin-left: percentage((6 / @grid-columns)); }\n  .col-md-offset-7  { margin-left: percentage((7 / @grid-columns)); }\n  .col-md-offset-8  { margin-left: percentage((8 / @grid-columns)); }\n  .col-md-offset-9  { margin-left: percentage((9 / @grid-columns)); }\n  .col-md-offset-10 { margin-left: percentage((10/ @grid-columns)); }\n  .col-md-offset-11 { margin-left: percentage((11/ @grid-columns)); }\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n//\n// Note that `.col-lg-12` doesn't get floated on purpose—there's no need since\n// it's full-width.\n\n@media (min-width: @screen-large-desktop) {\n  .container {\n    max-width: @container-large-desktop;\n  }\n\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11 {\n    float: left;\n  }\n  .col-lg-1  { width: percentage((1 / @grid-columns)); }\n  .col-lg-2  { width: percentage((2 / @grid-columns)); }\n  .col-lg-3  { width: percentage((3 / @grid-columns)); }\n  .col-lg-4  { width: percentage((4 / @grid-columns)); }\n  .col-lg-5  { width: percentage((5 / @grid-columns)); }\n  .col-lg-6  { width: percentage((6 / @grid-columns)); }\n  .col-lg-7  { width: percentage((7 / @grid-columns)); }\n  .col-lg-8  { width: percentage((8 / @grid-columns)); }\n  .col-lg-9  { width: percentage((9 / @grid-columns)); }\n  .col-lg-10 { width: percentage((10/ @grid-columns)); }\n  .col-lg-11 { width: percentage((11/ @grid-columns)); }\n  .col-lg-12 { width: 100%; }\n\n  // Push and pull columns for source order changes\n  .col-lg-push-0  { left: auto; }\n  .col-lg-push-1  { left: percentage((1 / @grid-columns)); }\n  .col-lg-push-2  { left: percentage((2 / @grid-columns)); }\n  .col-lg-push-3  { left: percentage((3 / @grid-columns)); }\n  .col-lg-push-4  { left: percentage((4 / @grid-columns)); }\n  .col-lg-push-5  { left: percentage((5 / @grid-columns)); }\n  .col-lg-push-6  { left: percentage((6 / @grid-columns)); }\n  .col-lg-push-7  { left: percentage((7 / @grid-columns)); }\n  .col-lg-push-8  { left: percentage((8 / @grid-columns)); }\n  .col-lg-push-9  { left: percentage((9 / @grid-columns)); }\n  .col-lg-push-10 { left: percentage((10/ @grid-columns)); }\n  .col-lg-push-11 { left: percentage((11/ @grid-columns)); }\n\n  .col-lg-pull-0  { right: auto; }\n  .col-lg-pull-1  { right: percentage((1 / @grid-columns)); }\n  .col-lg-pull-2  { right: percentage((2 / @grid-columns)); }\n  .col-lg-pull-3  { right: percentage((3 / @grid-columns)); }\n  .col-lg-pull-4  { right: percentage((4 / @grid-columns)); }\n  .col-lg-pull-5  { right: percentage((5 / @grid-columns)); }\n  .col-lg-pull-6  { right: percentage((6 / @grid-columns)); }\n  .col-lg-pull-7  { right: percentage((7 / @grid-columns)); }\n  .col-lg-pull-8  { right: percentage((8 / @grid-columns)); }\n  .col-lg-pull-9  { right: percentage((9 / @grid-columns)); }\n  .col-lg-pull-10 { right: percentage((10/ @grid-columns)); }\n  .col-lg-pull-11 { right: percentage((11/ @grid-columns)); }\n\n  // Offsets\n  .col-lg-offset-0  { margin-left: 0; }\n  .col-lg-offset-1  { margin-left: percentage((1 / @grid-columns)); }\n  .col-lg-offset-2  { margin-left: percentage((2 / @grid-columns)); }\n  .col-lg-offset-3  { margin-left: percentage((3 / @grid-columns)); }\n  .col-lg-offset-4  { margin-left: percentage((4 / @grid-columns)); }\n  .col-lg-offset-5  { margin-left: percentage((5 / @grid-columns)); }\n  .col-lg-offset-6  { margin-left: percentage((6 / @grid-columns)); }\n  .col-lg-offset-7  { margin-left: percentage((7 / @grid-columns)); }\n  .col-lg-offset-8  { margin-left: percentage((8 / @grid-columns)); }\n  .col-lg-offset-9  { margin-left: percentage((9 / @grid-columns)); }\n  .col-lg-offset-10 { margin-left: percentage((10/ @grid-columns)); }\n  .col-lg-offset-11 { margin-left: percentage((11/ @grid-columns)); }\n}\n"
  },
  {
    "path": "site/less/input-groups.less",
    "content": "//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n  position: relative; // For dropdowns\n  display: table;\n  border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n  // Undo padding and float of grid classes\n  &.col {\n    float: none;\n    padding-left: 0;\n    padding-right: 0;\n  }\n\n  .form-control {\n    width: 100%;\n    margin-bottom: 0;\n  }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn { .input-lg(); }\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn { .input-sm(); }\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n\n  &:not(:first-child):not(:last-child) {\n    border-radius: 0;\n  }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n  padding: @padding-base-vertical @padding-base-horizontal;\n  font-size: @font-size-base;\n  font-weight: normal;\n  line-height: 1;\n  text-align: center;\n  background-color: @input-group-addon-bg;\n  border: 1px solid @input-group-addon-border-color;\n  border-radius: @border-radius-base;\n\n  // Sizing\n  &.input-sm {\n    padding: @padding-small-vertical @padding-small-horizontal;\n    font-size: @font-size-small;\n    border-radius: @border-radius-small;\n  }\n  &.input-lg {\n    padding: @padding-large-vertical @padding-large-horizontal;\n    font-size: @font-size-large;\n    border-radius: @border-radius-large;\n  }\n\n  // Nuke default margins from checkboxes and radios to vertically center within.\n  input[type=\"radio\"],\n  input[type=\"checkbox\"] {\n    margin-top: 0;\n  }\n}\n\n// Reset rounded corners\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 > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  .border-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 > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n  .border-left-radius(0);\n}\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n.input-group-btn > .btn {\n  position: relative;\n  // Jankily prevent input button groups from wrapping\n  + .btn {\n    margin-left: -4px;\n  }\n  // Bring the \"active\" button to the front\n  &:hover,\n  &:active {\n    z-index: 2;\n  }\n}\n"
  },
  {
    "path": "site/less/jumbotron.less",
    "content": "//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  font-size: (@font-size-base * 1.5);\n  font-weight: 200;\n  line-height: (@line-height-base * 1.5);\n  color: @jumbotron-lead-color;\n  background-color: @jumbotron-bg;\n  h1 {\n    line-height: 1;\n    color: @jumbotron-heading-color;\n  }\n  p {\n    line-height: 1.4;\n  }\n\n  @media screen and (min-width: @screen-tablet) {\n    padding: 50px 60px;\n    border-radius: @border-radius-large; // Only round corners at higher resolutions\n    h1 {\n      font-size: (@font-size-base * 4.5);\n    }\n  }\n}\n"
  },
  {
    "path": "site/less/labels.less",
    "content": "//\n// Labels\n// --------------------------------------------------\n\n.label {\n  display: inline;\n  padding: .25em .6em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: @label-color;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n\n  // Add hover effects, but only for links\n  &[href] {\n    &:hover,\n    &:focus {\n      color: @label-link-hover-color;\n      text-decoration: none;\n      cursor: pointer;\n    }\n  }\n\n  // Empty labels collapse automatically (not available in IE8)\n  &:empty {\n    display: none;\n  }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n  .label-variant(@label-default-bg);\n}\n\n.label-primary {\n  .label-variant(@label-primary-bg);\n}\n\n.label-success {\n  .label-variant(@label-success-bg);\n}\n\n.label-info {\n  .label-variant(@label-info-bg);\n}\n\n.label-warning {\n  .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n  .label-variant(@label-danger-bg);\n}\n"
  },
  {
    "path": "site/less/list-group.less",
    "content": "//\n// List groups\n// --------------------------------------------------\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n.list-group {\n  // No need to set list-style: none; since .list-group-item is block level\n  margin-bottom: 20px;\n  padding-left: 0; // reset padding because ul and ol\n}\n\n// Individual list items\n// -------------------------\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  // Place the border on the list items and negative margin up for better styling\n  margin-bottom: -1px;\n  background-color: @list-group-bg;\n  border: 1px solid @list-group-border;\n\n  // Round the first and last items\n  &:first-child {\n    .border-top-radius(@list-group-border-radius);\n  }\n  &:last-child {\n    margin-bottom: 0;\n    .border-bottom-radius(@list-group-border-radius);\n  }\n\n  // Align badges within list items\n  > .badge {\n    float: right;\n  }\n  > .badge + .badge {\n    margin-right: 5px;\n  }\n\n  // Linked list items\n  a& {\n    color: @list-group-link-color;\n\n    .list-group-item-heading {\n      color: @list-group-link-heading-color;\n    }\n\n    // Hover state\n    &:hover,\n    &:focus {\n      text-decoration: none;\n      background-color: @list-group-hover-bg;\n    }\n  }\n\n  // Active class on item itself, not parent\n  &.active,\n  &.active:hover,\n  &.active:focus {\n    z-index: 2; // Place active items above their siblings for proper border styling\n    color: @list-group-active-color;\n    background-color: @list-group-active-bg;\n    border-color: @list-group-active-border;\n\n    // Force color to inherit for custom content\n    .list-group-item-heading {\n      color: inherit;\n    }\n    .list-group-item-text {\n      color: lighten(@list-group-active-bg, 40%);\n    }\n  }\n}\n\n// Custom content options\n// -------------------------\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"
  },
  {
    "path": "site/less/media.less",
    "content": "// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n  display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n  margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n  > .pull-left {\n    margin-right: 10px;\n  }\n  > .pull-right {\n    margin-left: 10px;\n  }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n"
  },
  {
    "path": "site/less/mixins.less",
    "content": "//\n// Mixins\n// --------------------------------------------------\n\n\n// Utilities\n// -------------------------\n\n// Clearfix\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n//    contenteditable attribute is included anywhere else in the document.\n//    Otherwise it causes space to appear at the top and bottom of elements\n//    that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n//    `:before` to contain the top-margins of child elements.\n.clearfix() {\n  &:before,\n  &:after {\n    content: \" \"; /* 1 */\n    display: table; /* 2 */\n  }\n  &:after {\n    clear: both;\n  }\n}\n\n// Webkit-style focus\n.tab-focus() {\n  // Default\n  outline: thin dotted #333;\n  // Webkit\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n// Center-align a block level element\n.center-block() {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n\n// Sizing shortcuts\n.size(@width; @height) {\n  width: @width;\n  height: @height;\n}\n.square(@size) {\n  .size(@size; @size);\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n  &:-moz-placeholder            { color: @color; } // Firefox 4-18\n  &::-moz-placeholder           { color: @color; } // Firefox 19+\n  &:-ms-input-placeholder       { color: @color; } // Internet Explorer 10+\n  &::-webkit-input-placeholder  { color: @color; } // Safari and Chrome\n}\n\n// Text overflow\n// Requires inline-block or block for proper styling\n.text-overflow() {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n// CSS image replacement\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n.hide-text() {\n  font: ~\"0/0\" a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n\n\n// CSS3 PROPERTIES\n// --------------------------------------------------\n\n// Single side border-radius\n.border-top-radius(@radius) {\n  border-top-right-radius: @radius;\n   border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n  border-bottom-right-radius: @radius;\n     border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n  border-bottom-right-radius: @radius;\n   border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n  border-bottom-left-radius: @radius;\n     border-top-left-radius: @radius;\n}\n\n// Drop shadows\n.box-shadow(@shadow) {\n  -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n          box-shadow: @shadow;\n}\n\n// Transitions\n.transition(@transition) {\n  -webkit-transition: @transition;\n          transition: @transition;\n}\n.transition-delay(@transition-delay) {\n  -webkit-transition-delay: @transition-delay;\n          transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n  -webkit-transition-duration: @transition-duration;\n          transition-duration: @transition-duration;\n}\n.transition-transform(@transition) {\n  -webkit-transition: -webkit-transform @transition;\n     -moz-transition: -moz-transform @transition;\n       -o-transition: -o-transform @transition;\n          transition: transform @transition;\n}\n\n// Transformations\n.rotate(@degrees) {\n  -webkit-transform: rotate(@degrees);\n      -ms-transform: rotate(@degrees); // IE9+\n          transform: rotate(@degrees);\n}\n.scale(@ratio) {\n  -webkit-transform: scale(@ratio);\n      -ms-transform: scale(@ratio); // IE9+\n          transform: scale(@ratio);\n}\n.translate(@x; @y) {\n  -webkit-transform: translate(@x, @y);\n      -ms-transform: translate(@x, @y); // IE9+\n          transform: translate(@x, @y);\n}\n.skew(@x; @y) {\n  -webkit-transform: skew(@x, @y);\n      -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n          transform: skew(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n  -webkit-transform: translate3d(@x, @y, @z);\n          transform: translate3d(@x, @y, @z);\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n// See git pull https://github.com/dannykeane/bootstrap.git backface-visibility for examples\n.backface-visibility(@visibility){\n  -webkit-backface-visibility: @visibility;\n     -moz-backface-visibility: @visibility;\n          backface-visibility: @visibility;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n  -webkit-box-sizing: @boxmodel;\n     -moz-box-sizing: @boxmodel;\n          box-sizing: @boxmodel;\n}\n\n// User select\n// For selecting text on the page\n.user-select(@select) {\n  -webkit-user-select: @select;\n     -moz-user-select: @select;\n      -ms-user-select: @select; // IE10+\n       -o-user-select: @select;\n          user-select: @select;\n}\n\n// Resize anything\n.resizable(@direction) {\n  resize: @direction; // Options: horizontal, vertical, both\n  overflow: auto; // Safari fix\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n  -webkit-column-count: @column-count;\n     -moz-column-count: @column-count;\n          column-count: @column-count;\n  -webkit-column-gap: @column-gap;\n     -moz-column-gap: @column-gap;\n          column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n  word-wrap: break-word;\n  -webkit-hyphens: @mode;\n     -moz-hyphens: @mode;\n      -ms-hyphens: @mode; // IE10+\n       -o-hyphens: @mode;\n          hyphens: @mode;\n}\n\n// Opacity\n.opacity(@opacity) {\n  opacity: @opacity;\n  // IE8 filter\n  @opacity-ie: (@opacity * 100);\n  filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n\n\n\n// GRADIENTS\n// --------------------------------------------------\n\n#gradient {\n\n  // Horizontal gradient, from left to right\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-gradient(linear, @start-percent top, @end-percent top, from(@start-color), to(@end-color)); // Safari 4+, Chrome 2+\n    background-image: -webkit-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1+, Chrome 10+\n    background-image: -moz-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // FF 3.6+\n    background-image:  linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  // Vertical gradient, from top to bottom\n  //\n  // Creates two color stops, start and end, by specifying a color and position for each color stop.\n  // Color stops are not available in IE9 and below.\n  .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n    background-image: -webkit-gradient(linear, left @start-percent, left @end-percent, from(@start-color), to(@end-color)); // Safari 4+, Chrome 2+\n    background-image: -webkit-linear-gradient(top, @start-color, @start-percent, @end-color, @end-percent); // Safari 5.1+, Chrome 10+\n    background-image:  -moz-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // FF 3.6+\n    background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10\n    background-repeat: repeat-x;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n  }\n\n  .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n    background-repeat: repeat-x;\n    background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1+, Chrome 10+\n    background-image: -moz-linear-gradient(@deg, @start-color, @end-color); // FF 3.6+\n    background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10\n  }\n  .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-gradient(left, linear, 0 0, 0 100%, from(@start-color), color-stop(@color-stop, @mid-color), to(@end-color));\n    background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: -moz-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@start-color), color-stop(@color-stop, @mid-color), to(@end-color));\n    background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-image: -moz-linear-gradient(top, @start-color, @mid-color @color-stop, @end-color);\n    background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n    background-repeat: no-repeat;\n    filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n  }\n  .radial(@inner-color: #555; @outer-color: #333) {\n    background-image: -webkit-gradient(radial, center center, 0, center center, 460, from(@inner-color), to(@outer-color));\n    background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n    background-image: -moz-radial-gradient(circle, @inner-color, @outer-color);\n    background-image: radial-gradient(circle, @inner-color, @outer-color);\n    background-repeat: no-repeat;\n  }\n  .striped(@color: #555; @angle: 45deg) {\n    background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,.15)), color-stop(.75, rgba(255,255,255,.15)), color-stop(.75, transparent), to(transparent));\n    background-image: -webkit-linear-gradient(@angle, 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: -moz-linear-gradient(@angle, 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(@angle, 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}\n\n// Reset filters for IE\n//\n// When you need to remove a gradient background, don't forget to use this to reset\n// the IE filter for IE9 and below.\n.reset-filter() {\n  filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n\n\n\n// Retina images\n//\n// Short retina mixin for setting background-image and -size\n\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n  background-image: url(\"@{file-1x}\");\n\n  @media\n  only screen and (-webkit-min-device-pixel-ratio: 2),\n  only screen and (   min--moz-device-pixel-ratio: 2),\n  only screen and (     -o-min-device-pixel-ratio: 2/1),\n  only screen and (        min-device-pixel-ratio: 2),\n  only screen and (                min-resolution: 192dpi),\n  only screen and (                min-resolution: 2dppx) {\n    background-image: url(\"@{file-2x}\");\n    background-size: @width-1x @height-1x;\n  }\n}\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n.img-responsive(@display: block;) {\n  display: @display;\n  max-width: 100%; // Part 1: Set a maximum relative to the parent\n  height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// COMPONENT MIXINS\n// --------------------------------------------------\n\n// Horizontal dividers\n// -------------------------\n// Dividers (basically an hr) within dropdowns and nav lists\n.nav-divider(@color: #e5e5e5) {\n  height: 1px;\n  margin: ((@line-height-computed / 2) - 1) 0;\n  overflow: hidden;\n  background-color: @color;\n}\n\n// Panels\n// -------------------------\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n  border-color: @border;\n  & > .panel-heading {\n    color: @heading-text-color;\n    background-color: @heading-bg-color;\n    border-color: @heading-border;\n    + .panel-collapse .panel-body {\n      border-top-color: @border;\n    }\n  }\n  & > .panel-footer {\n    + .panel-collapse .panel-body {\n      border-bottom-color: @border;\n    }\n  }\n}\n\n// Alerts\n// -------------------------\n.alert-variant(@background; @border; @text-color) {\n  background-color: @background;\n  border-color: @border;\n  color: @text-color;\n  hr {\n    border-top-color: darken(@border, 5%);\n  }\n  .alert-link {\n    color: darken(@text-color, 10%);\n  }\n}\n\n// Tables\n// -------------------------\n.table-row-variant(@state; @background; @border) {\n  // Exact selectors below required to override `.table-striped` and prevent\n  // inheritance to nested tables.\n  .table > thead > tr,\n  .table > tbody > tr,\n  .table > tfoot > tr {\n    > td.@{state},\n    > th.@{state},\n    &.@{state} > td,\n    &.@{state} > th {\n      background-color: @background;\n      border-color: @border;\n    }\n  }\n\n  // Hover states for `.table-hover`\n  // Note: this is not available for cells or rows within `thead` or `tfoot`.\n  .table-hover > tbody > tr {\n    > td.@{state}:hover,\n    > th.@{state}:hover,\n    &.@{state}:hover > td {\n      background-color: darken(@background, 5%);\n      border-color: darken(@border, 5%);\n    }\n  }\n}\n\n// Button variants\n// -------------------------\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n.button-variant(@color; @background; @border) {\n  color: @color;\n  background-color: @background;\n  border-color: @border;\n\n  &:hover,\n  &:focus,\n  &:active,\n  &.active,\n  .open .dropdown-toggle& {\n    color: @color;\n    background-color: darken(@background, 8%);\n        border-color: darken(@border, 12%);\n  }\n  &:active,\n  &.active,\n  .open .dropdown-toggle& {\n    background-image: none;\n  }\n  &.disabled,\n  &[disabled],\n  fieldset[disabled] & {\n    &,\n    &:hover,\n    &:focus,\n    &:active,\n    &.active {\n      background-color: @background;\n          border-color: @border\n    }\n  }\n}\n\n// Button sizes\n// -------------------------\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n  padding: @padding-vertical @padding-horizontal;\n  font-size: @font-size;\n  line-height: @line-height;\n  border-radius: @border-radius;\n}\n\n// Pagination\n// -------------------------\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n  > li {\n    > a,\n    > span {\n      padding: @padding-vertical @padding-horizontal;\n      font-size: @font-size;\n    }\n    &:first-child {\n      > a,\n      > span {\n        .border-left-radius(@border-radius);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        .border-right-radius(@border-radius);\n      }\n    }\n  }\n}\n\n// Labels\n// -------------------------\n.label-variant(@color) {\n  background-color: @color;\n  &[href] {\n    &:hover,\n    &:focus {\n      background-color: darken(@color, 10%);\n    }\n  }\n}\n\n// Navbar vertical align\n// -------------------------\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n.navbar-vertical-align(@element-height) {\n  margin-top: ((@navbar-height - @element-height) / 2);\n  margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n\n// Progress bars\n// -------------------------\n.progress-bar-variant(@color) {\n  background-color: @color;\n  .progress-striped & {\n    #gradient > .striped(@color);\n  }\n}\n\n// Responsive utilities\n// -------------------------\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n  display: block !important;\n  tr& { display: table-row !important; }\n  th&,\n  td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n  display: none !important;\n  tr& { display: none !important; }\n  th&,\n  td& { display: none !important; }\n}\n\n// Grid System\n// -----------\n\n// Centered container element\n.container-fixed() {\n  margin-right: auto;\n  margin-left: auto;\n  .clearfix();\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n  // Then clear the floated columns\n  .clearfix();\n\n  .container & {\n    @media (min-width: @screen-small) {\n      margin-left:  (@gutter / -2);\n      margin-right: (@gutter / -2);\n    }\n  }\n\n  // Negative margin nested rows out to align the content of columns\n  .row {\n    margin-left:  (@gutter / -2);\n    margin-right: (@gutter / -2);\n  }\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  float: left;\n  width: percentage((@columns / @grid-columns));\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: @screen-small) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the small column offsets\n.make-sm-column-offset(@columns) {\n  @media (min-width: @screen-small) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-push(@columns) {\n  @media (min-width: @screen-small) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-sm-column-pull(@columns) {\n  @media (min-width: @screen-small) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: @screen-medium) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large column offsets\n.make-md-column-offset(@columns) {\n  @media (min-width: @screen-medium) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-push(@columns) {\n  @media (min-width: @screen-medium) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-md-column-pull(@columns) {\n  @media (min-width: @screen-medium) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n  position: relative;\n  // Prevent columns from collapsing when empty\n  min-height: 1px;\n  // Inner gutter via padding\n  padding-left:  (@gutter / 2);\n  padding-right: (@gutter / 2);\n\n  // Calculate width based on number of columns available\n  @media (min-width: @screen-large) {\n    float: left;\n    width: percentage((@columns / @grid-columns));\n  }\n}\n\n// Generate the large column offsets\n.make-lg-column-offset(@columns) {\n  @media (min-width: @screen-large) {\n    margin-left: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-push(@columns) {\n  @media (min-width: @screen-large) {\n    left: percentage((@columns / @grid-columns));\n  }\n}\n.make-lg-column-pull(@columns) {\n  @media (min-width: @screen-large) {\n    right: percentage((@columns / @grid-columns));\n  }\n}\n\n\n// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n  // Color the label and help text\n  .help-block,\n  .control-label {\n    color: @text-color;\n  }\n  // Set the border and box shadow on specific inputs to match\n  .form-control {\n    border-color: @border-color;\n    .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n    &:focus {\n      border-color: darken(@border-color, 10%);\n      @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n      .box-shadow(@shadow);\n    }\n  }\n  // Set validation states also for addons\n  .input-group-addon {\n    color: @text-color;\n    border-color: @border-color;\n    background-color: @background-color;\n  }\n}\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-focus-border` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n\n.form-control-focus(@color: @input-border-focus) {\n  @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n  &:focus {\n    border-color: @color;\n    outline: 0;\n    .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n  }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n  height: @input-height;\n  padding: @padding-vertical @padding-horizontal;\n  font-size: @font-size;\n  line-height: @line-height;\n  border-radius: @border-radius;\n\n  select& {\n    height: @input-height;\n    line-height: @input-height;\n  }\n\n  textarea& {\n    height: auto;\n  }\n}\n"
  },
  {
    "path": "site/less/modals.less",
    "content": "//\n// Modals\n// --------------------------------------------------\n\n// .modal-open      - body class for killing the scroll\n// .modal           - container to scroll within\n// .modal-dialog    - positioning shell for the actual modal\n// .modal-content   - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n  overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindex-modal-background;\n\n  // When fading in the modal, animate it to slide down\n  &.fade .modal-dialog {\n    .translate(0, -25%);\n    .transition-transform(~\"0.3s ease-out\");\n  }\n  &.in .modal-dialog { .translate(0, 0)}\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n  margin-left: auto;\n  margin-right: auto;\n  width: auto;\n  padding: 10px;\n  z-index: (@zindex-modal-background + 10);\n}\n\n// Actual modal\n.modal-content {\n  position: relative;\n  background-color: @modal-content-bg;\n  border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n  border: 1px solid @modal-content-border-color;\n  border-radius: @border-radius-large;\n  .box-shadow(0 3px 9px rgba(0,0,0,.5));\n  background-clip: padding-box;\n  // Remove focus outline from opened modal\n  outline: none;\n}\n\n// Modal background\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: (@zindex-modal-background - 10);\n  background-color: @modal-backdrop-bg;\n  // Fade for backdrop\n  &.fade { .opacity(0); }\n  &.in { .opacity(.5); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n  padding: @modal-title-padding;\n  border-bottom: 1px solid @modal-header-border-color;\n  min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n  margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n  margin: 0;\n  line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n  position: relative;\n  padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n  margin-top: 15px;\n  padding: (@modal-inner-padding - 1) @modal-inner-padding @modal-inner-padding;\n  text-align: right; // right align buttons\n  border-top: 1px solid @modal-footer-border-color;\n  .clearfix(); // clear it in case folks use .pull-* classes on buttons\n\n  // Properly space out buttons\n  .btn + .btn {\n    margin-left: 5px;\n    margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n  }\n  // but override that for button groups\n  .btn-group .btn + .btn {\n    margin-left: -1px;\n  }\n  // and override it for block buttons as well\n  .btn-block + .btn-block {\n    margin-left: 0;\n  }\n}\n\n// Scale up the modal\n@media screen and (min-width: @screen-tablet) {\n\n  .modal-dialog {\n    left: 50%;\n    right: auto;\n    width: 600px;\n    padding-top: 30px;\n    padding-bottom: 30px;\n  }\n  .modal-content {\n    .box-shadow(0 5px 15px rgba(0,0,0,.5));\n  }\n\n}\n"
  },
  {
    "path": "site/less/navbar.less",
    "content": "//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n  position: relative;\n  min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n  margin-bottom: @navbar-margin-bottom;\n  background-color: @navbar-bg;\n  border: 1px solid @navbar-border;\n\n  // Prevent floats from breaking the navbar\n  .clearfix();\n\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: @navbar-border-radius;\n  }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n  padding-left:  @navbar-padding-horizontal;\n  padding-right: @navbar-padding-horizontal;\n  .clearfix();\n\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n  }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n  padding-right: @navbar-padding-horizontal;\n  padding-left:  @navbar-padding-horizontal;\n  border-top: 1px solid darken(@navbar-bg, 7%);\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n  // Clear floated elements and prevent collapsing of padding\n  .clearfix();\n\n  // This is not automatically added to the `.navbar-fixed-top` because it causes\n  // z-index bugs in iOS7 (possibly earlier).\n  max-height: 340px;\n  overflow-x: visible;\n  overflow-y: auto;\n  -webkit-overflow-scrolling: touch;\n\n  @media (min-width: @grid-float-breakpoint) {\n    width: auto;\n    padding-right: 0;\n    padding-left:  0;\n    border-top: 0;\n    box-shadow: none;\n\n    &.collapse {\n      display: block !important;\n      height: auto !important;\n      padding-bottom: 0; // Override default setting\n      overflow: visible !important;\n    }\n\n    &.in {\n      overflow-y: visible;\n    }\n  }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirity of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n  border-width: 0 0 1px;\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: @zindex-navbar-fixed;\n  border-width: 0 0 1px;\n\n  // Undo the rounded corners\n  @media (min-width: @grid-float-breakpoint) {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top {\n  top: 0;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0; // override .navbar defaults\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n  float: left;\n  padding-top: @navbar-padding-vertical;\n  padding-bottom: @navbar-padding-vertical;\n  font-size: @font-size-large;\n  line-height: @line-height-computed;\n  color: @navbar-brand-color;\n  &:hover,\n  &:focus {\n    color: @navbar-brand-hover-color;\n    text-decoration: none;\n    background-color: @navbar-brand-hover-bg;\n  }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  padding: 9px 10px;\n  .navbar-vertical-align(34px);\n  background-color: transparent;\n  border: 1px solid @navbar-toggle-border-color;\n  border-radius: @border-radius-base;\n\n  &:hover,\n  &:focus {\n    background-color: @navbar-toggle-hover-bg;\n  }\n\n  // Bars\n  .icon-bar {\n    display: block;\n    width: 22px;\n    height: 2px;\n    background-color: @navbar-toggle-icon-bar-bg;\n    border-radius: 1px;\n  }\n  .icon-bar + .icon-bar {\n    margin-top: 4px;\n  }\n\n  @media (min-width: @grid-float-breakpoint) {\n    position: relative;\n    top: auto;\n    left: auto;\n    display: none;\n  }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with it's own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n  margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n  > li > a {\n    padding-top:    10px;\n    padding-bottom: 10px;\n    color: @navbar-link-color;\n    line-height: @line-height-computed;\n    &:hover,\n    &:focus {\n      color: @navbar-link-hover-color;\n      background-color: @navbar-link-hover-bg;\n    }\n  }\n  > .active > a {\n    &,\n    &:hover,\n    &:focus {\n      color: @navbar-link-active-color;\n      background-color: @navbar-link-active-bg;\n    }\n  }\n  > .disabled > a {\n    &,\n    &:hover,\n    &:focus {\n      color: @navbar-link-disabled-color;\n      background-color: @navbar-link-disabled-bg;\n    }\n  }\n\n  @media (max-width: @screen-phone-max) {\n    // Dropdowns get custom display when collapsed\n    .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      > li > a,\n      .dropdown-header {\n        padding: 5px 15px 5px 25px;\n      }\n      > li > a {\n        color: @navbar-link-color;\n        line-height: @line-height-computed;\n        &:hover,\n        &:focus {\n          color: @navbar-link-hover-color;\n          background-color: @navbar-link-hover-bg;\n          background-image: none;\n        }\n      }\n      > .active > a {\n        &,\n        &:hover,\n        &:focus {\n          color: @navbar-link-active-color;\n          background-color: @navbar-link-active-bg;\n        }\n      }\n      > .disabled > a {\n        &,\n        &:hover,\n        &:focus {\n          color: @navbar-link-disabled-color;\n          background-color: @navbar-link-disabled-bg;\n        }\n      }\n    }\n  }\n\n  // Uncollapse the nav\n  @media (min-width: @grid-float-breakpoint) {\n    float: left;\n    margin: 0;\n\n    > li {\n      float: left;\n      > a {\n        padding-top: ((@navbar-height - @line-height-computed) / 2);\n        padding-bottom: ((@navbar-height - @line-height-computed) / 2);\n      }\n    }\n  }\n\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specifity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n  .navbar-left  { .pull-left(); }\n  .navbar-right {\n    .pull-right();\n    .dropdown-menu {\n      .pull-right > .dropdown-menu();\n    }\n  }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n  margin-left: -@navbar-padding-horizontal;\n  margin-right: -@navbar-padding-horizontal;\n  padding: 10px @navbar-padding-horizontal;\n  border-top: 1px solid darken(@navbar-bg, 7%);\n  border-bottom: 1px solid darken(@navbar-bg, 7%);\n  @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n  .box-shadow(@shadow);\n\n  // Mixin behavior for optimum display\n  .form-inline();\n\n  .form-group {\n    @media (max-width: @screen-phone-max) {\n      margin-bottom: 5px;\n    }\n  }\n\n  // Vertically center in expanded, horizontal navbar\n  .navbar-vertical-align(@input-height-base);\n\n  // Undo 100% width for pull classes\n  @media (min-width: @grid-float-breakpoint) {\n    width: auto;\n    border: 0;\n    margin-left: 0;\n    margin-right: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    .box-shadow(none);\n  }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  .border-bottom-radius(0);\n}\n\n// Dropdown menu items and carets\n.navbar-nav {\n  // Caret should match text color on hover\n  > .dropdown > a:hover .caret,\n  > .dropdown > a:focus .caret {\n    border-top-color: @navbar-link-hover-color;\n    border-bottom-color: @navbar-link-hover-color;\n  }\n\n  // Remove background color from open dropdown\n  > .open > a {\n    &,\n    &:hover,\n    &:focus {\n      background-color: @navbar-link-active-bg;\n      color: @navbar-link-active-color;\n      .caret {\n        border-top-color: @navbar-link-active-color;\n        border-bottom-color: @navbar-link-active-color;\n      }\n    }\n  }\n  > .dropdown > a .caret {\n    border-top-color: @navbar-link-color;\n    border-bottom-color: @navbar-link-color;\n  }\n}\n\n// Right aligned menus need alt position\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  left: auto;\n  right: 0;\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n  .navbar-vertical-align(@input-height-base);\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n  float: left;\n  color: @navbar-color;\n  .navbar-vertical-align(@line-height-computed);\n\n  @media (min-width: @grid-float-breakpoint) {\n    margin-left: @navbar-padding-horizontal;\n    margin-right: @navbar-padding-horizontal;\n  }\n}\n\n\n// Links in navbars\n//\n// Add a class to ensure links outside the navbar nav are colored correctly.\n\n// Default navbar variables\n.navbar-link {\n  color: @navbar-link-color;\n  &:hover {\n    color: @navbar-link-hover-color;\n  }\n}\n\n\n// Inverse navbar\n// --------------------------------------------------\n\n.navbar-inverse {\n  background-color: @navbar-inverse-bg;\n  border-color: @navbar-inverse-border;\n\n  .navbar-brand {\n    color: @navbar-inverse-brand-color;\n    &:hover,\n    &:focus {\n      color: @navbar-inverse-brand-hover-color;\n      background-color: @navbar-inverse-brand-hover-bg;\n    }\n  }\n\n  .navbar-text {\n    color: @navbar-inverse-color;\n  }\n\n  .navbar-nav {\n    > li > a {\n      color: @navbar-inverse-link-color;\n\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-hover-color;\n        background-color: @navbar-inverse-link-hover-bg;\n      }\n    }\n    > .active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-active-color;\n        background-color: @navbar-inverse-link-active-bg;\n      }\n    }\n    > .disabled > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @navbar-inverse-link-disabled-color;\n        background-color: @navbar-inverse-link-disabled-bg;\n      }\n    }\n  }\n\n  // Darken the responsive nav toggle\n  .navbar-toggle {\n    border-color: @navbar-inverse-toggle-border-color;\n    &:hover,\n    &:focus {\n      background-color: @navbar-inverse-toggle-hover-bg;\n    }\n    .icon-bar {\n      background-color: @navbar-inverse-toggle-icon-bar-bg;\n    }\n  }\n\n  .navbar-collapse,\n  .navbar-form {\n    border-color: darken(@navbar-inverse-bg, 7%);\n  }\n\n  // Dropdowns\n  .navbar-nav {\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        background-color: @navbar-inverse-link-active-bg;\n        color: @navbar-inverse-link-active-color;\n      }\n    }\n    > .dropdown > a:hover .caret {\n      border-top-color: @navbar-inverse-link-hover-color;\n      border-bottom-color: @navbar-inverse-link-hover-color;\n    }\n    > .dropdown > a .caret {\n      border-top-color: @navbar-inverse-link-color;\n      border-bottom-color: @navbar-inverse-link-color;\n    }\n    > .open > a {\n      &,\n      &:hover,\n      &:focus {\n        .caret {\n          border-top-color: @navbar-inverse-link-active-color;\n          border-bottom-color: @navbar-inverse-link-active-color;\n        }\n      }\n    }\n\n    @media (max-width: @screen-phone-max) {\n      // Dropdowns get custom display\n      .open .dropdown-menu {\n        > .dropdown-header {\n          border-color: @navbar-inverse-border;\n        }\n        > li > a {\n          color: @navbar-inverse-link-color;\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-hover-color;\n            background-color: @navbar-inverse-link-hover-bg;\n          }\n        }\n        > .active > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-active-color;\n            background-color: @navbar-inverse-link-active-bg;\n          }\n        }\n        > .disabled > a {\n          &,\n          &:hover,\n          &:focus {\n            color: @navbar-inverse-link-disabled-color;\n            background-color: @navbar-inverse-link-disabled-bg;\n          }\n        }\n      }\n    }\n  }\n\n  .navbar-link {\n    color: @navbar-inverse-link-color;\n    &:hover {\n      color: @navbar-inverse-link-hover-color;\n    }\n  }\n\n}\n"
  },
  {
    "path": "site/less/navs.less",
    "content": "//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n  margin-bottom: 0;\n  padding-left: 0; // Override default ul/ol\n  list-style: none;\n  .clearfix();\n\n  > li {\n    position: relative;\n    display: block;\n\n    > a {\n      position: relative;\n      display: block;\n      padding: @nav-link-padding;\n      &:hover,\n      &:focus {\n        text-decoration: none;\n        background-color: @nav-link-hover-bg;\n      }\n    }\n\n    // Disabled state sets text to gray and nukes hover/tab effects\n    &.disabled > a {\n      color: @nav-disabled-link-color;\n\n      &:hover,\n      &:focus {\n        color: @nav-disabled-link-hover-color;\n        text-decoration: none;\n        background-color: transparent;\n        cursor: not-allowed;\n      }\n    }\n  }\n\n  // Open dropdowns\n  .open > a {\n    &,\n    &:hover,\n    &:focus {\n      background-color: @nav-link-hover-bg;\n      border-color: @link-color;\n    }\n  }\n\n  // Dividers (basically an hr) within the dropdown\n  .nav-divider {\n    .nav-divider();\n  }\n\n  // Prevent IE8 from misplacing imgs\n  // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n  > li > a > img {\n    max-width: none;\n  }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n  border-bottom: 1px solid @nav-tabs-border-color;\n  > li {\n    float: left;\n    // Make the list-items overlay the bottom border\n    margin-bottom: -1px;\n\n    // Actual tabs (as links)\n    > a {\n      margin-right: 2px;\n      line-height: @line-height-base;\n      border: 1px solid transparent;\n      border-radius: @border-radius-base @border-radius-base 0 0;\n      &:hover {\n        border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n      }\n    }\n\n    // Active state, and it's :hover to override normal :hover\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @nav-tabs-active-link-hover-color;\n        background-color: @nav-tabs-active-link-hover-bg;\n        border: 1px solid @nav-tabs-active-link-hover-border-color;\n        border-bottom-color: transparent;\n        cursor: default;\n      }\n    }\n  }\n  // pulling this in mainly for less shorthand\n  &.nav-justified {\n    .nav-justified();\n    .nav-tabs-justified();\n  }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n  > li {\n    float: left;\n\n    // Links rendered as pills\n    > a {\n      border-radius: 5px;\n    }\n    + li {\n      margin-left: 2px;\n    }\n\n    // Active state\n    &.active > a {\n      &,\n      &:hover,\n      &:focus {\n        color: @nav-pills-active-link-hover-color;\n        background-color: @nav-pills-active-link-hover-bg;\n      }\n    }\n  }\n}\n\n\n// Stacked pills\n.nav-stacked {\n  > li {\n    float: none;\n    + li {\n      margin-top: 2px;\n      margin-left: 0; // no need for this gap between nav items\n    }\n  }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n  width: 100%;\n\n  > li {\n    float: none;\n     > a {\n      text-align: center;\n    }\n  }\n\n  @media (min-width: @screen-small) {\n    > li {\n      display: table-cell;\n      width: 1%;\n    }\n  }\n}\n\n// Move borders to anchors instead of bottom of list\n.nav-tabs-justified {\n  border-bottom: 0;\n  > li > a {\n    border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n\n    // Override margin from .nav-tabs\n    margin-right: 0;\n  }\n  > .active > a {\n    border-bottom-color: @nav-tabs-justified-active-link-border-color;\n  }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Clear any floats\n.tabbable {\n  .clearfix();\n}\n\n// Show/hide tabbable areas\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n.tab-content,\n.pill-content {\n  > .active {\n    display: block;\n  }\n}\n\n\n\n// Dropdowns\n// -------------------------\n\n// Make dropdown carets use link color in navs\n.nav .caret {\n  border-top-color: @link-color;\n  border-bottom-color: @link-color;\n}\n.nav a:hover .caret {\n  border-top-color: @link-hover-color;\n  border-bottom-color: @link-hover-color;\n}\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n  // make dropdown border overlap tab border\n  margin-top: -1px;\n  // Remove the top rounded corners here since there is a hard edge above the menu\n  .border-top-radius(0);\n}\n"
  },
  {
    "path": "site/less/normalize.less",
    "content": "/*! normalize.css v2.1.0 | MIT License | git.io/normalize */\n\n// ==========================================================================\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined in IE 8/9.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\n//\n// Correct `inline-block` display not defined in IE 8/9.\n//\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\n[hidden] {\n  display: none;\n}\n\n// ==========================================================================\n// Base\n// ==========================================================================\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n//    user zoom.\n//\n\nhtml {\n  font-family: sans-serif; // 1\n  -webkit-text-size-adjust: 100%; // 2\n  -ms-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n  margin: 0;\n}\n\n// ==========================================================================\n// Links\n// ==========================================================================\n\n//\n// Address `outline` inconsistency between Chrome and other browsers.\n//\n\na:focus {\n  outline: thin dotted;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n  outline: 0;\n}\n\n// ==========================================================================\n// Typography\n// ==========================================================================\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari 5, and Chrome.\n//\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9, Safari 5, and Chrome.\n//\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.\n//\n\nb,\nstrong {\n  font-weight: bold;\n}\n\n//\n// Address styling not present in Safari 5 and Chrome.\n//\n\ndfn {\n  font-style: italic;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n  background: #ff0;\n  color: #000;\n}\n\n//\n// Correct font family set oddly in Safari 5 and Chrome.\n//\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n\n//\n// Improve readability of pre-formatted text in all browsers.\n//\n\npre {\n  white-space: pre-wrap;\n}\n\n//\n// Set consistent quote types.\n//\n\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n  font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\n// ==========================================================================\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9.\n//\n\nimg {\n  border: 0;\n}\n\n//\n// Correct overflow displayed oddly in IE 9.\n//\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n// ==========================================================================\n// Figures\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari 5.\n//\n\nfigure {\n  margin: 0;\n}\n\n// ==========================================================================\n// Forms\n// ==========================================================================\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n  border: 0; // 1\n  padding: 0; // 2\n}\n\n//\n// 1. Correct font family not being inherited in all browsers.\n// 2. Correct font size not being inherited in all browsers.\n// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n//\n\nbutton,\ninput,\nselect,\ntextarea {\n  font-family: inherit; // 1\n  font-size: 100%; // 2\n  margin: 0; // 3\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\nbutton,\ninput {\n  line-height: normal;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.\n// Correct `select` style inheritance in Firefox 4+ and Opera.\n//\n\nbutton,\nselect {\n  text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n//    and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n//    `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button; // 2\n  cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\n//\n// 1. Address box sizing set to `content-box` in IE 8/9.\n// 2. Remove excess padding in IE 8/9.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box; // 1\n  padding: 0; // 2\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome\n//    (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n  -webkit-appearance: textfield; // 1\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box; // 2\n  box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari 5 and Chrome\n// on OS X.\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\n\n//\n// 1. Remove default vertical scrollbar in IE 8/9.\n// 2. Improve readability and alignment in all browsers.\n//\n\ntextarea {\n  overflow: auto; // 1\n  vertical-align: top; // 2\n}\n\n// ==========================================================================\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n"
  },
  {
    "path": "site/less/pager.less",
    "content": "//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n  padding-left: 0;\n  margin: @line-height-computed 0;\n  list-style: none;\n  text-align: center;\n  .clearfix();\n  li {\n    display: inline;\n    > a,\n    > span {\n      display: inline-block;\n      padding: 5px 14px;\n      background-color: @pagination-bg;\n      border: 1px solid @pagination-border;\n      border-radius: @pager-border-radius;\n    }\n\n    > a:hover,\n    > a:focus {\n      text-decoration: none;\n      background-color: @pagination-active-bg;\n    }\n  }\n\n  .next {\n    > a,\n    > span {\n      float: right;\n    }\n  }\n\n  .previous {\n    > a,\n    > span {\n      float: left;\n    }\n  }\n\n  .disabled {\n    > a,\n    > a:hover,\n    > a:focus,\n    > span {\n      color: @pager-disabled-color;\n      background-color: @pagination-bg;\n      cursor: not-allowed;\n    }\n  }\n\n}\n"
  },
  {
    "path": "site/less/pagination.less",
    "content": "//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: @line-height-computed 0;\n  border-radius: @border-radius-base;\n\n  > li {\n    display: inline; // Remove list-style and block-level defaults\n    > a,\n    > span {\n      position: relative;\n      float: left; // Collapse white-space\n      padding: @padding-base-vertical @padding-base-horizontal;\n      line-height: @line-height-base;\n      text-decoration: none;\n      background-color: @pagination-bg;\n      border: 1px solid @pagination-border;\n      margin-left: -1px;\n    }\n    &:first-child {\n      > a,\n      > span {\n        margin-left: 0;\n        .border-left-radius(@border-radius-base);\n      }\n    }\n    &:last-child {\n      > a,\n      > span {\n        .border-right-radius(@border-radius-base);\n      }\n    }\n  }\n\n  > li > a,\n  > li > span {\n    &:hover,\n    &:focus {\n      background-color: @pagination-hover-bg;\n    }\n  }\n\n  > .active > a,\n  > .active > span {\n    &,\n    &:hover,\n    &:focus {\n      z-index: 2;\n      color: @pagination-active-color;\n      background-color: @pagination-active-bg;\n      border-color: @pagination-active-bg;\n      cursor: default;\n    }\n  }\n\n  > .disabled {\n    > span,\n    > a,\n    > a:hover,\n    > a:focus {\n      color: @pagination-disabled-color;\n      background-color: @pagination-bg;\n      border-color: @pagination-border;\n      cursor: not-allowed;\n    }\n  }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n  .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n  .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n"
  },
  {
    "path": "site/less/panels.less",
    "content": "//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n  margin-bottom: @line-height-computed;\n  background-color: @panel-bg;\n  border: 1px solid @panel-border;\n  border-radius: @panel-border-radius;\n  .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n  padding: 15px;\n}\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n  > .list-group {\n    margin-bottom: 0;\n\n    .list-group-item {\n      border-width: 1px 0;\n\n      // Remove border radius for top one\n      &:first-child {\n        .border-top-radius(0);\n      }\n      // But keep it for the last one\n      &:last-child {\n        border-bottom: 0;\n      }\n    }\n  }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n  .list-group-item:first-child {\n    border-top-width: 0;\n  }\n}\n\n// Optional heading\n.panel-heading {\n  padding: 10px 15px;\n  background-color: @panel-heading-bg;\n  border-bottom: 1px solid @panel-border;\n  .border-top-radius(@panel-border-radius - 1);\n}\n\n// Within heading, strip any `h*` tag of it's default margins for spacing.\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: (@font-size-base * 1.25);\n  > a {\n    color: inherit;\n  }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n  padding: 10px 15px;\n  background-color: @panel-footer-bg;\n  border-top: 1px solid @panel-border;\n  .border-bottom-radius(@panel-border-radius - 1);\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n  // Tighten up margin so it's only between panels\n  .panel {\n    margin-bottom: 0;\n    border-radius: @panel-border-radius;\n    overflow: hidden; // crop contents when collapsed\n    + .panel {\n      margin-top: 5px;\n    }\n  }\n\n  .panel-heading {\n    border-bottom: 0;\n    + .panel-collapse .panel-body {\n      border-top: 1px solid @panel-border;\n    }\n  }\n  .panel-footer {\n    border-top: 0;\n    + .panel-collapse .panel-body {\n      border-bottom: 1px solid @panel-border;\n    }\n  }\n\n  // New subcomponent for wrapping collapsable content for proper animations\n  .panel-collapse {\n\n  }\n}\n\n\n// Contextual variations\n.panel-primary {\n  .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n  .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-warning {\n  .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n  .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n.panel-info {\n  .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n"
  },
  {
    "path": "site/less/popovers.less",
    "content": "//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: @zindex-popover;\n  display: none;\n  max-width: @popover-max-width;\n  padding: 1px;\n  text-align: left; // Reset given new insertion method\n  background-color: @popover-bg;\n  background-clip: padding-box;\n  border: 1px solid @popover-fallback-border-color;\n  border: 1px solid @popover-border-color;\n  border-radius: @border-radius-large;\n  .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n  // Overrides for proper insertion\n  white-space: normal;\n\n  // Offset the popover to account for the popover arrow\n  &.top     { margin-top: -10px; }\n  &.right   { margin-left: 10px; }\n  &.bottom  { margin-top: 10px; }\n  &.left    { margin-left: -10px; }\n}\n\n.popover-title {\n  margin: 0; // reset heading margin\n  padding: 8px 14px;\n  font-size: @font-size-base;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: @popover-title-bg;\n  border-bottom: 1px solid darken(@popover-title-bg, 5%);\n  border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover .arrow {\n  &,\n  &:after {\n    position: absolute;\n    display: block;\n    width: 0;\n    height: 0;\n    border-color: transparent;\n    border-style: solid;\n  }\n}\n.popover .arrow {\n  border-width: @popover-arrow-outer-width;\n}\n.popover .arrow:after {\n  border-width: @popover-arrow-width;\n  content: \"\";\n}\n\n.popover {\n  &.top .arrow {\n    left: 50%;\n    margin-left: -@popover-arrow-outer-width;\n    border-bottom-width: 0;\n    border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-top-color: @popover-arrow-outer-color;\n    bottom: -@popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      bottom: 1px;\n      margin-left: -@popover-arrow-width;\n      border-bottom-width: 0;\n      border-top-color: @popover-arrow-color;\n    }\n  }\n  &.right .arrow {\n    top: 50%;\n    left: -@popover-arrow-outer-width;\n    margin-top: -@popover-arrow-outer-width;\n    border-left-width: 0;\n    border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-right-color: @popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      left: 1px;\n      bottom: -@popover-arrow-width;\n      border-left-width: 0;\n      border-right-color: @popover-arrow-color;\n    }\n  }\n  &.bottom .arrow {\n    left: 50%;\n    margin-left: -@popover-arrow-outer-width;\n    border-top-width: 0;\n    border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-bottom-color: @popover-arrow-outer-color;\n    top: -@popover-arrow-outer-width;\n    &:after {\n      content: \" \";\n      top: 1px;\n      margin-left: -@popover-arrow-width;\n      border-top-width: 0;\n      border-bottom-color: @popover-arrow-color;\n    }\n  }\n\n  &.left .arrow {\n    top: 50%;\n    right: -@popover-arrow-outer-width;\n    margin-top: -@popover-arrow-outer-width;\n    border-right-width: 0;\n    border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n    border-left-color: @popover-arrow-outer-color;\n    &:after {\n      content: \" \";\n      right: 1px;\n      border-right-width: 0;\n      border-left-color: @popover-arrow-color;\n      bottom: -@popover-arrow-width;\n    }\n  }\n\n}\n"
  },
  {
    "path": "site/less/print.less",
    "content": "//\n// Basic print styles\n// --------------------------------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n  * {\n    text-shadow: none !important;\n    color: #000 !important; // Black prints faster: h5bp.com/s\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  // Don't show links for images, or javascript/internal links\n  .ir a:after,\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n\n  thead {\n    display: table-header-group; // h5bp.com/t\n  }\n\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n\n  img {\n    max-width: 100% !important;\n  }\n\n  @page {\n    margin: 2cm .5cm;\n  }\n\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n\n  // Bootstrap components\n  .navbar {\n    display: none;\n  }\n  .table {\n    td,\n    th {\n      background-color: #fff !important;\n    }\n  }\n  .btn,\n  .dropup > .btn {\n    > .caret {\n      border-top-color: #000 !important;\n    }\n  }\n  .label {\n    border: 1px solid #000;\n  }\n\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table-bordered {\n    th,\n    td {\n      border: 1px solid #ddd !important;\n    }\n  }\n\n}\n"
  },
  {
    "path": "site/less/progress-bars.less",
    "content": "//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// Webkit\n@-webkit-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Firefox\n@-moz-keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n// Opera\n@-o-keyframes progress-bar-stripes {\n  from  { background-position: 0 0; }\n  to    { background-position: 40px 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n  from  { background-position: 40px 0; }\n  to    { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n  overflow: hidden;\n  height: @line-height-computed;\n  margin-bottom: @line-height-computed;\n  background-color: @progress-bg;\n  border-radius: @border-radius-base;\n  .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n  float: left;\n  width: 0%;\n  height: 100%;\n  font-size: @font-size-small;\n  color: @progress-bar-color;\n  text-align: center;\n  background-color: @progress-bar-bg;\n  .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n  .transition(width .6s ease);\n}\n\n// Striped bars\n.progress-striped .progress-bar {\n  #gradient > .striped(@progress-bar-bg);\n  background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n     -moz-animation: progress-bar-stripes 2s linear infinite;\n      -ms-animation: progress-bar-stripes 2s linear infinite;\n       -o-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n  .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n  .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n  .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n  .progress-bar-variant(@progress-bar-danger-bg);\n}\n"
  },
  {
    "path": "site/less/responsive-utilities.less",
    "content": "//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 Metro responsive\n// Required for Windows 8 Metro split-screen snapping with IE10\n//\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n@-ms-viewport{\n  width: device-width;\n}\n\n// IE10 on Windows Phone 8\n// IE10 on WP8 doesn't report CSS pixels, but actual device pixels. In\n// other words, say on a Lumia, you'll get 768px as the device width,\n// meaning users will see the tablet styles and not phone styles.\n//\n// Alternatively you can override this with JS (see source below), but\n// we won't be doing that here given our limited scope.\n//\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n@media screen and (max-width: 400px) {\n  @-ms-viewport{\n    width: 320px;\n  }\n}\n\n// Hide from screenreaders and browsers\n// Credit: HTML5 Boilerplate\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n// Visibility utilities\n\n.visible-xs {\n  .responsive-visibility();\n  @media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) {\n    .responsive-invisibility();\n  }\n  @media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) {\n    .responsive-invisibility();\n  }\n  @media (min-width: @screen-large-desktop) {\n    .responsive-invisibility();\n  }\n}\n.visible-sm {\n  .responsive-invisibility();\n  @media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) {\n    .responsive-visibility();\n  }\n  @media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) {\n    .responsive-invisibility();\n  }\n  @media (min-width: @screen-large-desktop) {\n    .responsive-invisibility();\n  }\n}\n.visible-md {\n  .responsive-invisibility();\n  @media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) {\n    .responsive-invisibility();\n  }\n  @media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) {\n    .responsive-visibility();\n  }\n  @media (min-width: @screen-large-desktop) {\n    .responsive-invisibility();\n  }\n}\n.visible-lg {\n  .responsive-invisibility();\n  @media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) {\n    .responsive-invisibility();\n  }\n  @media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) {\n    .responsive-invisibility();\n  }\n  @media (min-width: @screen-large-desktop) {\n    .responsive-visibility();\n  }\n}\n\n.hidden-xs {\n  .responsive-invisibility();\n  @media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) {\n    .responsive-visibility();\n  }\n  @media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) {\n    .responsive-visibility();\n  }\n  @media (min-width: @screen-large-desktop) {\n    .responsive-visibility();\n  }\n}\n.hidden-sm {\n  .responsive-visibility();\n  @media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) {\n    .responsive-invisibility();\n  }\n  @media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) {\n    .responsive-visibility();\n  }\n  @media (min-width: @screen-large-desktop) {\n    .responsive-visibility();\n  }\n}\n.hidden-md {\n  .responsive-visibility();\n  @media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) {\n    .responsive-visibility();\n  }\n  @media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) {\n    .responsive-invisibility();\n  }\n  @media (min-width: @screen-large-desktop) {\n    .responsive-visibility();\n  }\n}\n.hidden-lg {\n  .responsive-visibility();\n  @media (min-width: @screen-tablet) and (max-width: @screen-tablet-max) {\n    .responsive-visibility();\n  }\n  @media (min-width: @screen-desktop) and (max-width: @screen-desktop-max) {\n    .responsive-visibility();\n  }\n  @media (min-width: @screen-large-desktop) {\n    .responsive-invisibility();\n  }\n}\n\n// Print utilities\n.visible-print {\n  .responsive-invisibility();\n}\n.hidden-print  { }\n\n@media print {\n  .visible-print {\n    .responsive-visibility();\n  }\n  .hidden-print {\n    .responsive-invisibility();\n  }\n}\n"
  },
  {
    "path": "site/less/retina.less",
    "content": "// retina.less\n// A helper mixin for applying high-resolution background images (http://www.retinajs.com)\n\n.at2x(@path, @w: auto, @h: auto) {\n  background-image: url(@path);\n  @at2x_path: ~`\"@{path}\".split('.').slice(0, \"@{path}\".split('.').length - 1).join(\".\") + \"@2x\" + \".\" + \"@{path}\".split('.')[\"@{path}\".split('.').length - 1]`;\n\n  @media all and (-webkit-min-device-pixel-ratio : 1.5) {\n    background-image: url(@at2x_path);\n    background-size: @w @h;\n  }  \n}"
  },
  {
    "path": "site/less/scaffolding.less",
    "content": "//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n// -------------------------\n\n*,\n*:before,\n*:after {\n  .box-sizing(border-box);\n}\n\n\n// Body reset\n// -------------------------\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n  font-family: @font-family-base;\n  font-size: @font-size-base;\n  line-height: @line-height-base;\n  color: @text-color;\n  background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\n// Reset unusual Firefox-on-Android default style, see https://github.com/necolas/normalize.css/issues/214\nbutton,\ninput,\nselect[multiple],\ntextarea {\n  background-image: none;\n}\n\n\n// Links\n// -------------------------\n\na {\n  color: @link-color;\n  text-decoration: none;\n}\na:hover,\na:focus {\n  color: @link-hover-color;\n  text-decoration: underline;\n}\na:focus {\n  .tab-focus();\n}\n\n\n// Images\n// -------------------------\n\nimg {\n  vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n  .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n  border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n// See thumbnails.less for `.img-thumbnail`\n\n// Perfect circle\n.img-circle {\n  border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n// -------------------------\n\nhr {\n  margin-top:    @line-height-computed;\n  margin-bottom: @line-height-computed;\n  border: 0;\n  border-top: 1px solid @hr-border;\n}\n\n// Only display content to screen readers\n// See: http://a11yproject.com/posts/how-to-hide-content/\n// -------------------------\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0 0 0 0);\n  border: 0;\n}\n"
  },
  {
    "path": "site/less/tables.less",
    "content": "//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n  max-width: 100%;\n  background-color: @table-bg;\n}\nth {\n  text-align: left;\n}\n\n\n// Baseline styles\n// ---------------\n\n.table {\n  width: 100%;\n  margin-bottom: @line-height-computed;\n  // Cells\n  thead,\n  tbody,\n  tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: @table-cell-padding;\n        line-height: @line-height-base;\n        vertical-align: top;\n        border-top: 1px solid @table-border-color;\n      }\n    }\n  }\n  // Bottom align for column headings\n  thead > tr > th {\n    vertical-align: bottom;\n  }\n  // Remove top border from thead by default\n  caption + thead,\n  colgroup + thead,\n  thead:first-child {\n    tr:first-child {\n      th, td {\n        border-top: 0;\n      }\n    }\n  }\n  // Account for multiple tbody instances\n  tbody + tbody {\n    border-top: 2px solid @table-border-color;\n  }\n\n  // Nesting\n  .table {\n    background-color: @body-bg;\n  }\n}\n\n\n\n// Condensed table w/ half padding\n// -------------------------------\n\n.table-condensed {\n  thead,\n  tbody,\n  tfoot {\n    > tr {\n      > th,\n      > td {\n        padding: @table-condensed-cell-padding;\n      }\n    }\n  }\n}\n\n\n\n// Bordered version\n// ----------------\n\n.table-bordered {\n  border: 1px solid @table-border-color;\n  > thead,\n  > tbody,\n  > tfoot {\n    > tr {\n      > th,\n      > td {\n        border: 1px solid @table-border-color;\n      }\n    }\n  }\n}\n\n\n\n// Zebra-striping\n// --------------\n\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n.table-striped {\n  > tbody {\n    > tr:nth-child(odd) {\n      > td,\n      > th {\n        background-color: @table-bg-accent;\n      }\n    }\n  }\n}\n\n\n\n// Hover effect\n// ------------\n\n// Placed here since it has to come after the potential zebra striping\n.table-hover {\n  > tbody {\n    > tr:hover {\n      > td,\n      > th {\n        background-color: @table-bg-hover;\n      }\n    }\n  }\n}\n\n\n\n// Table cell sizing\n// -----------------\n\n// Reset default table behavior\ntable col[class^=\"col-\"] {\n  float: none;\n  display: table-column;\n}\ntable {\n  td,\n  th {\n    &[class^=\"col-\"] {\n      float: none;\n      display: table-cell;\n    }\n  }\n}\n\n\n\n// Table backgrounds\n// -----------------\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n.table > thead > tr,\n.table > tbody > tr,\n.table > tfoot > tr {\n  > td.active,\n  > th.active,\n  &.active > td,\n  &.active > th  {\n    background-color: @table-bg-active;\n  }\n}\n\n// Contextual variants\n// -------------------\n.table-row-variant(success; @state-success-bg; @state-success-border);\n\n.table-row-variant(danger; @state-danger-bg; @state-danger-border);\n\n.table-row-variant(warning; @state-warning-bg; @state-warning-border);\n"
  },
  {
    "path": "site/less/thumbnails.less",
    "content": "//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Base classes\n// For thumbnail block-level composite components and simple image styles\n\n// The actual thumbnailed element\n// Can be `a`, `div`, or `img`\n.thumbnail,\n.img-thumbnail {\n  padding: @thumbnail-padding;\n  line-height: @line-height-base;\n  background-color: @thumbnail-bg;\n  border: 1px solid @thumbnail-border;\n  border-radius: @thumbnail-border-radius;\n  .transition(all .2s ease-in-out);\n}\n.thumbnail {\n  display: block;\n}\n.thumbnail > img {\n  .img-responsive();\n}\n.img-thumbnail {\n  .img-responsive(inline-block);\n}\n\n// Add a hover state for linked versions only\na.thumbnail:hover,\na.thumbnail:focus {\n  border-color: @link-color;\n}\n\n// Images and captions\n.thumbnail > img {\n  margin-left: auto;\n  margin-right: auto;\n}\n.thumbnail .caption {\n  padding: @thumbnail-caption-padding;\n  color: @thumbnail-caption-color;\n}\n"
  },
  {
    "path": "site/less/tooltip.less",
    "content": "//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n  position: absolute;\n  z-index: @zindex-tooltip;\n  display: block;\n  visibility: visible;\n  font-size: @font-size-small;\n  line-height: 1.4;\n  .opacity(0);\n\n  &.in     { .opacity(.9); }\n  &.top    { margin-top:  -3px; padding: 5px 0; }\n  &.right  { margin-left:  3px; padding: 0 5px; }\n  &.bottom { margin-top:   3px; padding: 5px 0; }\n  &.left   { margin-left: -3px; padding: 0 5px; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n  max-width: @tooltip-max-width;\n  padding: 3px 8px;\n  color: @tooltip-color;\n  text-align: center;\n  text-decoration: none;\n  background-color: @tooltip-bg;\n  border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip {\n  &.top .tooltip-arrow {\n    bottom: 0;\n    left: 50%;\n    margin-left: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.top-left .tooltip-arrow {\n    bottom: 0;\n    left: 5px;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.top-right .tooltip-arrow {\n    bottom: 0;\n    right: 5px;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-top-color: @tooltip-arrow-color;\n  }\n  &.right .tooltip-arrow {\n    top: 50%;\n    left: 0;\n    margin-top: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n    border-right-color: @tooltip-arrow-color;\n  }\n  &.left .tooltip-arrow {\n    top: 50%;\n    right: 0;\n    margin-top: -@tooltip-arrow-width;\n    border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-left-color: @tooltip-arrow-color;\n  }\n  &.bottom .tooltip-arrow {\n    top: 0;\n    left: 50%;\n    margin-left: -@tooltip-arrow-width;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n  &.bottom-left .tooltip-arrow {\n    top: 0;\n    left: 5px;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n  &.bottom-right .tooltip-arrow {\n    top: 0;\n    right: 5px;\n    border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n    border-bottom-color: @tooltip-arrow-color;\n  }\n}\n"
  },
  {
    "path": "site/less/type.less",
    "content": "//\n// Typography\n// --------------------------------------------------\n\n\n// Body text\n// -------------------------\n\np {\n  margin: 0 0 (@line-height-computed / 2);\n}\n.lead {\n  margin-bottom: @line-height-computed;\n  font-size: (@font-size-base * 1.15);\n  font-weight: 200;\n  line-height: 1.4;\n\n  @media (min-width: 768px) {\n    font-size: (@font-size-base * 1.5);\n  }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: 14px base font * 85% = about 12px\nsmall   { font-size: 85%; }\n\n// Undo browser default styling\ncite    { font-style: normal; }\n\n// Contextual emphasis\n.text-muted          { color: @text-muted; }\n.text-primary        { color: @brand-primary; }\n.text-warning        { color: @state-warning-text; }\n.text-danger         { color: @state-danger-text; }\n.text-success        { color: @state-success-text; }\n.text-info           { color: @state-info-text; }\n\n// Alignment\n.text-left           { text-align: left; }\n.text-right          { text-align: right; }\n.text-center         { text-align: center; }\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n  font-family: @headings-font-family;\n  font-weight: @headings-font-weight;\n  line-height: @headings-line-height;\n  small {\n    font-weight: normal;\n    line-height: 1;\n    color: @headings-small-color;\n  }\n}\n\nh1,\nh2,\nh3 {\n  margin-top: @line-height-computed;\n  margin-bottom: (@line-height-computed / 2);\n}\nh4,\nh5,\nh6 {\n  margin-top: (@line-height-computed / 2);\n  margin-bottom: (@line-height-computed / 2);\n}\n\nh1, .h1 { font-size: ceil(@font-size-base * 2.70); } // ~38px\nh2, .h2 { font-size: ceil(@font-size-base * 2.25); } // ~32px\nh3, .h3 { font-size: ceil(@font-size-base * 1.70); } // ~24px\nh4, .h4 { font-size: ceil(@font-size-base * 1.25); } // ~18px\nh5, .h5 { font-size:  @font-size-base; }\nh6, .h6 { font-size: ceil(@font-size-base * 0.85); } // ~12px\n\nh1 small, .h1 small { font-size: ceil(@font-size-base * 1.70); } // ~24px\nh2 small, .h2 small { font-size: ceil(@font-size-base * 1.25); } // ~18px\nh3 small, .h3 small,\nh4 small, .h4 small { font-size: @font-size-base; }\n\n\n// Page header\n// -------------------------\n\n.page-header {\n  padding-bottom: ((@line-height-computed / 2) - 1);\n  margin: (@line-height-computed * 2) 0 @line-height-computed;\n  border-bottom: 1px solid @page-header-border-color;\n}\n\n\n\n// Lists\n// --------------------------------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n  margin-top: 0;\n  margin-bottom: (@line-height-computed / 2);\n  ul,\n  ol{\n    margin-bottom: 0;\n  }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n// Inline turns list items into inline-block\n.list-inline {\n  .list-unstyled();\n  > li {\n    display: inline-block;\n    padding-left: 5px;\n    padding-right: 5px;\n  }\n}\n\n// Description Lists\ndl {\n  margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n  line-height: @line-height-base;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n@media (min-width: @grid-float-breakpoint) {\n  .dl-horizontal {\n    dt {\n      float: left;\n      width: (@component-offset-horizontal - 20);\n      clear: left;\n      text-align: right;\n      .text-overflow();\n    }\n    dd {\n      margin-left: @component-offset-horizontal;\n      .clearfix(); // Clear the floated `dt` if an empty `dd` is present\n    }\n  }\n}\n\n// MISC\n// ----\n\n// Abbreviations and acronyms\nabbr[title],\n// Added data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted @abbr-border-color;\n}\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n  padding: (@line-height-computed / 2) @line-height-computed;\n  margin: 0 0 @line-height-computed;\n  border-left: 5px solid @blockquote-border-color;\n  p {\n    font-size: (@font-size-base * 1.25);\n    font-weight: 300;\n    line-height: 1.25;\n  }\n  p:last-child {\n    margin-bottom: 0;\n  }\n  small {\n    display: block;\n    line-height: @line-height-base;\n    color: @blockquote-small-color;\n    &:before {\n      content: '\\2014 \\00A0';// EM DASH, NBSP\n    }\n  }\n\n  // Float right with text-align: right\n  &.pull-right {\n    padding-right: 15px;\n    padding-left: 0;\n    border-right: 5px solid @blockquote-border-color;\n    border-left: 0;\n    p,\n    small {\n      text-align: right;\n    }\n    small {\n      &:before {\n        content: '';\n      }\n      &:after {\n        content: '\\00A0 \\2014';// NBSP, EM DASH\n      }\n    }\n  }\n}\n\n// Quotes\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\n// Addresses\naddress {\n  display: block;\n  margin-bottom: @line-height-computed;\n  font-style: normal;\n  line-height: @line-height-base;\n}\n"
  },
  {
    "path": "site/less/utilities.less",
    "content": "//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n  .clearfix();\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\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  .hide-text();\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "site/less/variables.less",
    "content": "//\n// Variables\n// --------------------------------------------------\n\n\n// Global values\n// --------------------------------------------------\n\n// Grays\n// -------------------------\n\n@gray-darker:            lighten(#000, 13.5%); // #222\n@gray-dark:              lighten(#000, 20%);   // #333\n@gray:                   lighten(#000, 33.5%); // #555\n@gray-light:             lighten(#000, 60%);   // #999\n@gray-lighter:           lighten(#000, 93.5%); // #eee\n\n// Brand colors\n// -------------------------\n\n@brand-primary:         #428bca;\n@brand-success:         #5cb85c;\n@brand-warning:         #f0ad4e;\n@brand-danger:          #d9534f;\n@brand-info:            #5bc0de;\n\n// Scaffolding\n// -------------------------\n\n@body-bg:               #fff;\n@text-color:            @gray-dark;\n\n// Links\n// -------------------------\n\n@link-color:            @brand-primary;\n@link-hover-color:      darken(@link-color, 15%);\n\n// Typography\n// -------------------------\n\n@font-family-sans-serif:  \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n@font-family-serif:       Georgia, \"Times New Roman\", Times, serif;\n@font-family-monospace:   Monaco, Menlo, Consolas, \"Courier New\", monospace;\n@font-family-base:        @font-family-sans-serif;\n\n@font-size-base:          14px;\n@font-size-large:         ceil(@font-size-base * 1.25); // ~18px\n@font-size-small:         ceil(@font-size-base * 0.85); // ~12px\n\n@line-height-base:        1.428571429; // 20/14\n@line-height-computed:    floor(@font-size-base * @line-height-base); // ~20px\n\n@headings-font-family:    @font-family-base;\n@headings-font-weight:    500;\n@headings-line-height:    1.1;\n\n\n// Components\n// -------------------------\n// Based on 14px font-size and 1.428 line-height (~20px to start)\n\n@padding-base-vertical:          6px;\n@padding-base-horizontal:        12px;\n\n@padding-large-vertical:         10px;\n@padding-large-horizontal:       16px;\n\n@padding-small-vertical:         5px;\n@padding-small-horizontal:       10px;\n\n@line-height-large:              1.33;\n@line-height-small:              1.5;\n\n@border-radius-base:             4px;\n@border-radius-large:            6px;\n@border-radius-small:            3px;\n\n@component-active-bg:            @brand-primary;\n\n@caret-width-base:               4px;\n@caret-width-large:              5px;\n\n// Tables\n// -------------------------\n\n@table-cell-padding:                 8px;\n@table-condensed-cell-padding:       5px;\n\n@table-bg:                           transparent; // overall background-color\n@table-bg-accent:                    #f9f9f9; // for striping\n@table-bg-hover:                     #f5f5f5;\n@table-bg-active:                    @table-bg-hover;\n\n@table-border-color:                 #ddd; // table and cell border\n\n\n// Buttons\n// -------------------------\n\n@btn-font-weight:                bold;\n\n@btn-default-color:              #333;\n@btn-default-bg:                 #fff;\n@btn-default-border:             #ccc;\n\n@btn-primary-color:              #fff;\n@btn-primary-bg:                 @brand-primary;\n@btn-primary-border:             darken(@btn-primary-bg, 5%);\n\n@btn-success-color:              #fff;\n@btn-success-bg:                 @brand-success;\n@btn-success-border:             darken(@btn-success-bg, 5%);\n\n@btn-warning-color:              #fff;\n@btn-warning-bg:                 @brand-warning;\n@btn-warning-border:             darken(@btn-warning-bg, 5%);\n\n@btn-danger-color:               #fff;\n@btn-danger-bg:                  @brand-danger;\n@btn-danger-border:              darken(@btn-danger-bg, 5%);\n\n@btn-info-color:                 #fff;\n@btn-info-bg:                    @brand-info;\n@btn-info-border:                darken(@btn-info-bg, 5%);\n\n@btn-link-disabled-color:        @gray-light;\n\n\n// Forms\n// -------------------------\n\n@input-bg:                       #fff;\n@input-bg-disabled:              @gray-lighter;\n\n@input-color:                    @gray;\n@input-border:                   #ccc;\n@input-border-radius:            @border-radius-base;\n@input-border-focus:             #66afe9;\n\n@input-color-placeholder:        @gray-light;\n\n@input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);\n@input-height-large:             (floor(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n@input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);\n\n@legend-color:                   @gray-dark;\n@legend-border-color:            #e5e5e5;\n\n@input-group-addon-bg:           @gray-lighter;\n@input-group-addon-border-color: @input-border;\n\n\n// Dropdowns\n// -------------------------\n\n@dropdown-bg:                    #fff;\n@dropdown-border:                rgba(0,0,0,.15);\n@dropdown-fallback-border:       #ccc;\n@dropdown-divider-bg:            #e5e5e5;\n\n@dropdown-link-active-color:     #fff;\n@dropdown-link-active-bg:        @component-active-bg;\n\n@dropdown-link-color:            @gray-dark;\n@dropdown-link-hover-color:      #fff;\n@dropdown-link-hover-bg:         @dropdown-link-active-bg;\n\n@dropdown-link-disabled-color:   @gray-light;\n\n@dropdown-header-color:          @gray-light;\n\n@dropdown-caret-color:           #000;\n\n\n// COMPONENT VARIABLES\n// --------------------------------------------------\n\n\n// Z-index master list\n// -------------------------\n// Used for a bird's eye view of components dependent on the z-axis\n// Try to avoid customizing these :)\n\n@zindex-dropdown:          1000;\n@zindex-popover:           1010;\n@zindex-tooltip:           1030;\n@zindex-navbar-fixed:      1030;\n@zindex-modal-background:  1040;\n@zindex-modal:             1050;\n\n// Media queries breakpoints\n// --------------------------------------------------\n\n// Extra small screen / phone\n@screen-xsmall:              480px;\n@screen-phone:               @screen-xsmall;\n\n// Small screen / tablet\n@screen-small:               768px;\n@screen-tablet:              @screen-small;\n\n// Medium screen / desktop\n@screen-medium:              992px;\n@screen-desktop:             @screen-medium;\n\n// Large screen / wide desktop\n@screen-large:               1200px;\n@screen-large-desktop:       @screen-large;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-phone-max:           (@screen-small - 1);\n@screen-small-max:           (@screen-medium - 1);\n@screen-tablet-max:          (@screen-desktop - 1);\n@screen-desktop-max:         (@screen-large-desktop - 1);\n\n\n// Grid system\n// --------------------------------------------------\n\n// Number of columns in the grid system\n@grid-columns:              12;\n// Padding, to be divided by two and applied to the left and right of all columns\n@grid-gutter-width:         30px;\n// Point at which the navbar stops collapsing\n@grid-float-breakpoint:     @screen-tablet;\n\n\n// Navbar\n// -------------------------\n\n// Basics of a navbar\n@navbar-height:                    50px;\n@navbar-margin-bottom:             @line-height-computed;\n@navbar-color:                     #777;\n@navbar-bg:                        #f8f8f8;\n@navbar-border:                    darken(@navbar-bg, 6.5%);\n@navbar-border-radius:             @border-radius-base;\n@navbar-padding-horizontal:        floor(@grid-gutter-width / 2);\n@navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);\n\n// Navbar links\n@navbar-link-color:                #777;\n@navbar-link-hover-color:          #333;\n@navbar-link-hover-bg:             transparent;\n@navbar-link-active-color:         #555;\n@navbar-link-active-bg:            darken(@navbar-bg, 6.5%);\n@navbar-link-disabled-color:       #ccc;\n@navbar-link-disabled-bg:          transparent;\n\n// Navbar brand label\n@navbar-brand-color:               @navbar-link-color;\n@navbar-brand-hover-color:         darken(@navbar-link-color, 10%);\n@navbar-brand-hover-bg:            transparent;\n\n// Navbar toggle\n@navbar-toggle-hover-bg:           #ddd;\n@navbar-toggle-icon-bar-bg:        #ccc;\n@navbar-toggle-border-color:       #ddd;\n\n\n// Inverted navbar\n//\n// Reset inverted navbar basics\n@navbar-inverse-color:                      @gray-light;\n@navbar-inverse-bg:                         #222;\n@navbar-inverse-border:                     darken(@navbar-inverse-bg, 10%);\n\n// Inverted navbar links\n@navbar-inverse-link-color:                 @gray-light;\n@navbar-inverse-link-hover-color:           #fff;\n@navbar-inverse-link-hover-bg:              transparent;\n@navbar-inverse-link-active-color:          @navbar-inverse-link-hover-color;\n@navbar-inverse-link-active-bg:             darken(@navbar-inverse-bg, 10%);\n@navbar-inverse-link-disabled-color:        #444;\n@navbar-inverse-link-disabled-bg:           transparent;\n\n// Inverted navbar brand label\n@navbar-inverse-brand-color:                @navbar-inverse-link-color;\n@navbar-inverse-brand-hover-color:          #fff;\n@navbar-inverse-brand-hover-bg:             transparent;\n\n// Inverted navbar search\n// Normal navbar needs no special styles or vars\n@navbar-inverse-search-bg:                  lighten(@navbar-inverse-bg, 25%);\n@navbar-inverse-search-bg-focus:            #fff;\n@navbar-inverse-search-border:              @navbar-inverse-bg;\n@navbar-inverse-search-placeholder-color:   #ccc;\n\n// Inverted navbar toggle\n@navbar-inverse-toggle-hover-bg:            #333;\n@navbar-inverse-toggle-icon-bar-bg:         #fff;\n@navbar-inverse-toggle-border-color:        #333;\n\n\n// Navs\n// -------------------------\n\n@nav-link-padding:                          10px 15px;\n@nav-link-hover-bg:                         @gray-lighter;\n\n@nav-disabled-link-color:                   @gray-light;\n@nav-disabled-link-hover-color:             @gray-light;\n\n@nav-open-link-hover-color:                 #fff;\n@nav-open-caret-border-color:               #fff;\n\n// Tabs\n@nav-tabs-border-color:                     #ddd;\n\n@nav-tabs-link-hover-border-color:          @gray-lighter;\n\n@nav-tabs-active-link-hover-bg:             @body-bg;\n@nav-tabs-active-link-hover-color:          @gray;\n@nav-tabs-active-link-hover-border-color:   #ddd;\n\n@nav-tabs-justified-link-border-color:            #ddd;\n@nav-tabs-justified-active-link-border-color:     @body-bg;\n\n// Pills\n@nav-pills-active-link-hover-bg:            @component-active-bg;\n@nav-pills-active-link-hover-color:         #fff;\n\n\n// Pagination\n// -------------------------\n\n@pagination-bg:                        #fff;\n@pagination-border:                    #ddd;\n\n@pagination-hover-bg:                  @gray-lighter;\n\n@pagination-active-bg:                 @brand-primary;\n@pagination-active-color:              #fff;\n\n@pagination-disabled-color:            @gray-light;\n\n\n// Pager\n// -------------------------\n\n@pager-border-radius:                  15px;\n@pager-disabled-color:                 @gray-light;\n\n\n// Jumbotron\n// -------------------------\n\n@jumbotron-bg:                   @gray-lighter;\n@jumbotron-heading-color:        inherit;\n@jumbotron-lead-color:           inherit;\n\n\n// Form states and alerts\n// -------------------------\n\n@state-warning-text:             #c09853;\n@state-warning-bg:               #fcf8e3;\n@state-warning-border:           darken(spin(@state-warning-bg, -10), 3%);\n\n@state-danger-text:              #b94a48;\n@state-danger-bg:                #f2dede;\n@state-danger-border:            darken(spin(@state-danger-bg, -10), 3%);\n\n@state-success-text:             #468847;\n@state-success-bg:               #dff0d8;\n@state-success-border:           darken(spin(@state-success-bg, -10), 5%);\n\n@state-info-text:                #3a87ad;\n@state-info-bg:                  #d9edf7;\n@state-info-border:              darken(spin(@state-info-bg, -10), 7%);\n\n\n// Tooltips\n// -------------------------\n@tooltip-max-width:           200px;\n@tooltip-color:               #fff;\n@tooltip-bg:                  #000;\n\n@tooltip-arrow-width:         5px;\n@tooltip-arrow-color:         @tooltip-bg;\n\n\n// Popovers\n// -------------------------\n@popover-bg:                          #fff;\n@popover-max-width:                   276px;\n@popover-border-color:                rgba(0,0,0,.2);\n@popover-fallback-border-color:       #ccc;\n\n@popover-title-bg:                    darken(@popover-bg, 3%);\n\n@popover-arrow-width:                 10px;\n@popover-arrow-color:                 #fff;\n\n@popover-arrow-outer-width:           (@popover-arrow-width + 1);\n@popover-arrow-outer-color:           rgba(0,0,0,.25);\n@popover-arrow-outer-fallback-color:  #999;\n\n\n// Labels\n// -------------------------\n\n@label-default-bg:            @gray-light;\n@label-primary-bg:            @brand-primary;\n@label-success-bg:            @brand-success;\n@label-info-bg:               @brand-info;\n@label-warning-bg:            @brand-warning;\n@label-danger-bg:             @brand-danger;\n\n@label-color:                 #fff;\n@label-link-hover-color:      #fff;\n\n\n// Modals\n// -------------------------\n@modal-inner-padding:         20px;\n\n@modal-title-padding:         15px;\n@modal-title-line-height:     @line-height-base;\n\n@modal-content-bg:                             #fff;\n@modal-content-border-color:                   rgba(0,0,0,.2);\n@modal-content-fallback-border-color:          #999;\n\n@modal-backdrop-bg:           #000;\n@modal-header-border-color:   #e5e5e5;\n@modal-footer-border-color:   @modal-header-border-color;\n\n\n// Alerts\n// -------------------------\n@alert-padding:               15px;\n@alert-border-radius:         @border-radius-base;\n@alert-link-font-weight:      bold;\n\n@alert-bg:                    @state-warning-bg;\n@alert-text:                  @state-warning-text;\n@alert-border:                @state-warning-border;\n\n@alert-success-bg:            @state-success-bg;\n@alert-success-text:          @state-success-text;\n@alert-success-border:        @state-success-border;\n\n@alert-danger-bg:             @state-danger-bg;\n@alert-danger-text:           @state-danger-text;\n@alert-danger-border:         @state-danger-border;\n\n@alert-info-bg:               @state-info-bg;\n@alert-info-text:             @state-info-text;\n@alert-info-border:           @state-info-border;\n\n\n// Progress bars\n// -------------------------\n@progress-bg:                 #f5f5f5;\n@progress-bar-color:          #fff;\n\n@progress-bar-bg:             @brand-primary;\n@progress-bar-success-bg:     @brand-success;\n@progress-bar-warning-bg:     @brand-warning;\n@progress-bar-danger-bg:      @brand-danger;\n@progress-bar-info-bg:        @brand-info;\n\n\n// List group\n// -------------------------\n@list-group-bg:               #fff;\n@list-group-border:           #ddd;\n@list-group-border-radius:    @border-radius-base;\n\n@list-group-hover-bg:         #f5f5f5;\n@list-group-active-color:     #fff;\n@list-group-active-bg:        @component-active-bg;\n@list-group-active-border:    @list-group-active-bg;\n\n@list-group-link-color:          #555;\n@list-group-link-heading-color:  #333;\n\n\n// Panels\n// -------------------------\n@panel-bg:                    #fff;\n@panel-border:                #ddd;\n@panel-border-radius:         @border-radius-base;\n@panel-heading-bg:            #f5f5f5;\n@panel-footer-bg:             #f5f5f5;\n\n@panel-primary-text:          #fff;\n@panel-primary-border:        @brand-primary;\n@panel-primary-heading-bg:    @brand-primary;\n\n@panel-success-text:          @state-success-text;\n@panel-success-border:        @state-success-border;\n@panel-success-heading-bg:    @state-success-bg;\n\n@panel-warning-text:          @state-warning-text;\n@panel-warning-border:        @state-warning-border;\n@panel-warning-heading-bg:    @state-warning-bg;\n\n@panel-danger-text:           @state-danger-text;\n@panel-danger-border:         @state-danger-border;\n@panel-danger-heading-bg:     @state-danger-bg;\n\n@panel-info-text:             @state-info-text;\n@panel-info-border:           @state-info-border;\n@panel-info-heading-bg:       @state-info-bg;\n\n\n// Thumbnails\n// -------------------------\n@thumbnail-padding:           4px;\n@thumbnail-bg:                @body-bg;\n@thumbnail-border:            #ddd;\n@thumbnail-border-radius:     @border-radius-base;\n\n@thumbnail-caption-color:     @text-color;\n@thumbnail-caption-padding:   9px;\n\n\n// Wells\n// -------------------------\n@well-bg:                     #f5f5f5;\n\n\n// Badges\n// -------------------------\n@badge-color:                 #fff;\n@badge-link-hover-color:      #fff;\n@badge-bg:                    @gray-light;\n\n@badge-active-color:          @link-color;\n@badge-active-bg:             #fff;\n\n@badge-font-weight:           bold;\n@badge-line-height:           1;\n@badge-border-radius:         10px;\n\n\n// Breadcrumbs\n// -------------------------\n@breadcrumb-bg:               #f5f5f5;\n@breadcrumb-color:            #ccc;\n@breadcrumb-active-color:     @gray-light;\n\n\n// Carousel\n// ------------------------\n\n@carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);\n\n@carousel-control-color:                      #fff;\n@carousel-control-width:                      15%;\n@carousel-control-opacity:                    .5;\n@carousel-control-font-size:                  20px;\n\n@carousel-indicator-active-bg:                #fff;\n@carousel-indicator-border-color:             #fff;\n\n@carousel-caption-color:                      #fff;\n\n\n// Close\n// ------------------------\n@close-color:                 #000;\n@close-font-weight:           bold;\n@close-text-shadow:           0 1px 0 #fff;\n\n\n// Code\n// ------------------------\n@code-color:                  #c7254e;\n@code-bg:                     #f9f2f4;\n\n@pre-bg:                      #f5f5f5;\n@pre-color:                   @gray-dark;\n@pre-border-color:            #ccc;\n@pre-scrollable-max-height:   340px;\n\n// Type\n// ------------------------\n@text-muted:                  @gray-light;\n@abbr-border-color:           @gray-light;\n@headings-small-color:        @gray-light;\n@blockquote-small-color:      @gray-light;\n@blockquote-border-color:     @gray-lighter;\n@page-header-border-color:    @gray-lighter;\n\n// Miscellaneous\n// -------------------------\n\n// Hr border color\n@hr-border:                   @gray-lighter;\n\n// Horizontal forms & lists\n@component-offset-horizontal: 180px;\n\n\n// Container sizes\n// --------------------------------------------------\n\n// Small screen / tablet\n@container-tablet:          720px;\n\n// Medium screen / desktop\n@container-desktop:         940px;\n\n// Large screen / wide desktop\n@container-large-desktop:   1140px;\n"
  },
  {
    "path": "site/less/wells.less",
    "content": "//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: @well-bg;\n  border: 1px solid darken(@well-bg, 7%);\n  border-radius: @border-radius-base;\n  .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n  blockquote {\n    border-color: #ddd;\n    border-color: rgba(0,0,0,.15);\n  }\n}\n\n// Sizes\n.well-lg {\n  padding: 24px;\n  border-radius: @border-radius-large;\n}\n.well-sm {\n  padding: 9px;\n  border-radius: @border-radius-small;\n}\n"
  },
  {
    "path": "site/source-code-index.tmpl",
    "content": "{% extends \"base.tmpl\" %}\n{% block styles %}\n  <link rel=\"stylesheet\" href=\"{{ base }}css/docco.css\">\n  <script src=\"{{ base }}js/source-code.js\"></script>\n{% endblock %}\n{% block body %}\n\n<div class=\"container\">\n\n    <section class=\"row\" id=\"sourcecode\">\n      \n      <div class=\"col-md-3\" id=\"source-toc\">\n        <div class=\"panel\" role=\"complementary\" data-spy=\"affix\" data-offset-top=\"200\" id=\"sidenav\">\n          <div class=\"panel-heading\">Source Code</div>\n          <ul class=\"nav\" id=\"sectionmenu\">\n            {% for source in sourceList %}\n              <li><a href=\"{{ source.link }}\">{{ source.name }}</a></li>\n            {% endfor %}\n          </ul>\n          <div class=\"well\">\n            <button type=\"button\" class=\"btn btn-primary btn-lg btn-block\">\n              Get help\n            </button>\n            <div class=\"small text-center\">Get support from the TogetherJS team.</div>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"col-md-9\" id=\"source-content\">\n        <h1>TogetherJS Source Code</h1>\n\n        <dl>\n          {% for source in sourceList %}\n            <dt><code><a href=\"{{ source.link }}\">{{ source.name }}</a></code></dt>\n            <dd>{{ source.description }}</dd>\n          {% endfor %}\n        </dl>\n\n        <div class=\"small\"><a href=\"https://github.com/mozilla/togetherjs/\">See all files on Github</a></div>\n      </div>\n    </section>\n\n{% endblock %}\n"
  },
  {
    "path": "site/source-code.tmpl",
    "content": "{% extends \"base.tmpl\" %}\n{% block styles %}\n  <link rel=\"stylesheet\" href=\"{{ base }}css/docco.css\">\n  <script src=\"{{ base }}js/source-code.js\"></script>\n{% endblock %}\n{% block body %}\n\n<div class=\"container\">\n\n    <section class=\"row\" id=\"sourcecode\">\n      <div class=\"col-md-3\" id=\"source-toc\">\n        <div class=\"panel\" role=\"complementary\" data-spy=\"affix\" data-offset-top=\"200\" id=\"sidenav\">\n          <div class=\"panel-heading\">Source Code</div>\n          <ul class=\"nav\" id=\"sectionmenu\">\n            {% for source in sourceList %}\n              <li><a href=\"{{ source.link }}\">{{ source.name }}</a></li>\n            {% endfor %}\n          </ul>\n        </div>\n      </div>\n\n      <div class=\"col-md-9\" id=\"source-content\">\n        <h1>{{ source }}</h1>\n        {% if sourceDescription %}\n          <h4>{{ sourceDescription }}</h4>\n        {% endif %}\n\n        <div class=\"small\"><a href=\"https://github.com/mozilla/togetherjs/blob/develop/togetherjs/{{ source }}\">See this file on Github</a></div>\n\n        <ul class=\"sections\">\n          {% for section in sections %}\n            <li id=\"section-{{ section.index }}\">\n              <div class=\"annotation\">\n                <div class=\"pilwrap\">\n                  <a class=\"pilcrow\" href=\"#section-{{ section.index }}\">&#182;</a>\n                </div>\n                {{ section.docsHtml }}\n              </div>\n              {% if section.empty %}\n              {% else %}\n                <div class=\"content\">{{ section.codeHtml }}</div>\n              {% endif %}\n            </li>\n          {% endfor %}\n        </ul>\n      </div>\n    </section>\n\n\n\n{% endblock %}\n"
  },
  {
    "path": "site/the-developers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>The Developer's hangout</title>\n    <link rel=\"shortcut icon\" href=\"/images/fav-icon-bizarro.png\">\n    <script src=\"//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js\"></script>\n    <script>\n      TogetherJSConfig_suppressJoinConfirmation = true;\n      TogetherJSConfig_findRoom = \"developers\";\n      TogetherJSConfig_autoStart = true;\n    </script>\n    <link rel=\"stylesheet\" href=\"the-developers.css\">\n    <script src=\"/togetherjs.js\"></script>\n    <script src=\"the-developers.js\"></script>\n  </head>\n  <body>\n    <p>\n      Now just hang out and wait...\n      <button onclick=\"TogetherJS(this); return false\">Start/Stop</button>\n    </p>\n\n    <div id=\"record\"></div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "site/the-developers/the-developers.css",
    "content": "body {\n  font-family: sans-serif;\n  height: 100%;\n}\n\n#chat {\n  height: 90%;\n}\n\n#input {\n  width: 100%;\n}\n"
  },
  {
    "path": "site/the-developers/the-developers.js",
    "content": "$(function () {\n\n  TogetherJS.hub.on(\"togetherjs.invite\", function (msg) {\n    var div = $(\"<div />\");\n    div.text(\"Invite from: \" + msg.userInfo.name + \" at \" + (new Date()) + \" \");\n    div.append($(\"<a />\").attr(\"href\", msg.url).text(msg.url));\n    $(\"#record\").append(div);\n  });\n\n});\n"
  },
  {
    "path": "togetherjs/README.md",
    "content": "TogetherJS client\n=================\n\nThis is all the files for the TogetherJS client.\nAn overview of the modules:\n\n- `libs/`: contains external libraries, sometimes as [git subtree inclusions](https://github.com/apenwarr/git-subtree) and sometimes just copied in.\n\n- `analytics.js`: a little library for handling Google Analytics opt-in support\n\n- `channels.js`: abstraction over WebSockets and other communication methods (like `postMessage`).  Buffers output while the connection is opening, handles JSON encoding/decoding.\n\n- `chat.js`: handles the chat code, including logging old chat messages.  Doesn't actually include the chat UI, which is in `ui.js`\n\n- `cursor.js`: handles the shared cursors, both displaying and capturing events.  Also handles clicks.  This *does* include the relevant UI.\n\n- `elementFinder.js`: this generates a description/locator/path for any element, and finds elements based on those paths.  It generates something similar to a CSS selector.  It also includes a function to determine what elements should be ignored (generally TogetherJS's own elements).\n\n- `eventMaker.js`: this creates artificial events, like a fake click event.\n\n- `forms.js`: handles synchronization of forms, including CodeMirror and ACE support.\n\n- `jqueryPlugins.js`: some plugins for jQuery; doesn't export anything.\n\n- `linkify.js`: detects and adds links to plain text.\n\n- `ot.js`: operational transformation support: what keeps big chunks of text in sync when multiple people are simultaneously editing those fields.\n\n- `peers.js`: handles the objects representing the peers and oneself.\n\n- `playback.js`: handles the magic `/playback` command that plays recordings.\n\n- `randomutil.js`: some functions/methods for random numbers, really just for testing.\n\n- `recorder.js`: this is used by `recorder.html`, which is a kind of alternate mini-client used to record sessions when you put `/record` in the chat box.\n\n- `session.js`: probably the most important and most core module in the system.  This sets up the channels, routes messages, tracks peers, and is used for some communication (like `session.on(\"ui-ready\")` - which is actually signalled by `ui.js` but is fired on the session module).\n\n- `startup.js`: handles the logic of what to display when TogetherJS is first started up (including warning messages, introductory stuff, the share link, confirmation of joining the session)\n\n- `storage.js`: an abstraction of per-tab and client storage.  Mostly uses `localStorage` (or `sessionStorage`), but designed so it could use an async backed someday, perhaps.\n\n- `templates.js`: this is generated dynamically, and includes the `*.html` content as inlined strings.  Basically just a container for these strings.\n\n- `templating.js`: handles creating nodes based on DOM templates.  Does some substitution based on specific class names.\n\n- `togetherjs.js`: this is the bootstrap code.  It is included on all pages, defines the `TogetherJS` variable, and handles configuration and initial loading.\n\n- `ui.js`: this has most of the UI.  It loads the UI and binds most of the methods.  It's a jumble of UI stuff.  `ui.activateUI()` is the most important function.\n\n- `util.js`: several bits of abstract support code are in here.  It doesn't depend on other things, and has fairly abstract general-purpose code.  It includes a pattern for creating classes, assertions, events.\n\n- `walkthrough.js`: implements the walkthrough help.\n\n- `webrtc.js`: handles the live audio chat and avatar editing.\n\n- `windowing.js`: handles creating the different windows, notifications, and modal windows.\n"
  },
  {
    "path": "togetherjs/analytics.js",
    "content": "define([\"util\"], function (util) {\n  var analytics = util.Module(\"analytics\");\n\n  analytics.activate = function () {\n    var enable = TogetherJS.config.get(\"enableAnalytics\");\n    var code = TogetherJS.config.get(\"analyticsCode\");\n    TogetherJS.config.close(\"enableAnalytics\");\n    TogetherJS.config.close(\"analyticsCode\");\n    if (! (enable && code)) {\n      return;\n    }\n    // This is intended to be global:\n    var gaq = window._gaq || [];\n    gaq.push([\"_setAccount\", code]);\n    gaq.push(['_setDomainName', location.hostname]);\n    gaq.push([\"_trackPageview\"]);\n    window._gaq = gaq;\n\n    (function() {\n      var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n      ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n    })();\n  };\n\n  return analytics;\n});\n"
  },
  {
    "path": "togetherjs/channels.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/* Channel abstraction.  Supported channels:\n\n- WebSocket to an address\n- postMessage between windows\n\nIn the future:\n\n- XMLHttpRequest to a server (with some form of queuing)\n\nThe interface:\n\n  channel = new ChannelName(parameters)\n\nThe instantiation is specific to the kind of channel\n\nMethods:\n\n  onmessage: set to function (jsonData)\n  rawdata: set to true if you want onmessage to receive raw string data\n  onclose: set to function ()\n  send: function (string or jsonData)\n  close: function ()\n\n.send() will encode the data if it is not a string.\n\n(should I include readyState as an attribute?)\n\nChannels must accept messages immediately, caching if the connection\nis not fully established yet.\n\n*/\n\ndefine([\"util\"], function (util) {\n\nvar channels = util.Module(\"channels\");\n/* Subclasses must define:\n\n- ._send(string)\n- ._setupConnection()\n- ._ready()\n- .close() (and must set this.closed to true)\n\nAnd must call:\n\n- ._flush() on open\n- ._incoming(string) on incoming message\n- onclose() (not onmessage - instead _incoming)\n- emit(\"close\")\n*/\n\nvar AbstractChannel = util.mixinEvents({\n  onmessage: null,\n  rawdata: false,\n  onclose: null,\n  closed: false,\n\n  baseConstructor: function () {\n    this._buffer = [];\n    this._setupConnection();\n  },\n\n  send: function (data) {\n    if (this.closed) {\n      throw 'Cannot send to a closed connection';\n    }\n    if (typeof data != \"string\") {\n      data = JSON.stringify(data);\n    }\n    if (! this._ready()) {\n      this._buffer.push(data);\n      return;\n    }\n    this._send(data);\n  },\n\n  _flush: function () {\n    for (var i=0; i<this._buffer.length; i++) {\n      this._send(this._buffer[i]);\n    }\n    this._buffer = [];\n  },\n\n  _incoming: function (data) {\n    if (! this.rawdata) {\n      try {\n        data = JSON.parse(data);\n      } catch (e) {\n        console.error(\"Got invalid JSON data:\", data.substr(0, 40));\n        throw e;\n      }\n    }\n    if (this.onmessage) {\n      this.onmessage(data);\n    }\n    this.emit(\"message\", data);\n  }\n\n});\n\n\nchannels.WebSocketChannel = util.Class(AbstractChannel, {\n\n  constructor: function (address) {\n    if (address.search(/^https?:/i) === 0) {\n      address = address.replace(/^http/i, 'ws');\n    }\n    this.address = address;\n    this.socket = null;\n    this._reopening = false;\n    this._lastConnectTime = 0;\n    this._backoff = 0;\n    this.baseConstructor();\n  },\n\n  backoffTime: 50, // Milliseconds to add to each reconnect time\n  maxBackoffTime: 1500,\n  backoffDetection: 2000, // Amount of time since last connection attempt that shows we need to back off\n\n  toString: function () {\n    var s = '[WebSocketChannel to ' + this.address;\n    if (! this.socket) {\n      s += ' (socket unopened)';\n    } else {\n      s += ' readyState: ' + this.socket.readyState;\n    }\n    if (this.closed) {\n      s += ' CLOSED';\n    }\n    return s + ']';\n  },\n\n  close: function () {\n    this.closed = true;\n    if (this.socket) {\n      // socket.onclose will call this.onclose:\n      this.socket.close();\n    } else {\n      if (this.onclose) {\n        this.onclose();\n      }\n      this.emit(\"close\");\n    }\n  },\n\n  _send: function (data) {\n    this.socket.send(data);\n  },\n\n  _ready: function () {\n    return this.socket && this.socket.readyState == this.socket.OPEN;\n  },\n\n  _setupConnection: function () {\n    if (this.closed) {\n      return;\n    }\n    this._lastConnectTime = Date.now();\n    this.socket = new WebSocket(this.address);\n    this.socket.onopen = (function () {\n      this._flush();\n      this._reopening = false;\n    }).bind(this);\n    this.socket.onclose = (function (event) {\n      this.socket = null;\n      var method = \"error\";\n      if (event.wasClean) {\n        // FIXME: should I even log clean closes?\n        method = \"log\";\n      }\n      console[method]('WebSocket close', event.wasClean ? 'clean' : 'unclean',\n                      'code:', event.code, 'reason:', event.reason || 'none');\n      if (! this.closed) {\n        this._reopening = true;\n        if (Date.now() - this._lastConnectTime > this.backoffDetection) {\n          this._backoff = 0;\n        } else {\n          this._backoff++;\n        }\n        var time = Math.min(this._backoff * this.backoffTime, this.maxBackoffTime);\n        setTimeout((function () {\n          this._setupConnection();\n        }).bind(this), time);\n      }\n    }).bind(this);\n    this.socket.onmessage = (function (event) {\n      this._incoming(event.data);\n    }).bind(this);\n    this.socket.onerror = (function (event) {\n      console.error('WebSocket error:', event.data);\n    }).bind(this);\n  }\n\n});\n\n\n/* Sends TO a window or iframe */\nchannels.PostMessageChannel = util.Class(AbstractChannel, {\n  _pingPollPeriod: 100, // milliseconds\n  _pingPollIncrease: 100, // +100 milliseconds for each failure\n  _pingMax: 2000, // up to a max of 2000 milliseconds\n\n  constructor: function (win, expectedOrigin) {\n    this.expectedOrigin = expectedOrigin;\n    this._pingReceived = false;\n    this._receiveMessage = this._receiveMessage.bind(this);\n    if (win) {\n      this.bindWindow(win, true);\n    }\n    this._pingFailures = 0;\n    this.baseConstructor();\n  },\n\n  toString: function () {\n    var s = '[PostMessageChannel';\n    if (this.window) {\n      s += ' to window ' + this.window;\n    } else {\n      s += ' not bound to a window';\n    }\n    if (this.window && ! this._pingReceived) {\n      s += ' still establishing';\n    }\n    return s + ']';\n  },\n\n  bindWindow: function (win, noSetup) {\n    if (this.window) {\n      this.close();\n      // Though we deinitialized everything, we aren't exactly closed:\n      this.closed = false;\n    }\n    if (win && win.contentWindow) {\n      win = win.contentWindow;\n    }\n    this.window = win;\n    // FIXME: The distinction between this.window and window seems unimportant\n    // in the case of postMessage\n    var w = this.window;\n    // In a Content context we add the listener to the local window\n    // object, but in the addon context we add the listener to some\n    // other window, like the one we were given:\n    if (typeof window != \"undefined\") {\n      w = window;\n    }\n    w.addEventListener(\"message\", this._receiveMessage, false);\n    if (! noSetup) {\n      this._setupConnection();\n    }\n  },\n\n  _send: function (data) {\n    this.window.postMessage(data, this.expectedOrigin || \"*\");\n  },\n\n  _ready: function () {\n    return this.window && this._pingReceived;\n  },\n\n  _setupConnection: function () {\n    if (this.closed || this._pingReceived || (! this.window)) {\n      return;\n    }\n    this._pingFailures++;\n    this._send(\"hello\");\n    // We'll keep sending ping messages until we get a reply\n    var time = this._pingPollPeriod + (this._pingPollIncrease * this._pingFailures);\n    time = time > this._pingPollMax ? this._pingPollMax : time;\n    this._pingTimeout = setTimeout(this._setupConnection.bind(this), time);\n  },\n\n  _receiveMessage: function (event) {\n    if (event.source !== this.window) {\n      return;\n    }\n    if (this.expectedOrigin && event.origin != this.expectedOrigin) {\n      console.info(\"Expected message from\", this.expectedOrigin,\n                   \"but got message from\", event.origin);\n      return;\n    }\n    if (! this.expectedOrigin) {\n      this.expectedOrigin = event.origin;\n    }\n    if (event.data == \"hello\") {\n      this._pingReceived = true;\n      if (this._pingTimeout) {\n        clearTimeout(this._pingTimeout);\n        this._pingTimeout = null;\n      }\n      this._flush();\n      return;\n    }\n    this._incoming(event.data);\n  },\n\n  close: function () {\n    this.closed = true;\n    this._pingReceived = false;\n    if (this._pingTimeout) {\n      clearTimeout(this._pingTimeout);\n    }\n    window.removeEventListener(\"message\", this._receiveMessage, false);\n    if (this.onclose) {\n      this.onclose();\n    }\n    this.emit(\"close\");\n  }\n\n});\n\n\n/* Handles message FROM an exterior window/parent */\nchannels.PostMessageIncomingChannel = util.Class(AbstractChannel, {\n\n  constructor: function (expectedOrigin) {\n    this.source = null;\n    this.expectedOrigin = expectedOrigin;\n    this._receiveMessage = this._receiveMessage.bind(this);\n    window.addEventListener(\"message\", this._receiveMessage, false);\n    this.baseConstructor();\n  },\n\n  toString: function () {\n    var s = '[PostMessageIncomingChannel';\n    if (this.source) {\n      s += ' bound to source ' + s;\n    } else {\n      s += ' awaiting source';\n    }\n    return s + ']';\n  },\n\n  _send: function (data) {\n    this.source.postMessage(data, this.expectedOrigin);\n  },\n\n  _ready: function () {\n    return !!this.source;\n  },\n\n  _setupConnection: function () {\n  },\n\n  _receiveMessage: function (event) {\n    if (this.expectedOrigin && this.expectedOrigin != \"*\" &&\n        event.origin != this.expectedOrigin) {\n      // FIXME: Maybe not worth mentioning?\n      console.info(\"Expected message from\", this.expectedOrigin,\n                   \"but got message from\", event.origin);\n      return;\n    }\n    if (! this.expectedOrigin) {\n      this.expectedOrigin = event.origin;\n    }\n    if (! this.source) {\n      this.source = event.source;\n    }\n    if (event.data == \"hello\") {\n      // Just a ping\n      this.source.postMessage(\"hello\", this.expectedOrigin);\n      return;\n    }\n    this._incoming(event.data);\n  },\n\n  close: function () {\n    this.closed = true;\n    window.removeEventListener(\"message\", this._receiveMessage, false);\n    if (this._pingTimeout) {\n      clearTimeout(this._pingTimeout);\n    }\n    if (this.onclose) {\n      this.onclose();\n    }\n    this.emit(\"close\");\n  }\n\n});\n\nchannels.Router = util.Class(util.mixinEvents({\n\n  constructor: function (channel) {\n    this._channelMessage = this._channelMessage.bind(this);\n    this._channelClosed = this._channelClosed.bind(this);\n    this._routes = Object.create(null);\n    if (channel) {\n      this.bindChannel(channel);\n    }\n  },\n\n  bindChannel: function (channel) {\n    if (this.channel) {\n      this.channel.removeListener(\"message\", this._channelMessage);\n      this.channel.removeListener(\"close\", this._channelClosed);\n    }\n    this.channel = channel;\n    this.channel.on(\"message\", this._channelMessage.bind(this));\n    this.channel.on(\"close\", this._channelClosed.bind(this));\n  },\n\n  _channelMessage: function (msg) {\n    if (msg.type == \"route\") {\n      var id = msg.routeId;\n      var route = this._routes[id];\n      if (! route) {\n        console.warn(\"No route with the id\", id);\n        return;\n      }\n      if (msg.close) {\n        this._closeRoute(route.id);\n      } else {\n        if (route.onmessage) {\n          route.onmessage(msg.message);\n        }\n        route.emit(\"message\", msg.message);\n      }\n    }\n  },\n\n  _channelClosed: function () {\n    for (var id in this._routes) {\n      this._closeRoute(id);\n    }\n  },\n\n  _closeRoute: function (id) {\n    var route = this._routes[id];\n    if (route.onclose) {\n      route.onclose();\n    }\n    route.emit(\"close\");\n    delete this._routes[id];\n  },\n\n  makeRoute: function (id) {\n    id = id || util.generateId();\n    var route = Route(this, id);\n    this._routes[id] = route;\n    return route;\n  }\n}));\n\nvar Route = util.Class(util.mixinEvents({\n  constructor: function (router, id) {\n    this.router = router;\n    this.id = id;\n  },\n\n  send: function (msg) {\n    this.router.channel.send({\n      type: \"route\",\n      routeId: this.id,\n      message: msg\n    });\n  },\n\n  close: function () {\n    if (this.router._routes[this.id] !== this) {\n      // This route instance has been overwritten, so ignore\n      return;\n    }\n    delete this.router._routes[this.id];\n  }\n\n}));\n\nreturn channels;\n\n});\n"
  },
  {
    "path": "togetherjs/chat.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n/*jshint evil:true */\ndefine([\"require\", \"jquery\", \"util\", \"session\", \"ui\", \"templates\", \"playback\", \"storage\", \"peers\", \"windowing\"], function (require, $, util, session, ui, templates, playback, storage, peers, windowing) {\n  var chat = util.Module(\"chat\");\n  var assert = util.assert;\n  var Walkabout;\n\n  session.hub.on(\"chat\", function (msg) {\n    ui.chat.text({\n      text: msg.text,\n      peer: msg.peer,\n      // FIXME: a little unsure of trusting this (maybe I should prefix it?)\n      messageId: msg.messageId,\n      notify: true\n    });\n    saveChatMessage({\n      text: msg.text,\n      date: Date.now(),\n      peerId: msg.peer.id,\n      messageId: msg.messageId\n    });\n  });\n\n  // FIXME: this doesn't really belong in this module:\n  session.hub.on(\"bye\", function (msg) {\n    ui.chat.leftSession({\n      peer: msg.peer,\n      declinedJoin: msg.reason == \"declined-join\"\n    });\n  });\n\n  chat.submit = function (message) {\n    var parts = message.split(/ /);\n    if (parts[0].charAt(0) == \"/\") {\n      var name = parts[0].substr(1).toLowerCase();\n      var method = commands[\"command_\" + name];\n      if (method) {\n        method.apply(null, parts.slice(1));\n        return;\n      }\n    }\n    var messageId = session.clientId + \"-\" + Date.now();\n    session.send({\n      type: \"chat\",\n      text: message,\n      messageId: messageId\n    });\n    ui.chat.text({\n      text: message,\n      peer: peers.Self,\n      messageId: messageId,\n      notify: false\n    });\n    saveChatMessage({\n      text: message,\n      date: Date.now(),\n      peerId: peers.Self.id,\n      messageId: messageId\n    });\n  };\n\n  var commands = {\n    command_help: function () {\n      var msg = util.trim(templates(\"help\"));\n      ui.chat.system({\n        text: msg\n      });\n    },\n\n    command_test: function (args) {\n      if (! Walkabout) {\n        require([\"walkabout\"], (function (WalkaboutModule) {\n          Walkabout = WalkaboutModule;\n          this.command_test(args);\n        }).bind(this));\n        return;\n      }\n      args = util.trim(args || \"\").split(/\\s+/g);\n      if (args[0] === \"\" || ! args.length) {\n        if (this._testCancel) {\n          args = [\"cancel\"];\n        } else {\n          args = [\"start\"];\n        }\n      }\n      if (args[0] == \"cancel\") {\n        ui.chat.system({\n          text: \"Aborting test\"\n        });\n        this._testCancel();\n        this._testCancel = null;\n        return;\n      }\n      if (args[0] == \"start\") {\n        var times = parseInt(args[1], 10);\n        if (isNaN(times) || ! times) {\n          times = 100;\n        }\n        ui.chat.system({\n          text: \"Testing with walkabout.js\"\n        });\n        var tmpl = $(templates(\"walkabout\"));\n        var container = ui.container.find(\".togetherjs-test-container\");\n        container.empty();\n        container.append(tmpl);\n        container.show();\n        var statusContainer = container.find(\".togetherjs-status\");\n        statusContainer.text(\"starting...\");\n        this._testCancel = Walkabout.runManyActions({\n          ondone: function () {\n            statusContainer.text(\"done\");\n            statusContainer.one(\"click\", function () {\n              container.hide();\n            });\n            this._testCancel = null;\n          },\n          onstatus: function (status) {\n            var note = \"actions: \" + status.actions.length + \" running: \" +\n              (status.times - status.remaining) + \" / \" + status.times;\n            statusContainer.text(note);\n          }\n        });\n        return;\n      }\n      if (args[0] == \"show\") {\n        if (this._testShow.length) {\n          this._testShow.forEach(function (item) {\n            if (item) {\n              item.remove();\n            }\n          }, this);\n          this._testShow = [];\n        } else {\n          var actions = Walkabout.findActions();\n          actions.forEach(function (action) {\n            this._testShow.push(action.show());\n          }, this);\n        }\n        return;\n      }\n      if (args[0] == \"describe\") {\n        Walkabout.findActions().forEach(function (action) {\n          ui.chat.system({\n            text: action.description()\n          });\n        }, this);\n        return;\n      }\n      ui.chat.system({\n        text: \"Did not understand: \" + args.join(\" \")\n      });\n    },\n\n    _testCancel: null,\n    _testShow: [],\n\n    command_clear: function () {\n      ui.chat.clear();\n    },\n\n    command_exec: function () {\n      var expr = Array.prototype.slice.call(arguments).join(\" \");\n      var result;\n      // We use this to force global eval (not in this scope):\n      var e = eval;\n      try {\n        result = e(expr);\n      } catch (error) {\n        ui.chat.system({\n          text: \"Error: \" + error\n        });\n      }\n      if (result !== undefined) {\n        ui.chat.system({\n          text: \"\" + result\n        });\n      }\n    },\n\n    command_record: function () {\n      ui.chat.system({\n        text: \"When you see the robot appear, the recording will have started\"\n      });\n      window.open(\n        session.recordUrl(), \"_blank\",\n        \"left,width=\" + ($(window).width() / 2));\n    },\n\n    playing: null,\n\n    command_playback: function (url) {\n      if (this.playing) {\n        this.playing.cancel();\n        this.playing.unload();\n        this.playing = null;\n        ui.chat.system({\n          text: \"playback cancelled\"\n        });\n        return;\n      }\n      if (! url) {\n        ui.chat.system({\n          text: \"Nothing is playing\"\n        });\n        return;\n      }\n      var logLoader = playback.getLogs(url);\n      logLoader.then(\n        (function (logs) {\n          if (! logs) {\n            ui.chat.system({\n              text: \"No logs found.\"\n            });\n            return;\n          }\n          logs.save();\n          this.playing = logs;\n          logs.play();\n        }).bind(this),\n        function (error) {\n          ui.chat.system({\n            text: \"Error fetching \" + url + \":\\n\" + JSON.stringify(error, null, \"  \")\n          });\n        });\n      windowing.hide(\"#togetherjs-chat\");\n    },\n\n    command_savelogs: function (name) {\n      session.send({\n        type: \"get-logs\",\n        forClient: session.clientId,\n        saveAs: name\n      });\n      function save(msg) {\n        if (msg.request.forClient == session.clientId && msg.request.saveAs == name) {\n          storage.set(\"recording.\" + name, msg.logs).then(function () {\n            session.hub.off(\"logs\", save);\n            ui.chat.system({\n              text: \"Saved as local:\" + name\n            });\n          });\n        }\n      }\n      session.hub.on(\"logs\", save);\n    },\n\n    command_baseurl: function (url) {\n      if (! url) {\n        storage.get(\"baseUrlOverride\").then(function (b) {\n          if (b) {\n            ui.chat.system({\n              text: \"Set to: \" + b.baseUrl\n            });\n          } else {\n            ui.chat.system({\n              text: \"No baseUrl override set\"\n            });\n          }\n        });\n        return;\n      }\n      url = url.replace(/\\/*$/, \"\");\n      ui.chat.system({\n        text: \"If this goes wrong, do this in the console to reset:\\n  localStorage.setItem('togetherjs.baseUrlOverride', null)\"\n      });\n      storage.set(\"baseUrlOverride\", {\n        baseUrl: url,\n        expiresAt: Date.now() + (1000 * 60 * 60 * 24)\n      }).then(function () {\n        ui.chat.system({\n          text: \"baseUrl overridden (to \" + url + \"), will last for one day.\"\n        });\n      });\n    },\n\n    command_config: function (variable, value) {\n      if (! (variable || value)) {\n        storage.get(\"configOverride\").then(function (c) {\n          if (c) {\n            util.forEachAttr(c, function (value, attr) {\n              if (attr == \"expiresAt\") {\n                return;\n              }\n              ui.chat.system({\n                text: \"  \" + attr + \" = \" + JSON.stringify(value)\n              });\n            });\n            ui.chat.system({\n              text: \"Config expires at \" + (new Date(c.expiresAt))\n            });\n          } else {\n            ui.chat.system({\n              text: \"No config override\"\n            });\n          }\n        });\n        return;\n      }\n      if (variable == \"clear\") {\n        storage.set(\"configOverride\", undefined);\n        ui.chat.system({\n          text: \"Clearing all overridden configuration\"\n        });\n        return;\n      }\n      console.log(\"config\", [variable, value]);\n      if (! (variable && value)) {\n        ui.chat.system({\n          text: \"Error: must provide /config VAR VALUE\"\n        });\n        return;\n      }\n      try {\n        value = JSON.parse(value);\n      } catch (e) {\n        ui.chat.system({\n          text: \"Error: value (\" + value + \") could not be parsed: \" + e\n        });\n        return;\n      }\n      if (! TogetherJS._defaultConfiguration.hasOwnProperty(variable)) {\n        ui.chat.system({\n          text: \"Warning: variable \" + variable + \" is unknown\"\n        });\n      }\n      storage.get(\"configOverride\").then(function (c) {\n        c = c || {};\n        c[variable] = value;\n        c.expiresAt = Date.now() + (1000 * 60 * 60 * 24);\n        storage.set(\"configOverride\", c).then(function () {\n          ui.chat.system({\n            text: \"Variable \" + variable + \" = \" + JSON.stringify(value) + \"\\nValue will be set for one day.\"\n          });\n        });\n      });\n    }\n\n  };\n\n  // this section deal with saving/restoring chat history as long as session is alive\n  var chatStorageKey = \"chatlog\";\n  var maxLogMessages = 100;\n\n  function saveChatMessage(obj) {\n    assert(obj.peerId);\n    assert(obj.messageId);\n    assert(obj.date);\n    assert(typeof obj.text == \"string\");\n\n    loadChatLog().then(function (log) {\n      for (var i = log.length - 1; i >= 0; i--) {\n        if (log[i].messageId === obj.messageId) {\n          return;\n        }\n      }\n      log.push(obj);\n      if (log.length > maxLogMessages) {\n        log.splice(0, log.length - maxLogMessages);\n      }\n      storage.tab.set(chatStorageKey, log);\n    });\n  }\n\n  function loadChatLog() {\n    return storage.tab.get(chatStorageKey, []);\n  }\n\n  session.once(\"ui-ready\", function () {\n    loadChatLog().then(function (log) {\n      if (! log) {\n        return;\n      }\n      for (var i = 0; i < log.length; i++) {\n        // peers should already be loaded from sessionStorage by the peers module\n        var currentPeer = peers.getPeer(log[i].peerId, null, true);\n        if (!currentPeer) {\n          // sometimes peers go away\n          continue;\n        }\n        ui.chat.text({\n          text: log[i].text,\n          date: log[i].date,\n          peer: currentPeer,\n          messageId: log[i].messageId\n        });\n      }\n    });\n  });\n  //delete chat log\n  session.on(\"close\", function(){\n    storage.tab.set(chatStorageKey, undefined);\n  });\n\n  return chat;\n\n});\n"
  },
  {
    "path": "togetherjs/console.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\ndefine([\"util\"], function (util) {\n\n  var console = window.console || {log: function () {}};\n\n  var Console = util.Class({\n    constructor: function () {\n      this.messages = [];\n      this.level = this.levels.log;\n    },\n\n    messageLimit: 100,\n\n    levels: {\n      debug: 1,\n      // FIXME: I'm considering *not* wrapping console.log, and strictly keeping\n      // it as a debugging tool; also line numbers would be preserved\n      log: 2,\n      info: 3,\n      notify: 4,\n      warn: 5,\n      error: 6,\n      fatal: 7\n    },\n\n    // Gets set below:\n    maxLevel: 0,\n\n    consoleLevels: [\n      [],\n      console.debug || [],\n      console.log || [],\n      console.info || [],\n      console.notify || [],\n      console.warn || [],\n      console.error || [],\n      console.fatal || []\n    ],\n\n    levelNames: {},\n\n    setLevel: function (l) {\n      var number;\n      if (typeof l == \"string\") {\n        number = this.levels[l];\n        if (number === undefined) {\n          throw new Error(\"Tried to set Console level to unknown level string: \" + l);\n        }\n        l = number;\n      }\n      if (typeof l == \"function\") {\n        number = this.consoleLevels.indexOf(l);\n        if (number == -1) {\n          throw new Error(\"Tried to set Console level based on unknown console function: \" + l);\n        }\n        l = number;\n      }\n      if (typeof l == \"number\") {\n        if (l < 0) {\n          throw new Error(\"Console level must be 0 or larger: \" + l);\n        } else if (l > this.maxLevel) {\n          throw new Error(\"Console level must be \" + this.maxLevel + \" or smaller: \" + l);\n        }\n      }\n      this.level = l;\n    },\n\n    write: function (level) {\n      try {\n        this.messages.push([\n          Date.now(),\n          level,\n          this._stringify(Array.prototype.slice.call(arguments, 1))\n        ]);\n      } catch (e) {\n        console.warn(\"Error stringifying argument:\", e);\n      }\n      if (level != \"suppress\" && this.level <= level) {\n        var method = console[this.levelNames[level]];\n        if (! method) {\n          method = console.log;\n        }\n        method.apply(console, Array.prototype.slice.call(arguments, 1));\n      }\n    },\n\n    suppressedWrite: function () {\n      this.write.apply(this, [\"suppress\"].concat(Array.prototype.slice.call(arguments)));\n    },\n\n    trace: function (level) {\n      level = level || 'log';\n      if (console.trace) {\n        level = \"suppressedWrite\";\n      }\n      try {\n        throw new Error();\n      } catch (e) {\n        // FIXME: trim this frame\n        var stack = e.stack;\n        stack = stack.replace(/^[^\\n]*\\n/, \"\");\n        this[level](stack);\n      }\n      if (console.trace) {\n        console.trace();\n      }\n    },\n\n    _browserInfo: function () {\n      // FIXME: add TogetherJS version and\n      return [\n        \"TogetherJS base URL: \" + TogetherJS.baseUrl,\n        \"User Agent: \" + navigator.userAgent,\n        \"Page loaded: \" + this._formatDate(TogetherJS.pageLoaded),\n        \"Age: \" + this._formatMinutes(Date.now() - TogetherJS.pageLoaded) + \" minutes\",\n        // FIXME: make this right:\n        //\"Window: height: \" + window.screen.height + \" width: \" + window.screen.width\n        \"URL: \" + location.href,\n        \"------+------+----------------------------------------------\"\n      ];\n    },\n\n    _stringify: function (args) {\n      var s = \"\";\n      for (var i=0; i<args.length; i++) {\n        if (s) {\n          s += \" \";\n        }\n        s += this._stringifyItem(args[i]);\n      }\n      return s;\n    },\n\n    _stringifyItem: function (item) {\n      if (typeof item == \"string\") {\n        if (item === \"\") {\n          return '\"\"';\n        }\n        return item;\n      }\n      if (typeof item == \"object\" && item.repr) {\n        try {\n          return item.repr();\n        } catch (e) {\n          console.warn(\"Error getting object repr:\", item, e);\n        }\n      }\n      if (item !== null && typeof item == \"object\") {\n        // FIXME: this can drop lots of kinds of values, like a function or undefined\n        item = JSON.stringify(item);\n      }\n      return item.toString();\n    },\n\n    _formatDate: function (timestamp) {\n      return (new Date(timestamp)).toISOString();\n    },\n\n    _formatTime: function (timestamp) {\n      return ((timestamp - TogetherJS.pageLoaded) / 1000).toFixed(2);\n    },\n\n    _formatMinutes: function (milliseconds) {\n      var m = Math.floor(milliseconds / 1000 / 60);\n      var remaining = milliseconds - (m * 1000 * 60);\n      if (m > 10) {\n        // Over 10 minutes, just ignore the seconds\n        return m;\n      }\n      var seconds = Math.floor(remaining / 1000) + \"\";\n      m += \":\";\n      seconds = lpad(seconds, 2, \"0\");\n      m += seconds;\n      if (m == \"0:00\") {\n        m += ((remaining / 1000).toFixed(3) + \"\").substr(1);\n      }\n      return m;\n    },\n\n    _formatLevel: function (l) {\n      if (l === \"suppress\") {\n        return \"\";\n      }\n      return this.levelNames[l];\n    },\n\n    toString: function () {\n      try {\n        var lines = this._browserInfo();\n        this.messages.forEach(function (m) {\n          lines.push(lpad(this._formatTime(m[0]), 6) + \" \" + rpad(this._formatLevel(m[1]), 6) + \" \" + lpadLines(m[2], 14));\n        }, this);\n        return lines.join(\"\\n\");\n      } catch (e) {\n        // toString errors can otherwise be swallowed:\n        console.warn(\"Error running console.toString():\", e);\n        throw e;\n      }\n    },\n\n    submit: function (options) {\n      // FIXME: friendpaste is broken for this\n      // (and other pastebin sites aren't really Browser-accessible)\n      return util.Deferred(function (def) {\n        options = options || {};\n        var site = options.site || TogetherJS.config.get(\"pasteSite\") || \"https://www.friendpaste.com/\";\n        var req = new XMLHttpRequest();\n        req.open(\"POST\", site);\n        req.setRequestHeader(\"Content-Type\", \"application/json\");\n        req.send(JSON.stringify({\n          \"title\": options.title || \"TogetherJS log file\",\n          \"snippet\": this.toString(),\n          \"language\": \"text\"\n        }));\n        req.onreadystatechange = function () {\n          if (req.readyState === 4) {\n            var data = JSON.parse(req.responseText);\n          }\n        };\n      });\n    }\n\n  });\n\n  function rpad(s, len, pad) {\n    s = s + \"\";\n    pad = pad || \" \";\n    while (s.length < len) {\n      s += pad;\n    }\n    return s;\n  }\n\n  function lpad(s, len, pad) {\n    s = s + \"\";\n    pad = pad || \" \";\n    while (s.length < len) {\n      s = pad + s;\n    }\n    return s;\n  }\n\n  function lpadLines(s, len, pad) {\n    var i;\n    s = s + \"\";\n    if (s.indexOf(\"\\n\") == -1) {\n      return s;\n    }\n    pad = pad || \" \";\n    var fullPad = \"\";\n    for (i=0; i<len; i++) {\n      fullPad += pad;\n    }\n    s = s.split(/\\n/g);\n    for (i=1; i<s.length; i++) {\n      s[i] = fullPad + s[i];\n    }\n    return s.join(\"\\n\");\n  }\n\n\n\n  // This is a factory that creates `Console.prototype.debug`, `.error` etc:\n  function logFunction(name, level) {\n    return function () {\n      this.write.apply(this, [level].concat(Array.prototype.slice.call(arguments)));\n    };\n  }\n\n  util.forEachAttr(Console.prototype.levels, function (value, name) {\n    Console.prototype[name] = logFunction(name, value);\n    Console.prototype.maxLevel = Math.max(Console.prototype.maxLevel, value);\n  });\n\n  util.forEachAttr(Console.prototype.levels, function (value, name) {\n    Console.prototype.levelNames[value] = name;\n  });\n\n  var appConsole = Console();\n\n  appConsole.ConsoleClass = Console;\n\n  return appConsole;\n});\n"
  },
  {
    "path": "togetherjs/cursor.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// Cursor viewing support\n\ndefine([\"jquery\", \"ui\", \"util\", \"session\", \"elementFinder\", \"tinycolor\", \"eventMaker\", \"peers\", \"templating\"], function ($, ui, util, session, elementFinder, tinycolor, eventMaker, peers, templating) {\n  var assert = util.assert;\n  var cursor = util.Module(\"cursor\");\n\n  var FOREGROUND_COLORS = [\"#111\", \"#eee\"];\n  var CURSOR_HEIGHT = 50;\n  var CURSOR_ANGLE = (35 / 180) * Math.PI;\n  var CURSOR_WIDTH = Math.ceil(Math.sin(CURSOR_ANGLE) * CURSOR_HEIGHT);\n  // Number of milliseconds after page load in which a scroll-update\n  // related hello-back message will be processed:\n  var SCROLL_UPDATE_CUTOFF = 2000;\n\n  session.hub.on(\"cursor-update\", function (msg) {\n    if (msg.sameUrl) {\n      Cursor.getClient(msg.clientId).updatePosition(msg);\n    } else {\n      // FIXME: This should be caught even before the cursor-update message,\n      // when the peer goes to another URL\n      Cursor.getClient(msg.clientId).hideOtherUrl();\n    }\n  });\n\n  // FIXME: should check for a peer leaving and remove the cursor object\n  var Cursor = util.Class({\n\n    constructor: function (clientId) {\n      this.clientId = clientId;\n      this.element = templating.clone(\"cursor\");\n      this.elementClass = \"togetherjs-scrolled-normal\";\n      this.element.addClass(this.elementClass);\n      this.updatePeer(peers.getPeer(clientId));\n      this.lastTop = this.lastLeft = null;\n      $(document.body).append(this.element);\n      this.element.animateCursorEntry();\n      this.keydownTimeout = null;\n      this.clearKeydown = this.clearKeydown.bind(this);\n      this.atOtherUrl = false;\n    },\n\n    // How long after receiving a setKeydown call that we should show the\n    // user typing.  This should be more than MIN_KEYDOWN_TIME:\n    KEYDOWN_WAIT_TIME: 2000,\n\n    updatePeer: function (peer) {\n      // FIXME: can I use peer.setElement()?\n      this.element.css({color: peer.color});\n      var img = this.element.find(\"img.togetherjs-cursor-img\");\n      img.attr(\"src\", makeCursor(peer.color));\n      var name = this.element.find(\".togetherjs-cursor-name\");\n      var nameContainer = this.element.find(\".togetherjs-cursor-container\");\n      assert(name.length);\n      name.text(peer.name);\n      nameContainer.css({\n        backgroundColor: peer.color,\n        color: tinycolor.mostReadable(peer.color, FOREGROUND_COLORS)\n      });\n      var path = this.element.find(\"svg path\");\n      path.attr(\"fill\", peer.color);\n      // FIXME: should I just remove the element?\n      if (peer.status != \"live\") {\n        //this.element.hide();\n        this.element.find(\"svg\").animate({\n          opacity: 0\n        }, 350);\n        this.element.find(\".togetherjs-cursor-container\").animate({\n                width: 34,\n                height: 20,\n                padding: 12,\n                margin: 0\n            }, 200).animate({\n                width: 0,\n                height: 0,\n                padding: 0,\n                opacity: 0\n                }, 200);\n      } else {\n        //this.element.show();\n        this.element.animate({\n          opacity:0.3\n        }).animate({\n          opacity:1\n        });\n      }\n    },\n\n    setClass: function (name) {\n      if (name != this.elementClass) {\n        this.element.removeClass(this.elementClass).addClass(name);\n        this.elementClass = name;\n      }\n    },\n\n    updatePosition: function (pos) {\n      var top, left;\n      if (this.atOtherUrl) {\n        this.element.show();\n        this.atOtherUrl = false;\n      }\n      if (pos.element) {\n        var target = $(elementFinder.findElement(pos.element));\n        var offset = target.offset();\n        top = offset.top + pos.offsetY;\n        left = offset.left + pos.offsetX;\n      } else {\n        // No anchor, just an absolute position\n        top = pos.top;\n        left = pos.left;\n      }\n      // These are saved for use by .refresh():\n      this.lastTop = top;\n      this.lastLeft = left;\n      this.setPosition(top, left);\n    },\n\n    hideOtherUrl: function () {\n      if (this.atOtherUrl) {\n        return;\n      }\n      this.atOtherUrl = true;\n      // FIXME: should show away status better:\n      this.element.hide();\n    },\n\n    // place Cursor rotate function down here FIXME: this doesnt do anything anymore.  This is in the CSS as an animation\n    rotateCursorDown: function(){\n      var e = $(this.element).find('svg');\n        e.animate({borderSpacing: -150, opacity: 1}, {\n        step: function(now, fx) {\n          if (fx.prop == \"borderSpacing\") {\n            e.css('-webkit-transform', 'rotate('+now+'deg)')\n              .css('-moz-transform', 'rotate('+now+'deg)')\n              .css('-ms-transform', 'rotate('+now+'deg)')\n              .css('-o-transform', 'rotate('+now+'deg)')\n              .css('transform', 'rotate('+now+'deg)');\n          } else {\n            e.css(fx.prop, now);\n          }\n        },\n        duration: 500\n      }, 'linear').promise().then(function () {\n        e.css('-webkit-transform', '')\n          .css('-moz-transform', '')\n          .css('-ms-transform', '')\n          .css('-o-transform', '')\n          .css('transform', '')\n          .css(\"opacity\", \"\");\n      });\n    },\n\n    setPosition: function (top, left) {\n      var wTop = $(window).scrollTop();\n      var height = $(window).height();\n\n      if (top < wTop) {\n        // FIXME: this is a totally arbitrary number, but is meant to be big enough\n        // to keep the cursor name from being off the top of the screen.\n        top = 25;\n        this.setClass(\"togetherjs-scrolled-above\");\n      } else if (top > wTop + height - CURSOR_HEIGHT) {\n        top = height - CURSOR_HEIGHT - 5;\n        this.setClass(\"togetherjs-scrolled-below\");\n      } else {\n        this.setClass(\"togetherjs-scrolled-normal\");\n      }\n      this.element.css({\n        top: top,\n        left: left\n      });\n    },\n\n    refresh: function () {\n      if (this.lastTop !== null) {\n        this.setPosition(this.lastTop, this.lastLeft);\n      }\n    },\n\n    setKeydown: function () {\n      if (this.keydownTimeout) {\n        clearTimeout(this.keydownTimeout);\n      } else {\n        this.element.find(\".togetherjs-cursor-typing\").show().animateKeyboard();\n      }\n      this.keydownTimeout = setTimeout(this.clearKeydown, this.KEYDOWN_WAIT_TIME);\n    },\n\n    clearKeydown: function () {\n      this.keydownTimeout = null;\n      this.element.find(\".togetherjs-cursor-typing\").hide().stopKeyboardAnimation();\n    },\n\n    _destroy: function () {\n      this.element.remove();\n      this.element = null;\n    }\n  });\n\n  Cursor._cursors = {};\n\n  cursor.getClient = Cursor.getClient = function (clientId) {\n    var c = Cursor._cursors[clientId];\n    if (! c) {\n      c = Cursor._cursors[clientId] = Cursor(clientId);\n    }\n    return c;\n  };\n\n  Cursor.forEach = function (callback, context) {\n    context = context || null;\n    for (var a in Cursor._cursors) {\n      if (Cursor._cursors.hasOwnProperty(a)) {\n        callback.call(context, Cursor._cursors[a], a);\n      }\n    }\n  };\n\n  Cursor.destroy = function (clientId) {\n    Cursor._cursors[clientId]._destroy();\n    delete Cursor._cursors[clientId];\n  };\n\n  peers.on(\"new-peer identity-updated status-updated\", function (peer) {\n    var c = Cursor.getClient(peer.id);\n    c.updatePeer(peer);\n  });\n\n  var lastTime = 0;\n  var MIN_TIME = 100;\n  var lastPosX = -1;\n  var lastPosY = -1;\n  var lastMessage = null;\n  function mousemove(event) {\n    var now = Date.now();\n    if (now - lastTime < MIN_TIME) {\n      return;\n    }\n    lastTime = now;\n    var pageX = event.pageX;\n    var pageY = event.pageY;\n    if (Math.abs(lastPosX - pageX) < 3 && Math.abs(lastPosY - pageY) < 3) {\n      // Not a substantial enough change\n      return;\n    }\n    lastPosX = pageX;\n    lastPosY = pageY;\n    var target = event.target;\n    var parent = $(target).closest(\".togetherjs-window, .togetherjs-popup, #togetherjs-dock\");\n    if (parent.length) {\n      target = parent[0];\n    } else if (elementFinder.ignoreElement(target)) {\n      target = null;\n    }\n    if ((! target) || target == document.documentElement || target == document.body) {\n      lastMessage = {\n        type: \"cursor-update\",\n        top: pageY,\n        left: pageX\n      };\n      session.send(lastMessage);\n      return;\n    }\n    target = $(target);\n    var offset = target.offset();\n    if (! offset) {\n      // FIXME: this really is walkabout.js's problem to fire events on the\n      // document instead of a specific element\n      console.warn(\"Could not get offset of element:\", target[0]);\n      return;\n    }\n    var offsetX = pageX - offset.left;\n    var offsetY = pageY - offset.top;\n    lastMessage = {\n      type: \"cursor-update\",\n      element: elementFinder.elementLocation(target),\n      offsetX: Math.floor(offsetX),\n      offsetY: Math.floor(offsetY)\n    };\n    session.send(lastMessage);\n  }\n\n  function makeCursor(color) {\n    var canvas = $(\"<canvas></canvas>\");\n    canvas.attr(\"height\", CURSOR_HEIGHT);\n    canvas.attr(\"width\", CURSOR_WIDTH);\n    var context = canvas[0].getContext('2d');\n    context.fillStyle = color;\n    context.moveTo(0, 0);\n    context.beginPath();\n    context.lineTo(0, CURSOR_HEIGHT/1.2);\n    context.lineTo(Math.sin(CURSOR_ANGLE/2) * CURSOR_HEIGHT / 1.5,\n                   Math.cos(CURSOR_ANGLE/2) * CURSOR_HEIGHT / 1.5);\n    context.lineTo(Math.sin(CURSOR_ANGLE) * CURSOR_HEIGHT / 1.2,\n                   Math.cos(CURSOR_ANGLE) * CURSOR_HEIGHT / 1.2);\n    context.lineTo(0, 0);\n    context.shadowColor = 'rgba(0,0,0,0.3)';\n    context.shadowBlur = 2;\n    context.shadowOffsetX = 1;\n    context.shadowOffsetY = 2;\n\tcontext.strokeStyle = \"#ffffff\";\n\tcontext.stroke();\n    context.fill();\n    return canvas[0].toDataURL(\"image/png\");\n  }\n\n  var scrollTimeout = null;\n  var scrollTimeoutSet = 0;\n  var SCROLL_DELAY_TIMEOUT = 75;\n  var SCROLL_DELAY_LIMIT = 300;\n\n  function scroll() {\n    var now = Date.now();\n    if (scrollTimeout) {\n      if (now - scrollTimeoutSet < SCROLL_DELAY_LIMIT) {\n        clearTimeout(scrollTimeout);\n      } else {\n        // Just let it progress anyway\n        return;\n      }\n    }\n    scrollTimeout = setTimeout(_scrollRefresh, SCROLL_DELAY_TIMEOUT);\n    if (! scrollTimeoutSet) {\n      scrollTimeoutSet = now;\n    }\n  }\n\n  var lastScrollMessage = null;\n  function _scrollRefresh() {\n    scrollTimeout = null;\n    scrollTimeoutSet = 0;\n    Cursor.forEach(function (c) {\n      c.refresh();\n    });\n    lastScrollMessage = {\n      type: \"scroll-update\",\n      position: elementFinder.elementByPixel($(window).scrollTop())\n    };\n    session.send(lastScrollMessage);\n  }\n\n  // FIXME: do the same thing for cursor position?  And give up on the\n  // ad hoc update-on-hello?\n  session.on(\"prepare-hello\", function (helloMessage) {\n    if (lastScrollMessage) {\n      helloMessage.scrollPosition = lastScrollMessage.position;\n    }\n  });\n\n  session.hub.on(\"scroll-update\", function (msg) {\n    msg.peer.scrollPosition = msg.position;\n    if (msg.peer.following) {\n      msg.peer.view.scrollTo();\n    }\n  });\n\n  // In case there are multiple peers, we track that we've accepted one of their\n  // hello-based scroll updates, just so we don't bounce around (we don't intelligently\n  // choose which one to use, just the first that comes in)\n  var acceptedScrollUpdate = false;\n  session.hub.on(\"hello-back hello\", function (msg) {\n    if (msg.type == \"hello\") {\n      // Once a hello comes in, a bunch of hello-backs not intended for us will also\n      // come in, and we should ignore them\n      acceptedScrollUpdate = true;\n    }\n    if (! msg.scrollPosition) {\n      return;\n    }\n    msg.peer.scrollPosition = msg.scrollPosition;\n    if ((! acceptedScrollUpdate) &&\n        msg.sameUrl &&\n        Date.now() - session.timeHelloSent < SCROLL_UPDATE_CUTOFF) {\n      acceptedScrollUpdate = true;\n      msg.peer.view.scrollTo();\n    }\n  });\n\n  session.on(\"ui-ready\", function () {\n    $(document).mousemove(mousemove);\n    document.addEventListener(\"click\", documentClick, true);\n    document.addEventListener(\"keydown\", documentKeydown, true);\n    $(window).scroll(scroll);\n    scroll();\n  });\n\n  session.on(\"close\", function () {\n    Cursor.forEach(function (c, clientId) {\n      Cursor.destroy(clientId);\n    });\n    $(document).unbind(\"mousemove\", mousemove);\n    document.removeEventListener(\"click\", documentClick, true);\n    document.removeEventListener(\"keydown\", documentKeydown, true);\n    $(window).unbind(\"scroll\", scroll);\n  });\n\n  session.hub.on(\"hello\", function (msg) {\n    // Immediately get our cursor onto this new person's screen:\n    if (lastMessage) {\n      session.send(lastMessage);\n    }\n    if (lastScrollMessage) {\n      session.send(lastScrollMessage);\n    }\n  });\n\n  function documentClick(event) {\n    if (event.togetherjsInternal) {\n      // This is an artificial internal event\n      return;\n    }\n    // FIXME: this might just be my imagination, but somehow I just\n    // really don't want to do anything at this stage of the event\n    // handling (since I'm catching every click), and I'll just do\n    // something real soon:\n    setTimeout(function () {\n      if (! TogetherJS.running) {\n        // This can end up running right after TogetherJS has been closed, often\n        // because TogetherJS was closed with a click...\n        return;\n      }\n      var element = event.target;\n      if (element == document.documentElement) {\n        // For some reason clicking on <body> gives the <html> element here\n        element = document.body;\n      }\n      if (elementFinder.ignoreElement(element)) {\n        return;\n      }\n      //Prevent click events on video objects to avoid conflicts with\n      //togetherjs's own video events\n      if (element.nodeName.toLowerCase() === 'video'){\n        return;\n      }\n\n      var dontShowClicks = TogetherJS.config.get(\"dontShowClicks\");\n      var cloneClicks = TogetherJS.config.get(\"cloneClicks\");\n      // If you dont want to clone the click for this element\n      // and you dont want to show the click for this element or you dont want to show any clicks\n      // then return to avoid sending a useless click\n      if ((! util.matchElement(element, cloneClicks)) && util.matchElement(element, dontShowClicks)) {\n        return;\n      }\n      var location = elementFinder.elementLocation(element);\n      var offset = $(element).offset();\n      var offsetX = event.pageX - offset.left;\n      var offsetY = event.pageY - offset.top;\n      session.send({\n        type: \"cursor-click\",\n        element: location,\n        offsetX: offsetX,\n        offsetY: offsetY\n      });\n      if (util.matchElement(element, dontShowClicks)) {\n        return;\n      }\n      displayClick({top: event.pageY, left: event.pageX}, peers.Self.color);\n    });\n  }\n\n  var CLICK_TRANSITION_TIME = 3000;\n\n  session.hub.on(\"cursor-click\", function (pos) {\n    // When the click is calculated isn't always the same as how the\n    // last cursor update was calculated, so we force the cursor to\n    // the last location during a click:\n    if (! pos.sameUrl) {\n      // FIXME: if we *could have* done a local click, but we follow along\n      // later, we'll be in different states if that click was important.\n      // Mostly click cloning just won't work.\n      return;\n    }\n    Cursor.getClient(pos.clientId).updatePosition(pos);\n    var target = $(elementFinder.findElement(pos.element));\n    var offset = target.offset();\n    var top = offset.top + pos.offsetY;\n    var left = offset.left + pos.offsetX;\n    var cloneClicks = TogetherJS.config.get(\"cloneClicks\");\n    if (util.matchElement(target, cloneClicks)) {\n      eventMaker.performClick(target);\n    }\n    var dontShowClicks = TogetherJS.config.get(\"dontShowClicks\");\n    if (util.matchElement(target, dontShowClicks)) {\n      return;\n    }\n    displayClick({top: top, left: left}, pos.peer.color);\n  });\n\n  function displayClick(pos, color) {\n    // FIXME: should we hide the local click if no one else is going to see it?\n    // That means tracking who might be able to see our screen.\n    var element = templating.clone(\"click\");\n    $(document.body).append(element);\n    element.css({\n      top: pos.top,\n      left: pos.left,\n      borderColor: color\n    });\n    setTimeout(function () {\n      element.addClass(\"togetherjs-clicking\");\n    }, 100);\n    setTimeout(function () {\n      element.remove();\n    }, CLICK_TRANSITION_TIME);\n  }\n\n  var lastKeydown = 0;\n  var MIN_KEYDOWN_TIME = 500;\n\n  function documentKeydown(event) {\n    setTimeout(function () {\n      var now = Date.now();\n      if (now - lastKeydown < MIN_KEYDOWN_TIME) {\n        return;\n      }\n      lastKeydown = now;\n      // FIXME: is event.target interesting here?  That is, *what* the\n      // user is typing into, not just that the user is typing?  Also\n      // I'm assuming we don't care if the user it typing into a\n      // togetherjs-related field, since chat activity is as interesting\n      // as any other activity.\n      session.send({type: \"keydown\"});\n    });\n  }\n\n  session.hub.on(\"keydown\", function (msg) {\n    // FIXME: when the cursor is hidden there's nothing to show with setKeydown().\n    var cursor = Cursor.getClient(msg.clientId);\n    cursor.setKeydown();\n  });\n\n  util.testExpose({Cursor: Cursor});\n\n  return cursor;\n\n});\n"
  },
  {
    "path": "togetherjs/elementFinder.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"util\", \"jquery\"], function (util, $) {\n  var elementFinder = util.Module(\"elementFinder\");\n  var assert = util.assert;\n\n  elementFinder.ignoreElement = function ignoreElement(el) {\n    if (el instanceof $) {\n      el = el[0];\n    }\n    while (el) {\n      if ($(el).hasClass(\"togetherjs\")) {\n        return true;\n      }\n      el = el.parentNode;\n    }\n    return false;\n  };\n\n  elementFinder.elementLocation = function elementLocation(el) {\n    assert(el !== null, \"Got null element\");\n    if (el instanceof $) {\n      // a jQuery element\n      el = el[0];\n    }\n    if (el[0] && el.attr && el[0].nodeType == 1) {\n      // Or a jQuery element not made by us\n      el = el[0];\n    }\n    if (el.id) {\n      return \"#\" + el.id;\n    }\n    if (el.tagName == \"BODY\") {\n      return \"body\";\n    }\n    if (el.tagName == \"HEAD\") {\n      return \"head\";\n    }\n    if (el === document) {\n      return \"document\";\n    }\n    var parent = el.parentNode;\n    if ((! parent) || parent == el) {\n      console.warn(\"elementLocation(\", el, \") has null parent\");\n      throw new Error(\"No locatable parent found\");\n    }\n    var parentLocation = elementLocation(parent);\n    var children = parent.childNodes;\n    var _len = children.length;\n    var index = 0;\n    for (var i=0; i<_len; i++) {\n      if (children[i] == el) {\n        break;\n      }\n      if (children[i].nodeType == document.ELEMENT_NODE) {\n        if (children[i].className.indexOf(\"togetherjs\") != -1) {\n          // Don't count our UI\n          continue;\n        }\n        // Don't count text or comments\n        index++;\n      }\n    }\n    return parentLocation + \":nth-child(\" + (index+1) + \")\";\n  };\n\n  elementFinder.CannotFind = util.Class({\n    constructor: function CannotFind(location, reason, context) {\n      this.prefix = \"\";\n      this.location = location;\n      this.reason = reason;\n      this.context = context;\n    },\n    toString: function () {\n      var loc;\n      try {\n        loc = elementFinder.elementLocation(this.context);\n      } catch (e) {\n        loc = this.context;\n      }\n      return (\n        \"[CannotFind \" + this.prefix +\n          \"(\" + this.location + \"): \" +\n          this.reason + \" in \" +\n          loc + \"]\");\n    }\n  });\n\n  elementFinder.findElement = function findElement(loc, container) {\n    // FIXME: should this all just be done with document.querySelector()?\n    // But no!  We can't ignore togetherjs elements with querySelector.\n    // But maybe!  We *could* make togetherjs elements less obtrusive?\n    container = container || document;\n    var el, rest;\n    if (loc === \"body\") {\n      return document.body;\n    } else if (loc === \"head\") {\n      return document.head;\n    } else if (loc === \"document\") {\n      return document;\n    } else if (loc.indexOf(\"body\") === 0) {\n      el = document.body;\n      try {\n        return findElement(loc.substr((\"body\").length), el);\n      } catch (e) {\n        if (e instanceof elementFinder.CannotFind) {\n          e.prefix = \"body\" + e.prefix;\n        }\n        throw e;\n      }\n    } else if (loc.indexOf(\"head\") === 0) {\n      el = document.head;\n      try {\n        return findElement(loc.substr((\"head\").length), el);\n      } catch (e) {\n        if (e instanceof elementFinder.CannotFind) {\n          e.prefix = \"head\" + e.prefix;\n        }\n        throw e;\n      }\n    } else if (loc.indexOf(\"#\") === 0) {\n      var id;\n      loc = loc.substr(1);\n      if (loc.indexOf(\":\") === -1) {\n        id = loc;\n        rest = \"\";\n      } else {\n        id = loc.substr(0, loc.indexOf(\":\"));\n        rest = loc.substr(loc.indexOf(\":\"));\n      }\n      el = document.getElementById(id);\n      if (! el) {\n        throw elementFinder.CannotFind(\"#\" + id, \"No element by that id\", container);\n      }\n      if (rest) {\n        try {\n          return findElement(rest, el);\n        } catch (e) {\n          if (e instanceof elementFinder.CannotFind) {\n            e.prefix = \"#\" + id + e.prefix;\n          }\n          throw e;\n        }\n      } else {\n        return el;\n      }\n    } else if (loc.indexOf(\":nth-child(\") === 0) {\n      loc = loc.substr((\":nth-child(\").length);\n      if (loc.indexOf(\")\") == -1) {\n        throw \"Invalid location, missing ): \" + loc;\n      }\n      var num = loc.substr(0, loc.indexOf(\")\"));\n      num = parseInt(num, 10);\n      var count = num;\n      loc = loc.substr(loc.indexOf(\")\") + 1);\n      var children = container.childNodes;\n      el = null;\n      for (var i=0; i<children.length; i++) {\n        var child = children[i];\n        if (child.nodeType == document.ELEMENT_NODE) {\n          if (child.className.indexOf(\"togetherjs\") != -1) {\n            continue;\n          }\n          count--;\n          if (count === 0) {\n            // this is the element\n            el = child;\n            break;\n          }\n        }\n      }\n      if (! el) {\n        throw elementFinder.CannotFind(\":nth-child(\" + num + \")\", \"container only has \" + (num - count) + \" elements\", container);\n      }\n      if (loc) {\n        try {\n          return elementFinder.findElement(loc, el);\n        } catch (e) {\n          if (e instanceof elementFinder.CannotFind) {\n            e.prefix = \":nth-child(\" + num + \")\" + e.prefix;\n          }\n          throw e;\n        }\n      } else {\n        return el;\n      }\n    } else {\n      throw elementFinder.CannotFind(loc, \"Malformed location\", container);\n    }\n  };\n\n  elementFinder.elementByPixel = function (height) {\n    /* Returns {location: \"...\", offset: pixels}\n\n       To get the pixel position back, you'd do:\n         $(location).offset().top + offset\n     */\n    function search(start, height) {\n      var last = null;\n      var children = start.children();\n      children.each(function () {\n        var el = $(this);\n        if (el.hasClass(\"togetherjs\") || el.css(\"position\") == \"fixed\" || ! el.is(\":visible\")) {\n          return;\n        }\n        if (el.offset().top > height) {\n          return false;\n        }\n        last = el;\n      });\n      if ((! children.length) || (! last)) {\n        // There are no children, or only inapplicable children\n        return {\n          location: elementFinder.elementLocation(start[0]),\n          offset: height - start.offset().top,\n          absoluteTop: height,\n          documentHeight: $(document).height()\n        };\n      }\n      return search(last, height);\n    }\n    return search($(document.body), height);\n  };\n\n  elementFinder.pixelForPosition = function (position) {\n    /* Inverse of elementFinder.elementByPixel */\n    if (position.location == \"body\") {\n      return position.offset;\n    }\n    var el;\n    try {\n      el = elementFinder.findElement(position.location);\n    } catch (e) {\n      if (e instanceof elementFinder.CannotFind && position.absoluteTop) {\n        // We don't trust absoluteTop to be quite right locally, so we adjust\n        // for the total document height differences:\n        var percent = position.absoluteTop / position.documentHeight;\n        return $(document).height() * percent;\n      }\n      throw e;\n    }\n    var top = $(el).offset().top;\n    // FIXME: maybe here we should test for sanity, like if an element is\n    // hidden.  We can use position.absoluteTop to get a sense of where the\n    // element roughly should be.  If the sanity check failed we'd use\n    // absoluteTop\n    return top + position.offset;\n  };\n\n  return elementFinder;\n\n});\n"
  },
  {
    "path": "togetherjs/eventMaker.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"jquery\", \"util\"], function ($, util) {\n  var eventMaker = util.Module(\"eventMaker\");\n\n  eventMaker.performClick = function (target) {\n    // FIXME: should accept other parameters, like Ctrl/Alt/etc\n    var event = document.createEvent(\"MouseEvents\");\n    event.initMouseEvent(\n      \"click\", // type\n      true, // canBubble\n      true, // cancelable\n      window, // view\n      0, // detail\n      0, // screenX\n      0, // screenY\n      0, // clientX\n      0, // clientY\n      false, // ctrlKey\n      false, // altKey\n      false, // shiftKey\n      false, // metaKey\n      0, // button\n      null // relatedTarget\n    );\n    // FIXME: I'm not sure this custom attribute always propagates?\n    // seems okay in Firefox/Chrome, but I've had problems with\n    // setting attributes on keyboard events in the past.\n    event.togetherjsInternal = true;\n    target = $(target)[0];\n    var cancelled = target.dispatchEvent(event);\n    if (cancelled) {\n      return;\n    }\n    if (target.tagName == \"A\") {\n      var href = target.href;\n      if (href) {\n        location.href = href;\n        return;\n      }\n    }\n    // FIXME: should do button clicks (like a form submit)\n    // FIXME: should run .onclick() as well\n  };\n\n  eventMaker.fireChange = function (target) {\n    target = $(target)[0];\n    var event = document.createEvent(\"HTMLEvents\");\n    event.initEvent(\"change\", true, true);\n    target.dispatchEvent(event);\n  };\n\n  return eventMaker;\n});\n"
  },
  {
    "path": "togetherjs/forms.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"jquery\", \"util\", \"session\", \"elementFinder\", \"eventMaker\", \"templating\", \"ot\"], function ($, util, session, elementFinder, eventMaker, templating, ot) {\n  var forms = util.Module(\"forms\");\n  var assert = util.assert;\n\n  // This is how much larger the focus element is than the element it surrounds\n  // (this is padding on each side)\n  var FOCUS_BUFFER = 5;\n\n  var inRemoteUpdate = false;\n\n  function suppressSync(element) {\n    var ignoreForms = TogetherJS.config.get(\"ignoreForms\");\n    if (ignoreForms === true) {\n      return true;\n    }\n    else {\n      return $(element).is(ignoreForms.join(\",\")); \n    }\n  }\n\n  function maybeChange(event) {\n    // Called when we get an event that may or may not indicate a real change\n    // (like keyup in a textarea)\n    var tag = event.target.tagName;\n    if (tag == \"TEXTAREA\" || tag == \"INPUT\") {\n      change(event);\n    }\n  }\n\n  function change(event) {\n    sendData({\n      element: event.target,\n      value: getValue(event.target)\n    });\n  }\n\n  function sendData(attrs) {\n    var el = $(attrs.element);\n    assert(el);\n    var tracker = attrs.tracker;\n    var value = attrs.value;\n    if (inRemoteUpdate) {\n      return;\n    }\n    if (elementFinder.ignoreElement(el) ||\n        (elementTracked(el) && !tracker) ||\n        suppressSync(el)) {\n      return;\n    }\n    var location = elementFinder.elementLocation(el);\n    var msg = {\n      type: \"form-update\",\n      element: location\n    };\n    if (isText(el) || tracker) {\n      var history = el.data(\"togetherjsHistory\");\n      if (history) {\n        if (history.current == value) {\n          return;\n        }\n        var delta = ot.TextReplace.fromChange(history.current, value);\n        assert(delta);\n        history.add(delta);\n        maybeSendUpdate(msg.element, history, tracker);\n        return;\n      } else {\n        msg.value = value;\n        msg.basis = 1;\n        el.data(\"togetherjsHistory\", ot.SimpleHistory(session.clientId, value, 1));\n      }\n    } else {\n      msg.value = value;\n    }\n    session.send(msg);\n  }\n\n  function isCheckable(el) {\n    el = $(el);\n    var type = (el.prop(\"type\") || \"text\").toLowerCase();\n    if (el.prop(\"tagName\") == \"INPUT\" && [\"radio\", \"checkbox\"].indexOf(type) != -1) {\n      return true;\n    }\n    return false;\n  }\n\n  var editTrackers = {};\n  var liveTrackers = [];\n\n  TogetherJS.addTracker = function (TrackerClass, skipSetInit) {\n    assert(typeof TrackerClass === \"function\", \"You must pass in a class\");\n    assert(typeof TrackerClass.prototype.trackerName === \"string\",\n           \"Needs a .prototype.trackerName string\");\n    // Test for required instance methods.\n    \"destroy update init makeInit tracked\".split(/ /).forEach(function(m) {\n      assert(typeof TrackerClass.prototype[m] === \"function\",\n             \"Missing required tracker method: \"+m);\n    });\n    // Test for required class methods.\n    \"scan tracked\".split(/ /).forEach(function(m) {\n      assert(typeof TrackerClass[m] === \"function\",\n             \"Missing required tracker class method: \"+m);\n    });\n    editTrackers[TrackerClass.prototype.trackerName] = TrackerClass;\n    if (!skipSetInit) {\n      setInit();\n    }\n  };\n\n  var AceEditor = util.Class({\n\n    trackerName: \"AceEditor\",\n\n    constructor: function (el) {\n      this.element = $(el)[0];\n      assert($(this.element).hasClass(\"ace_editor\"));\n      this._change = this._change.bind(this);\n      this._editor().document.on(\"change\", this._change);\n    },\n\n    tracked: function (el) {\n      return this.element === $(el)[0];\n    },\n\n    destroy: function (el) {\n      this._editor().document.removeListener(\"change\", this._change);\n    },\n\n    update: function (msg) {\n      this._editor().document.setValue(msg.value);\n    },\n\n    init: function (update, msg) {\n      this.update(update);\n    },\n\n    makeInit: function () {\n      return {\n        element: this.element,\n        tracker: this.trackerName,\n        value: this._editor().document.getValue()\n      };\n    },\n\n    _editor: function () {\n      return this.element.env;\n    },\n\n    _change: function (e) {\n      // FIXME: I should have an internal .send() function that automatically\n      // asserts !inRemoteUpdate, among other things\n      if (inRemoteUpdate) {\n        return;\n      }\n      sendData({\n        tracker: this.trackerName,\n        element: this.element,\n        value: this.getContent()\n      });\n    },\n\n    getContent: function() {\n      return this._editor().document.getValue();\n    }\n  });\n\n  AceEditor.scan = function () {\n    return $(\".ace_editor\");\n  };\n\n  AceEditor.tracked = function (el) {\n    return !! $(el).closest(\".ace_editor\").length;\n  };\n\n  TogetherJS.addTracker(AceEditor, true /* skip setInit */);\n\n  var CodeMirrorEditor = util.Class({\n    trackerName: \"CodeMirrorEditor\",\n\n    constructor: function (el) {\n      this.element = $(el)[0];\n      assert(this.element.CodeMirror);\n      this._change = this._change.bind(this);\n      this._editor().on(\"change\", this._change);\n    },\n\n    tracked: function (el) {\n      return this.element === $(el)[0];\n    },\n\n    destroy: function (el) {\n      this._editor().off(\"change\", this._change);\n    },\n\n    update: function (msg) {\n      this._editor().setValue(msg.value);\n    },\n\n    init: function (msg) {\n      if (msg.value) {\n        this.update(msg);\n      }\n    },\n\n    makeInit: function () {\n      return {\n        element: this.element,\n        tracker: this.trackerName,\n        value: this._editor().getValue()\n      };\n    },\n\n    _change: function (editor, change) {\n      if (inRemoteUpdate) {\n        return;\n      }\n      sendData({\n        tracker: this.trackerName,\n        element: this.element,\n        value: this.getContent()\n      });\n    },\n\n    _editor: function () {\n      return this.element.CodeMirror;\n    },\n\n    getContent: function() {\n      return this._editor().getValue();\n    }\n  });\n\n  CodeMirrorEditor.scan = function () {\n    var result = [];\n    var els = document.body.getElementsByTagName(\"*\");\n    var _len = els.length;\n    for (var i=0; i<_len; i++) {\n      var el = els[i];\n      if (el.CodeMirror) {\n        result.push(el);\n      }\n    }\n    return $(result);\n  };\n\n  CodeMirrorEditor.tracked = function (el) {\n    el = $(el)[0];\n    while (el) {\n      if (el.CodeMirror) {\n        return true;\n      }\n      el = el.parentNode;\n    }\n    return false;\n  };\n\n  TogetherJS.addTracker(CodeMirrorEditor, true /* skip setInit */);\n\n  var CKEditor = util.Class({\n    trackerName: \"CKEditor\",\n\n    constructor: function (el) {\n      this.element = $(el)[0];\n      assert(CKEDITOR);\n      assert(CKEDITOR.dom.element.get(this.element));\n      this._change = this._change.bind(this);\n      // FIXME: change event is available since CKEditor 4.2\n      this._editor().on(\"change\", this._change);\n    },\n    tracked: function (el) {\n      return this.element === $(el)[0];\n    },\n    destroy: function (el) {\n      this._editor().removeListener(\"change\", this._change);\n    },\n\n    update: function (msg) {\n      //FIXME: use setHtml instead of setData to avoid frame reloading overhead\n      this._editor().editable().setHtml(msg.value);\n    },\n\n    init: function (update, msg) {\n      this.update(update);\n    },\n\n    makeInit: function () {\n      return {\n        element: this.element,\n        tracker: this.trackerName,\n        value: this.getContent()\n      };\n    },\n\n    _change: function (e) {\n      if (inRemoteUpdate) {\n        return;\n      }\n      sendData({\n        tracker: this.trackerName,\n        element: this.element,\n        value: this.getContent()\n      });\n    },\n\n    _editor: function () {\n      return CKEDITOR.dom.element.get(this.element).getEditor();\n    },\n    \n    getContent: function () {\n      return this._editor().getData();\n    }\n  });\n\n  CKEditor.scan = function () {\n    var result = [];\n    if (typeof CKEDITOR == \"undefined\") {\n      return;\n    }\n    var editorInstance;\n    for (var instanceIdentifier in CKEDITOR.instances) {\n      editorInstance = document.getElementById(instanceIdentifier) || document.getElementsByName(instanceIdentifier)[0];\n      if (editorInstance) {\n        result.push(editorInstance);\n      }\n    }\n    return $(result);\n  };\n\n  CKEditor.tracked = function (el) {\n    if (typeof CKEDITOR == \"undefined\") {\n      return false;\n    }\n    el = $(el)[0];\n    return !! (CKEDITOR.dom.element.get(el) && CKEDITOR.dom.element.get(el).getEditor());\n  };\n\n  TogetherJS.addTracker(CKEditor, true /* skip setInit */);\n\n  //////////////////// BEGINNING OF TINYMCE ////////////////////////\n  var tinymceEditor = util.Class({\n    trackerName: \"tinymceEditor\",\n\n    constructor: function (el) {\n      this.element = $(el)[0];\n      assert($(this.element).attr('id').indexOf('mce_') != -1);\n      this._change = this._change.bind(this);\n      this._editor().on(\"input keyup cut paste change\", this._change);\n    },\n\n    tracked: function (el) {\n      return this.element === $(el)[0];\n    },\n\n    destroy: function (el) {\n      this._editor().destory();\n    },\n\n    update: function (msg) {\n      this._editor().setContent(msg.value, {format: 'raw'});\n    },\n\n    init: function (update, msg) {\n      this.update(update);\n    },\n\n    makeInit: function () {\n      return {\n        element: this.element,\n        tracker: this.trackerName,\n        value: this.getContent()\n      };\n    },\n\n    _change: function (e) {\n      if (inRemoteUpdate) {\n        return;\n      }  \n      sendData({\n        tracker: this.trackerName,\n        element: this.element,\n        value: this.getContent()\n      });\n    },\n\n    _editor: function () {\n      if (typeof tinymce == \"undefined\") {\n        return;\n      }\n      return $(this.element).data(\"tinyEditor\");\n    },\n    \n    getContent: function () {\n      return this._editor().getContent();\n    }\n  });\n\n  tinymceEditor.scan = function () {\n    //scan all the elements that contain tinyMCE editors\n    if (typeof tinymce == \"undefined\") {\n      return;\n    }\n    var result = [];\n    $(window.tinymce.editors).each(function (i, ed) {\n      result.push($('#'+ed.id));\n      //its impossible to retrieve a single editor from a container, so lets store it\n      $('#'+ed.id).data(\"tinyEditor\", ed);\n    });\n    return $(result);\n  };\n\n  tinymceEditor.tracked = function (el) {\n    if (typeof tinymce == \"undefined\") {\n      return false;\n    }\n    el = $(el)[0];\n    return !!$(el).data(\"tinyEditor\");\n    /*var flag = false;\n    $(window.tinymce.editors).each(function (i, ed) {\n      if (el.id == ed.id) {\n        flag = true;\n      }\n    });\n    return flag;*/\n  };\n\n  TogetherJS.addTracker(tinymceEditor, true);\n  ///////////////// END OF TINYMCE ///////////////////////////////////\n\n  function buildTrackers() {\n    assert(! liveTrackers.length);\n    util.forEachAttr(editTrackers, function (TrackerClass) {\n      var els = TrackerClass.scan();\n      if (els) {\n        $.each(els, function () {\n          var tracker = new TrackerClass(this);\n          $(this).data(\"togetherjsHistory\", ot.SimpleHistory(session.clientId, tracker.getContent(), 1));\n          liveTrackers.push(tracker);\n        });\n      }\n    });\n  }\n\n  function destroyTrackers() {\n    liveTrackers.forEach(function (tracker) {\n      tracker.destroy();\n    });\n    liveTrackers = [];\n  }\n\n  function elementTracked(el) {\n    var result = false;\n    util.forEachAttr(editTrackers, function (TrackerClass) {\n      if (TrackerClass.tracked(el)) {\n        result = true;\n      }\n    });\n    return result;\n  }\n\n  function getTracker(el, name) {\n    el = $(el)[0];\n    for (var i=0; i<liveTrackers.length; i++) {\n      var tracker = liveTrackers[i];\n      if (tracker.tracked(el)) {\n        //FIXME: assert statement below throws an exception when data is submitted to the hub too fast\n        //in other words, name == tracker.trackerName instead of name == tracker when someone types too fast in the tracked editor\n        //commenting out this assert statement solves the problem\n        assert((! name) || name == tracker.trackerName, \"Expected to map to a tracker type\", name, \"but got\", tracker.trackerName);\n        return tracker;\n      }\n    }\n    return null;\n  }\n\n  var TEXT_TYPES = (\n    \"color date datetime datetime-local email \" +\n        \"tel text time week\").split(/ /g);\n\n  function isText(el) {\n    el = $(el);\n    var tag = el.prop(\"tagName\");\n    var type = (el.prop(\"type\") || \"text\").toLowerCase();\n    if (tag == \"TEXTAREA\") {\n      return true;\n    }\n    if (tag == \"INPUT\" && TEXT_TYPES.indexOf(type) != -1) {\n      return true;\n    }\n    return false;\n  }\n\n  function getValue(el) {\n    el = $(el);\n    if (isCheckable(el)) {\n      return el.prop(\"checked\");\n    } else {\n      return el.val();\n    }\n  }\n\n  function getElementType(el) {\n    el = $(el)[0];\n    if (el.tagName == \"TEXTAREA\") {\n      return \"textarea\";\n    }\n    if (el.tagName == \"SELECT\") {\n      return \"select\";\n    }\n    if (el.tagName == \"INPUT\") {\n      return (el.getAttribute(\"type\") || \"text\").toLowerCase();\n    }\n    return \"?\";\n  }\n\n  function setValue(el, value) {\n    el = $(el);\n    var changed = false;\n    if (isCheckable(el)) {\n      var checked = !! el.prop(\"checked\");\n      value = !! value;\n      if (checked != value) {\n        changed = true;\n        el.prop(\"checked\", value);\n      }\n    } else {\n      if (el.val() != value) {\n        changed = true;\n        el.val(value);\n      }\n    }\n    if (changed) {\n      eventMaker.fireChange(el);\n    }\n  }\n\n  /* Send the top of this history queue, if it hasn't been already sent. */\n  function maybeSendUpdate(element, history, tracker) {\n    var change = history.getNextToSend();\n    if (! change) {\n      /* nothing to send */\n      return;\n    }\n    var msg = {\n      type: \"form-update\",\n      element: element,\n      \"server-echo\": true,\n      replace: {\n        id: change.id,\n        basis: change.basis,\n        delta: {\n          start: change.delta.start,\n          del: change.delta.del,\n          text: change.delta.text\n        }\n      }\n    };\n    if (tracker) {\n      msg.tracker = tracker;\n    }\n    session.send(msg);\n  }\n\n  session.hub.on(\"form-update\", function (msg) {\n    if (! msg.sameUrl) {\n      return;\n    }\n    var el = $(elementFinder.findElement(msg.element));\n    var tracker;\n    if (msg.tracker) {\n      tracker = getTracker(el, msg.tracker);\n      assert(tracker);\n    }\n    var focusedEl = el[0].ownerDocument.activeElement;\n    var focusedElSelection;\n    if (isText(focusedEl)) {\n      focusedElSelection = [focusedEl.selectionStart, focusedEl.selectionEnd];\n    }\n    var selection;\n    if (isText(el)) {\n      selection = [el[0].selectionStart, el[0].selectionEnd];\n    }\n    var value;\n    if (msg.replace) {\n      var history = el.data(\"togetherjsHistory\");\n      if (!history) {\n        console.warn(\"form update received for uninitialized form element\");\n        return;\n      }\n      history.setSelection(selection);\n      // make a real TextReplace object.\n      msg.replace.delta = ot.TextReplace(msg.replace.delta.start,\n                                         msg.replace.delta.del,\n                                         msg.replace.delta.text);\n      // apply this change to the history\n      var changed = history.commit(msg.replace);\n      var trackerName = null;\n      if (typeof tracker != \"undefined\") {\n        trackerName = tracker.trackerName;\n      }\n      maybeSendUpdate(msg.element, history, trackerName);\n      if (! changed) {\n        return;\n      }\n      value = history.current;\n      selection = history.getSelection();\n    } else {\n      value = msg.value;\n    }\n    inRemoteUpdate = true;\n    try {\n      if(tracker) {\n        tracker.update({value:value});\n      } else {\n        setValue(el, value);\n      }\n      if (isText(el)) {\n        el[0].selectionStart = selection[0];\n        el[0].selectionEnd = selection[1];\n      }\n      // return focus to original input:\n      if (focusedEl != el[0]) {\n        focusedEl.focus();\n        if (isText(focusedEl)) {\n          focusedEl.selectionStart = focusedElSelection[0];\n          focusedEl.selectionEnd = focusedElSelection[1];\n        }\n      }\n    } finally {\n      inRemoteUpdate = false;\n    }\n  });\n\n  var initSent = false;\n\n  function sendInit() {\n    initSent = true;\n    var msg = {\n      type: \"form-init\",\n      pageAge: Date.now() - TogetherJS.pageLoaded,\n      updates: []\n    };\n    var els = $(\"textarea, input, select\");\n    els.each(function () {\n      if (elementFinder.ignoreElement(this) || elementTracked(this) ||\n          suppressSync(this)) {\n        return;\n      }\n      var el = $(this);\n      var value = getValue(el);\n      var upd = {\n        element: elementFinder.elementLocation(this),\n        //elementType: getElementType(el), // added in 5cbb88c9a but unused\n        value: value\n      };\n      if (isText(el)) {\n        var history = el.data(\"togetherjsHistory\");\n        if (history) {\n          upd.value = history.committed;\n          upd.basis = history.basis;\n        }\n      }\n      msg.updates.push(upd);\n    });\n    liveTrackers.forEach(function (tracker) {\n      var init = tracker.makeInit();\n      assert(tracker.tracked(init.element));\n      var history = $(init.element).data(\"togetherjsHistory\");\n      if (history) {\n        init.value = history.committed;\n        init.basis = history.basis;\n      }\n      init.element = elementFinder.elementLocation($(init.element));\n      msg.updates.push(init);\n    });\n    if (msg.updates.length) {\n      session.send(msg);\n    }\n  }\n\n  function setInit() {\n    var els = $(\"textarea, input, select\");\n    els.each(function () {\n      if (elementTracked(this)) {\n        return;\n      }\n      if (elementFinder.ignoreElement(this)) {\n        return;\n      }\n      var el = $(this);\n      var value = getValue(el);\n      el.data(\"togetherjsHistory\", ot.SimpleHistory(session.clientId, value, 1));\n    });\n    destroyTrackers();\n    buildTrackers();\n  }\n\n  session.on(\"reinitialize\", setInit);\n\n  session.on(\"ui-ready\", setInit);\n\n  session.on(\"close\", destroyTrackers);\n\n  session.hub.on(\"form-init\", function (msg) {\n    if (! msg.sameUrl) {\n      return;\n    }\n    if (initSent) {\n      // In a 3+-peer situation more than one client may init; in this case\n      // we're probably the other peer, and not the peer that needs the init\n      // A quick check to see if we should init...\n      var myAge = Date.now() - TogetherJS.pageLoaded;\n      if (msg.pageAge < myAge) {\n        // We've been around longer than the other person...\n        return;\n      }\n    }\n    // FIXME: need to figure out when to ignore inits\n    msg.updates.forEach(function (update) {\n      var el;\n      try {\n        el = elementFinder.findElement(update.element);\n      } catch (e) {\n        /* skip missing element */\n        console.warn(e);\n        return;\n      }\n        inRemoteUpdate = true;\n        try {\n          if (update.tracker) {\n            var tracker = getTracker(el, update.tracker);\n            assert(tracker);\n            tracker.init(update, msg);\n          } else {\n            setValue(el, update.value);\n          }\n          if (update.basis) {\n            var history = $(el).data(\"togetherjsHistory\");\n            // don't overwrite history if we're already up to date\n            // (we might have outstanding queued changes we don't want to lose)\n            if (!(history && history.basis === update.basis &&\n                  // if history.basis is 1, the form could have lingering\n                  // edits from before togetherjs was launched.  that's too bad,\n                  // we need to erase them to resynchronize with the peer\n                  // we just asked to join.\n                  history.basis !== 1)) {\n              $(el).data(\"togetherjsHistory\", ot.SimpleHistory(session.clientId, update.value, update.basis));\n            }\n          }\n        } finally {\n          inRemoteUpdate = false;\n        }\n    });\n  });\n\n  var lastFocus = null;\n\n  function focus(event) {\n    var target = event.target;\n    if (elementFinder.ignoreElement(target) || elementTracked(target)) {\n      blur(event);\n      return;\n    }\n    if (target != lastFocus) {\n      lastFocus = target;\n      session.send({type: \"form-focus\", element: elementFinder.elementLocation(target)});\n    }\n  }\n\n  function blur(event) {\n    var target = event.target;\n    if (lastFocus) {\n      lastFocus = null;\n      session.send({type: \"form-focus\", element: null});\n    }\n  }\n\n  var focusElements = {};\n\n  session.hub.on(\"form-focus\", function (msg) {\n    if (! msg.sameUrl) {\n      return;\n    }\n    var current = focusElements[msg.peer.id];\n    if (current) {\n      current.remove();\n      current = null;\n    }\n    if (! msg.element) {\n      // A blur\n      return;\n    }\n    var element = elementFinder.findElement(msg.element);\n    var el = createFocusElement(msg.peer, element);\n    if (el) {\n      focusElements[msg.peer.id] = el;\n    }\n  });\n\n  function createFocusElement(peer, around) {\n    around = $(around);\n    var aroundOffset = around.offset();\n    if (! aroundOffset) {\n      console.warn(\"Could not get offset of element:\", around[0]);\n      return null;\n    }\n    var el = templating.sub(\"focus\", {peer: peer});\n    el = el.find(\".togetherjs-focus\");\n    el.css({\n      top: aroundOffset.top-FOCUS_BUFFER + \"px\",\n      left: aroundOffset.left-FOCUS_BUFFER + \"px\",\n      width: around.outerWidth() + (FOCUS_BUFFER*2) + \"px\",\n      height: around.outerHeight() + (FOCUS_BUFFER*2) + \"px\"\n    });\n    $(document.body).append(el);\n    return el;\n  }\n\n  session.on(\"ui-ready\", function () {\n    $(document).on(\"change\", change);\n    // note that textInput, keydown, and keypress aren't appropriate events\n    // to watch, since they fire *before* the element's value changes.\n    $(document).on(\"input keyup cut paste\", maybeChange);\n    $(document).on(\"focusin\", focus);\n    $(document).on(\"focusout\", blur);\n  });\n\n  session.on(\"close\", function () {\n    $(document).off(\"change\", change);\n    $(document).off(\"input keyup cut paste\", maybeChange);\n    $(document).off(\"focusin\", focus);\n    $(document).off(\"focusout\", blur);\n  });\n\n  session.hub.on(\"hello\", function (msg) {\n    if (msg.sameUrl) {\n      setTimeout(function () {\n\tsendInit();\n        if (lastFocus) {\n          session.send({type: \"form-focus\", element: elementFinder.elementLocation(lastFocus)});\n        }\n      });\n    }\n  });\n\n  return forms;\n});\n"
  },
  {
    "path": "togetherjs/functions.less",
    "content": ".transition (@val) {\n  /*    Note, you must call this like:\n  .transition(~\"value, value, value\")*/\n  transition: @val;\n  -moz-transition: @val;\n  -webkit-transition: @val;\n  -o-transition: @val;\n}\n\n.transform-origin (...) {\n  -moz-transform-origin: @arguments;\n  -webkit-transform-origin: @arguments;\n  -ms-transform-origin: @arguments;\n  -o-transform-origin: @arguments;\n  transform-origin: @arguments;\n}\n\n.user-select (@value) {\n  -moz-user-select: @value;\n  -webkit-user-select: @value;\n  -ms-user-select: @value;\n  user-select: @value;\n}\n\n// The CSS reset doesn't reset everything, just resets them to normal.\n// This resets buttons back to nothing.\n.button-reset () {\n  background-color: inherit;\n  border: none;\n  padding: 0;\n  margin: 0;\n}\n\n.gradient (@startColor, @endColor) {\n  background: @startColor; /* Old browsers */\n  background: -moz-linear-gradient(top,  @startColor 0%, @endColor 100%); /* FF3.6+ */\n  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, @startColor), color-stop(100%, @endColor)); /* Chrome,Safari4+ */\n  background: -webkit-linear-gradient(top, @startColor 0%, @endColor 100%); /* Chrome10+,Safari5.1+ */\n  background: -o-linear-gradient(top, @startColor 0%, @endColor 100%); /* Opera 11.10+ */\n  background: -ms-linear-gradient(top, @startColor 0%, @endColor 100%); /* IE10+ */\n  background: linear-gradient(to bottom, @startColor 0%, @endColor 100%); /* W3C */\n  // Not sure we can do this in LESS\n  // filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@startColor', endColorstr='@endColor',GradientType=0 ); /* IE6-9 */\n}\n"
  },
  {
    "path": "togetherjs/help.txt",
    "content": "<% /*\n  This is used to show the help when you type /help.  Used in\n  TogetherJS.localChatMessage().\n\n*/ %>\n/help : this message\n/test : run an automated/randomized test (or stop one that is in progress)\n  /test start N : run N times (instead of default 100)\n  /test show : show what kind of actions the random test would take (or stop showing)\n  /test describe : describe the possible actions (instead of showing them)\n/clear : clear the chat area\n/record : open up a recorder for the session\n/playback URL : play back a session that was recorded (it's up to you to figure out how to host it)\n  /playback local:NAME : play a locally saved log\n/savelogs NAME : save the currently recorded logs under NAME (recorder must be open)\n/baseurl : set a local baseUrl to load TogetherJS from, for debugging a development version of TogetherJS.\n/config : override some TogetherJS configuration parameters\n  /config VAR VALUE : set TogetherJS.config(\"VAR\", VALUE).  VALUE must be a legal Javascript/JSON literal.\n  /config clear : remove all overridden configuration\n"
  },
  {
    "path": "togetherjs/interface.html",
    "content": "<% /*\n   This is basically all the markup and interface for TogetherJS.\n   Note all links should be like http://localhost:8080/togetherjs/*\n   these links are rewritten with the location where TogetherJS was deployed.\n\n   This file is inlined into togetherjs/templates.js\n*/ %>\n<div id=\"togetherjs-container\" class=\"togetherjs\">\n\n  <!-- This is the main set of buttons: -->\n  <div id=\"togetherjs-dock\" class=\"togetherjs-dock-right\">\n    <div id=\"togetherjs-dock-anchor\" title=\"{{ gettext('Move the dock') }}\">\n      <span id=\"togetherjs-dock-anchor-horizontal\">\n        <img src=\"http://localhost:8080/togetherjs/images/icn-handle-circle@2x.png\" alt=\"drag\">\n      </span>\n      <span id=\"togetherjs-dock-anchor-vertical\">\n        <img src=\"http://localhost:8080/togetherjs/images/icn-handle-circle@2x.png\" alt=\"drag\">\n      </span>\n    </div>\n    <div id=\"togetherjs-buttons\">\n      <div style=\"display: none\">\n        <button id=\"togetherjs-template-dock-person\" class=\"togetherjs-button togetherjs-dock-person\">\n          <div class=\"togetherjs-tooltip togetherjs-dock-person-tooltip\">\n            <span class=\"togetherjs-person-name\"></span>\n            <span class=\"togetherjs-person-tooltip-arrow-r\"></span>\n          </div>\n          <div class=\"togetherjs-person togetherjs-person-status-overlay\"></div>\n        </button>\n      </div>\n      <button id=\"togetherjs-profile-button\" class=\"togetherjs-button\" title=\"{{ gettext('This is you') }}\">\n        <div class=\"togetherjs-person togetherjs-person-self\"></div>\n        <div id=\"togetherjs-profile-arrow\"></div>\n      </button>\n      <button id=\"togetherjs-share-button\" class=\"togetherjs-button\" title=\"{{ gettext('Add a friend') }}\"></button>\n      <button id=\"togetherjs-audio-button\" class=\"togetherjs-button\" title=\"{{ gettext('Turn on microphone')}}\">\n        <span id=\"togetherjs-audio-unavailable\" class=\"togetherjs-audio-set\" data-toggles=\".togetherjs-audio-set\">\n        </span>\n        <span id=\"togetherjs-audio-ready\" class=\"togetherjs-audio-set\" data-toggles=\".togetherjs-audio-set\" style=\"display: none\">\n        </span>\n        <span id=\"togetherjs-audio-outgoing\" class=\"togetherjs-audio-set\" data-toggles=\".togetherjs-audio-set\" style=\"display: none\">\n        </span>\n        <span id=\"togetherjs-audio-incoming\" class=\"togetherjs-audio-set\" data-toggles=\".togetherjs-audio-set\" style=\"display: none\">\n        </span>\n        <span id=\"togetherjs-audio-active\" class=\"togetherjs-audio-set\" data-toggles=\".togetherjs-audio-set\" style=\"display: none\">\n        </span>\n        <span id=\"togetherjs-audio-muted\" class=\"togetherjs-audio-set\" data-toggles=\".togetherjs-audio-set\" style=\"display: none\">\n        </span>\n        <span id=\"togetherjs-audio-error\" class=\"togetherjs-audio-set\" data-toggles=\".togetherjs-audio-set\" style=\"display: none\">\n        </span>\n      </button>\n      <button id=\"togetherjs-chat-button\" class=\"togetherjs-button\" title=\"{{ gettext('Chat') }}\"></button>\n      <div id=\"togetherjs-dock-participants\"></div>\n    </div>\n  </div>\n\n  <!-- The window for editing the avatar: -->\n  <div id=\"togetherjs-avatar-edit\" class=\"togetherjs-modal\"\n       style=\"display: none\">\n    <header> {{ gettext('Update avatar') }} </header>\n    <section>\n      <div class=\"togetherjs-avatar-preview togetherjs-person togetherjs-person-self\"></div>\n      <div id=\"togetherjs-avatar-buttons\">\n        <input type=\"file\" class=\"togetherjs-upload-avatar\">\n        <!--<button id=\"togetherjs-upload-avatar\" class=\"togetherjs-primary\">Upload a picture</button>-->\n        <!--<button id=\"togetherjs-camera-avatar\" class=\"togetherjs-default\">Take a picture</button>-->\n      </div>\n    </section>\n    <section class=\"togetherjs-buttons\">\n      <button class=\"togetherjs-cancel togetherjs-dismiss\">{{ gettext('Cancel') }}</button>\n      <span class=\"togetherjs-alt-text\">{{ gettext('or') }}</span>\n      <button class=\"togetherjs-avatar-save togetherjs-primary\">{{ gettext('Save') }}</button>\n    </section>\n  </div>\n\n  <!-- The window for sharing the link: -->\n  <div id=\"togetherjs-share\" class=\"togetherjs-window\"\n       data-bind-to=\"#togetherjs-share-button\" style=\"display: none\">\n    <header> {{ gettext('Invite a friend') }} </header>\n    <section>\n      <div class=\"togetherjs-not-mobile\">\n        <p>{{ gettext('Copy and paste this link over IM or email:') }}</p>\n        <input type=\"text\" class=\"togetherjs-share-link\">\n      </div>\n      <div class=\"togetherjs-only-mobile\">\n        <p>{{ gettext('Copy and paste this link over IM or email:') }}</p>\n        <input type=\"text\" class=\"togetherjs-share-link\">\n        <!-- <a class=\"togetherjs-share-link\" href=\"#\">Press your thumb here.</a> -->\n      </div>\n    </section>\n  </div>\n\n  <!-- Participant Full List view template: -->\n  <div id=\"togetherjs-participantlist\" class=\"togetherjs-window\"\n       data-bind-to=\"#togetherjs-participantlist-button\" style=\"display: none\">\n    <header> {{ gettext('Participants') }} </header>\n    <section>\n      <div class=\"togetherjs-not-mobile\">\n        <ul>\n          <li id=\"togetherjs-participant-item\">\n            <img class=\"togetherjs-person togetherjs-person-small\" src=\"http://localhost:8080/togetherjs/images/btn-menu-change-avatar.png\">\n            <span class=\"tj-name togetherjs-person-name\">NAME</span>\n            <span class=\"tj-status\">&#9679;</span>\n            <p class=\"tj-urllocation\">{{ gettext('Currently at:') }} <a class=\"togetherjs-person-url togetherjs-person-url-title\" href=\"\">http://www.location.comwww.location.comwww.location.comasdfsafd</a></p>\n            <p class=\"tj-follow\">{{ gettext('Follow:') }}\n              <label class=\"togetherjs-follow-question\" for=\"togetherjs-person-status-follow\">\n                <input type=\"checkbox\" id=\"togetherjs-person-status-follow\">\n              </label>\n            </p>\n            <section class=\"togetherjs-buttons\">\n              <!-- Displayed when the peer is at a different URL: -->\n              <div class=\"togetherjs-different-url\">\n                <a class=\"togetherjs-nudge togetherjs-default tj-btn-sm\">{{ gettext('Nudge them') }}</a>\n                <a href=\"#\" class=\"togetherjs-follow togetherjs-person-url togetherjs-primary tj-btn-sm\">{{ gettext('Join them') }}</a>\n              </div>\n              <!-- Displayed when the peer is at your same URL: -->\n              <div class=\"togetherjs-same-url\" style=\"display: none\">\n                <span class=\"togetherjs-person-name\"></span> {{ gettext('is on the same page as you.')}}\n              </div>\n            </section>\n          </li>\n        </ul>\n    </section>\n  </div>\n\n  <!-- Participant detail template: -->\n  <div id=\"togetherjs-template-participant-window\" class=\"togetherjs-window\" style=\"display: none\">\n    <header><div class=\"togetherjs-person togetherjs-person-small\"></div><span class=\"togetherjs-person-name\"></span></header>\n\n    <section class=\"togetherjs-participant-window-main\">\n      <p class=\"togetherjs-participant-window-row\"><strong>{{ gettext('Role:') }}</strong>\n        <span class=\"togetherjs-person-role\"></span>\n      </p>\n\n      <p class=\"togetherjs-participant-window-row\"><strong>{{ gettext('Currently at:') }}</strong>\n        <a class=\"togetherjs-person-url togetherjs-person-url-title\"></a>\n      </p>\n\n      <p class=\"togetherjs-participant-window-row\"><strong>{{ gettext('Status:') }}</strong>\n        <span class=\"togetherjs-person-status\"></span>\n      </p>\n\n      <p class=\"togetherjs-participant-window-row\"><strong class=\"togetherjs-float-left\">{{ gettext('Follow this participant:') }}</strong>\n        <label class=\"togetherjs-follow-question togetherjs-float-left\" for=\"togetherjs-person-status-follow\">\n          <input type=\"checkbox\" id=\"togetherjs-person-status-follow\">\n        </label>\n        <span class=\"togetherjs-clear\"></span>\n      </p>\n\n    </section>\n\n    <section class=\"togetherjs-buttons\">\n      <!-- Displayed when the peer is at a different URL: -->\n      <div class=\"togetherjs-different-url\">\n        <a class=\"togetherjs-nudge togetherjs-default\">{{ gettext('Nudge them') }}</a>\n        <a href=\"#\" class=\"togetherjs-follow togetherjs-person-url togetherjs-primary\">{{ gettext('Join them') }}</a>\n      </div>\n      <!-- Displayed when the peer is at your same URL: -->\n      <div class=\"togetherjs-same-url\" style=\"display: none\">\n        <span class=\"togetherjs-person-name\"></span> {{ gettext('is on the same page as you.') }}\n      </div>\n    </section>\n  </div>\n\n  <!-- The chat screen: -->\n  <div id=\"togetherjs-chat\" class=\"togetherjs-window\" data-bind-to=\"#togetherjs-chat-button\"\n       style=\"display: none\">\n    <header> {{ gettext('Chat') }} </header>\n    <section class=\"togetherjs-subtitle\">\n      <div id=\"togetherjs-chat-participants\" data-toggles=\"#togetherjs-chat-no-participants\" style=\"display: none\">\n        <span id=\"togetherjs-chat-participant-list\"></span>\n        &amp; {{ gettext('You') }}\n      </div>\n      <div id=\"togetherjs-chat-no-participants\" data-toggles=\"#togetherjs-chat-participants\">\n        {{ gettext('No one else is here.') }}\n      </div>\n    </section>\n\n    <div style=\"display: none\">\n\n      <!-- Template for one message: -->\n      <div id=\"togetherjs-template-chat-message\" class=\"togetherjs-chat-item togetherjs-chat-message\">\n        <div class=\"togetherjs-person\"></div>\n        <div class=\"togetherjs-timestamp\"><span class=\"togetherjs-time\">HH:MM</span> <span class=\"togetherjs-ampm\">AM/PM</span></div>\n        <div class=\"togetherjs-person-name-abbrev\"></div>\n        <div class=\"togetherjs-chat-content togetherjs-sub-content\"></div>\n      </div>\n\n      <!-- Template for when a person leaves: -->\n      <div id=\"togetherjs-template-chat-left\" class=\"togetherjs-chat-item togetherjs-chat-left-item\">\n        <div class=\"togetherjs-person\"></div>\n        <div class=\"togetherjs-ifnot-declinedJoin\">\n          <div class=\"togetherjs-inline-text\"><span class=\"togetherjs-person-name\"></span> {{ gettext('left the session.') }}</div>\n        </div>\n        <div class=\"togetherjs-if-declinedJoin\">\n          <div class=\"togetherjs-inline-text\"><span class=\"togetherjs-person-name\"></span> {{ gettext('declined to join the session.')}}</div>\n        </div>\n        <div class=\"togetherjs-clear\"></div>\n      </div>\n\n      <!-- Template when a person joins the session: -->\n      <div id=\"togetherjs-template-chat-joined\" class=\"togetherjs-chat-item togetherjs-chat-join-item\">\n        <div class=\"togetherjs-person\"></div>\n        <div class=\"togetherjs-inline-text\"><span class=\"togetherjs-person-name\"></span> {{ gettext('joined the session.') }}</div>\n        <div class=\"togetherjs-clear\"></div>\n      </div>\n\n      <!-- Template for system-derived messages: -->\n      <div id=\"togetherjs-template-chat-system\" class=\"togetherjs-chat-item\">\n        <span class=\"togetherjs-chat-content togetherjs-sub-content\"></span>\n      </div>\n\n      <!-- Template when a person joins the session: -->\n      <!-- <div id=\"togetherjs-template-chat-joined\" class=\"togetherjs-chat-item togetherjs-chat-join-item\">\n        <div class=\"togetherjs-person\"></div>\n        <div class=\"togetherjs-inline-text\"><span class=\"togetherjs-person-name\"></span> joined the session.</div>\n        <div class=\"togetherjs-clear\"></div>\n      </div> -->\n\n      <!-- Template for when someone goes to a new URL: -->\n      <div id=\"togetherjs-template-url-change\" class=\"togetherjs-chat-item togetherjs-chat-url-change\">\n        <div class=\"togetherjs-person\"></div>\n        <div class=\"togetherjs-inline-text\">\n          <div class=\"togetherjs-if-sameUrl\">\n            <span class=\"togetherjs-person-name\"></span>\n            {{ gettext('is on the same page as you.') }}\n          </div>\n          <div class=\"togetherjs-ifnot-sameUrl\">\n            <span class=\"togetherjs-person-name\"></span>\n            {{ gettext('has gone to:') }} <a href=\"#\" class=\"togetherjs-person-url togetherjs-person-url-title\" target=\"_self\"></a>\n            <section class=\"togetherjs-buttons togetherjs-buttons-notification-diff-url\">\n              <!-- Displayed when the peer is at a different URL: -->\n              <div class=\"togetherjs-different-url togetherjs-notification-diff-url\">\n                <a class=\"togetherjs-nudge togetherjs-default\">{{ gettext('Nudge them') }}</a>\n                <a href=\"#\" class=\"togetherjs-follow togetherjs-person-url togetherjs-primary\">{{ gettext('Join them') }}</a>\n              </div>\n            </section>\n\n            <!-- <div>\n              <a class=\"togetherjs-nudge togetherjs-secondary\">Nudge them</a>\n              <a href=\"\" class=\"togetherjs-person-url togetherjs-follow togetherjs-primary\">Join them</a>\n            </div> -->\n\n          </div>\n        </div>\n        <div class=\"togetherjs-clear\"></div>\n      </div>\n    </div>\n\n    <section id=\"togetherjs-chat-messages\">\n      <!-- FIX ME// need to have some dialogue that says something like - There are no chats yet! -->\n    </section>\n    <section id=\"togetherjs-chat-input-box\">\n      <textarea id=\"togetherjs-chat-input\" placeholder=\"{{ gettext('Type your message here') }}\"></textarea>\n    </section>\n  </div>\n\n  <!-- this is a kind of warning popped up when you (successfully) start RTC: -->\n  <div id=\"togetherjs-rtc-info\" class=\"togetherjs-window\"\n       data-bind-to=\"#togetherjs-audio-button\"\n       style=\"display: none\">\n\n    <header> {{ gettext('Audio Chat') }} </header>\n    <section>\n      <p>\n        {{ gettext('Activate your <strong>browser microphone</strong> near your URL bar above.') }}\n      </p>\n      <p>\n        {{ gettext('Talking on your microphone through your web browser is an experimental feature.') }}\n      </p>\n      <p>\n        {{ gettext('Read more about Audio Chat') }} <a href=\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\" target=\"_blank\">{{ gettext('here') }}</a>.\n      </p>\n    </section>\n\n    <section class=\"togetherjs-buttons\">\n      <label for=\"togetherjs-rtc-info-dismiss\" style=\"display: inline;\">\n        <input class=\"togetherjs-dont-show-again\" id=\"togetherjs-rtc-info-dismiss\" type=\"checkbox\">\n        {{ gettext('Don\\'t show again.') }}\n      </label>\n      <button class=\"togetherjs-default togetherjs-dismiss\" type=\"button\">{{ gettext('Close') }}</button>\n    </section>\n  </div>\n\n  <!-- this is popped up when you hit the audio button, but RTC isn't\n  supported: -->\n  <div id=\"togetherjs-rtc-not-supported\" class=\"togetherjs-window\"\n       data-bind-to=\"#togetherjs-audio-button\"\n       style=\"display: none\">\n    <header> {{ gettext('Audio Chat') }} </header>\n\n    <section>\n      <p>{{ gettext('Audio chat requires you to use a <a href=\\'https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\' target=\\'_blank\\'>newer browser</a>!') }}</p>\n      <p>\n        {{ gettext('Live audio chat requires a newer (or different) browser than you\\'re using.') }}\n      </p>\n      <p>\n        {{ gettext('See <a href=\\'https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\' target=\\'_blank\\'>this page</a>for more information and a list of supported browsers.') }}\n      </p>\n    </section>\n\n    <section class=\"togetherjs-buttons\">\n      <div class=\"togetherjs-rtc-dialog-btn\">\n        <button class=\"togetherjs-default togetherjs-dismiss\" type=\"button\">{{ gettext('Close') }}</button>\n      </div>\n    </section>\n  </div>\n\n  <!-- The popup when a chat message comes in and the #togetherjs-chat window isn't open -->\n  <div id=\"togetherjs-chat-notifier\" class=\"togetherjs-notification\"\n       data-bind-to=\"#togetherjs-chat-button\"\n       style=\"display: none\">\n    <img src=\"http://localhost:8080/togetherjs/images/notification-togetherjs-logo.png\" class=\"togetherjs-notification-logo\" alt=\"\">\n    <img src=\"http://localhost:8080/togetherjs/images/notification-btn-close.png\" class=\"togetherjs-notification-closebtn togetherjs-dismiss\" alt=\"[close]\">\n    <section id=\"togetherjs-chat-notifier-message\">\n    </section>\n  </div>\n\n  <!-- The menu when you click on the profile: -->\n  <div id=\"togetherjs-menu\" class=\"togetherjs-menu\" style=\"display: none\">\n    <div class=\"togetherjs-menu-item togetherjs-menu-disabled\" id=\"togetherjs-menu-profile\">\n      <img id=\"togetherjs-menu-avatar\">\n      <span class=\"togetherjs-person-name-self\" id=\"togetherjs-self-name-display\" data-toggles=\"#togetherjs-menu .togetherjs-self-name\">[nickname]</span>\n      <input class=\"togetherjs-self-name\" type=\"text\" data-toggles=\"#togetherjs-self-name-display\" style=\"display: none\" placeholder=\"{{ gettext(\"Enter your name\") }}\">\n    </div>\n    <div class=\"togetherjs-menu-hr-avatar\"></div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-update-name\"><img src=\"http://localhost:8080/togetherjs/images/button-pencil.png\" alt=\"\"> {{ gettext('Update your name') }}</div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-update-avatar\"><img src=\"http://localhost:8080/togetherjs/images/btn-menu-change-avatar.png\" alt=\"\"> {{ gettext('Change avatar') }}</div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-update-color\"><span class=\"togetherjs-person-bgcolor-self\"></span> {{ gettext('Pick profile color') }}</div>\n    <div class=\"togetherjs-hr\"></div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-help\">{{ gettext('Help') }}</div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-feedback\">{{ gettext('Feedback') }}</div>\n    <div id=\"togetherjs-invite\" style=\"display: none\">\n      <div class=\"togetherjs-hr\"></div>\n      <div id=\"togetherjs-invite-users\"></div>\n      <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-refresh-invite\">{{ gettext('Refresh users') }}</div>\n      <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-invite-anyone\">{{ gettext('Invite anyone') }}</div>\n    </div>\n    <div class=\"togetherjs-hr\"></div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-end\"><img src=\"http://localhost:8080/togetherjs/images/button-end-session.png\" alt=\"\"> {{ gettext('End') }} <span class=\"togetherjs-tool-name\">{{ gettext('TogetherJS') }}</span></div>\n  </div>\n\n  <!-- template for one person in the invite-users list -->\n  <div style=\"display: none\">\n    <div id=\"togetherjs-template-invite-user-item\" class=\"togetherjs-menu-item\">\n      <!-- FIXME: should include avatar in some way -->\n      <span class=\"togetherjs-person-name\"></span>\n    </div>\n  </div>\n\n  <!-- A window version of #togetherjs-menu, for use on mobile -->\n  <div id=\"togetherjs-menu-window\" class=\"togetherjs-window\" style=\"display: none\">\n    <header>{{ gettext('Settings and Profile') }}</header>\n    <section>\n    <div class=\"togetherjs-menu-item\">\n      <img class=\"togetherjs-menu-avatar\">\n      <span class=\"togetherjs-person-name-self\" id=\"togetherjs-self-name-display\"></span>\n    </div>\n    <div class=\"togetherjs-menu-hr-avatar\"></div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-update-name-button\"><img src=\"http://localhost:8080/togetherjs/images/button-pencil.png\" alt=\"\"> {{ gettext('Update your name') }}</div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-update-avatar-button\"><img src=\"http://localhost:8080/togetherjs/images/btn-menu-change-avatar.png\" alt=\"\"> {{ gettext('Change avatar') }}</div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-update-color-button\"><span class=\"togetherjs-person-bgcolor-self\"></span> {{ gettext('Pick profile color') }}</div>\n    <div class=\"togetherjs-hr\"></div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-help-button\">{{ gettext('Help') }}</div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-feedback-button\">{{ gettext('Feedback') }}</div>\n    <div class=\"togetherjs-hr\"></div>\n    <div class=\"togetherjs-menu-item\" id=\"togetherjs-menu-end-button\"><img src=\"http://localhost:8080/togetherjs/images/button-end-session.png\" alt=\"\"> {{ gettext('End TOOL_NAME') }}</div>\n    </section>\n    <section class=\"togetherjs-buttons\">\n      <button class=\"togetherjs-dismiss togetherjs-primary\">{{ gettext('OK') }}</button>\n    </section>\n  </div>\n\n  <!-- The name editor, for use on mobile -->\n  <div id=\"togetherjs-edit-name-window\" class=\"togetherjs-window\" style=\"display: none\">\n    <header>{{ gettext('Update Name') }}</header>\n    <section>\n      <div>\n        <input class=\"togetherjs-self-name\" type=\"text\" placeholder=\"{{ gettext('Enter your name') }}\">\n      </div>\n    </section>\n    <section class=\"togetherjs-buttons\">\n      <button class=\"togetherjs-dismiss togetherjs-primary\">{{ gettext('OK') }}</button>\n    </section>\n  </div>\n\n  <div class=\"togetherjs-menu\" id=\"togetherjs-pick-color\" style=\"display: none\">\n    <div class=\"togetherjs-triangle-up\"><img src=\"http://localhost:8080/togetherjs/images/icn-triangle-up.png\"></div>\n    <div style=\"display: none\">\n      <div id=\"togetherjs-template-swatch\" class=\"togetherjs-swatch\">\n      </div>\n    </div>\n  </div>\n\n  <!-- Invisible elements that handle the RTC audio: -->\n  <audio id=\"togetherjs-audio-element\"></audio>\n  <audio id=\"togetherjs-local-audio\" muted=\"true\" volume=\"0.3\"></audio>\n  <audio id=\"togetherjs-notification\" src=\"http://localhost:8080/togetherjs/images/notification.ogg\"></audio>\n\n  <!-- The intro screen for someone who joins a session the first time: -->\n  <div id=\"togetherjs-intro\" class=\"togetherjs-modal\" style=\"display: none\">\n    <header>{{ gettext('Join TOOL_NAME session?') }}</header>\n    <section>\n      <p>{{ gettext(\"Your friend has asked you to join their TOOL_SITE_LINK browser session to collaborate in real-time!\")}}</p>\n      <p>{{ gettext(\"Would you like to join their session?\") }}</p>\n    </section>\n\n    <section class=\"togetherjs-buttons\">\n      <button class=\"togetherjs-destructive togetherjs-modal-dont-join\">{{ gettext( \"No, don't join\" ) }}</button>\n      <button class=\"togetherjs-primary togetherjs-dismiss\">{{ gettext( \"Yes, join session\" ) }}</button>\n    </section>\n  </div>\n\n  <!-- Shown when a web browser is completely incapable of running TogetherJS: -->\n  <div id=\"togetherjs-browser-broken\" class=\"togetherjs-modal\" style=\"display: none\">\n    <header> {{ gettext('Sorry') }} </header>\n\n    <section>\n      <p>\n        {{ gettext(\"We're sorry, TOOL_NAME doesn't work with this browser.  Please <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>upgrade to a supported browser</a> to try TOOL_NAME.\" ) }}\n      </p>\n\n      <p id=\"togetherjs-browser-broken-is-ie\" style=\"display: none\">\n        {{ gettext('We need your help fixing TogetherJS on Internet Explorer!  Here are a list of IE <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">GitHub issues</a> we need fixed that you can work on.') }}\n        {{ gettext(\"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">is currently not supported</a>.  If you do want to try out TogetherJS, we'd suggest using Firefox or Chrome.\") }}\n      </p>\n    </section>\n\n    <section class=\"togetherjs-buttons\">\n      <button class=\"togetherjs-dismiss togetherjs-primary\">{{ gettext('End TOOL_NAME') }}</button>\n    </section>\n\n  </div>\n\n  <!-- Shown when the browser has WebSockets, but is IE (i.e., IE10) -->\n  <div id=\"togetherjs-browser-unsupported\" class=\"togetherjs-modal\" style=\"display: none\">\n    <header> {{ gettext('Unsupported Browser') }} </header>\n\n    <section>\n      <p>\n        {{ gettext('We need your help fixing TogetherJS on Internet Explorer!  Here are a list of IE <a href=\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\" target=\"_blank\">GitHub issues</a> we need fixed that you can work on.') }}\n        {{ gettext(\"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">is currently not supported</a>.  If you do want to try out TogetherJS, we'd suggest using Firefox or Chrome.\") }}\n      </p>\n\n      <p>{{ gettext('You can continue to try to use TOOL_NAME, but you are likely to hit lots of bugs.  So be warned.') }}</p>\n\n    </section>\n\n    <section class=\"togetherjs-buttons\">\n      <button class=\"togetherjs-dismiss togetherjs-primary\">{{ gettext('End TOOL_NAME') }}</button>\n      <button class=\"togetherjs-dismiss togetherjs-secondary togetherjs-browser-unsupported-anyway\">{{ gettext('Try TOOL_NAME Anyway') }}</button>\n    </section>\n\n  </div>\n\n  <div id=\"togetherjs-confirm-end\" class=\"togetherjs-modal\" style=\"display: none\">\n    <header> {{ gettext('End session?') }} </header>\n    <section>\n      <p>\n        {{ gettext(\"Are you sure you'd like to end your TOOL_NAME session?\") }}\n      </p>\n    </section>\n    <section class=\"togetherjs-buttons\">\n      <button class=\"togetherjs-cancel togetherjs-dismiss\">{{ gettext('Cancel') }}</button>\n      <span class=\"togetherjs-alt-text\">{{ gettext('or') }}</span>\n      <button id=\"togetherjs-end-session\" class=\"togetherjs-destructive\">{{ gettext('End session') }}</button>\n    </section>\n  </div>\n\n  <div id=\"togetherjs-feedback-form\" class=\"togetherjs-modal\" style=\"display: none;\">\n    <header> {{ gettext('Feedback') }} </header>\n    <iframe src=\"https://docs.google.com/a/mozilla.com/forms/d/1lVE7JyRo_tjakN0mLG1Cd9X9vseBX9wci153z9JcNEs/viewform?embedded=true\" width=\"400\" height=\"300\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\">{{ gettext('Loading form...') }}</iframe>\n    <!-- <p><button class=\"togetherjs-modal-close\">Close</button></p> -->\n  </div>\n\n  <div style=\"display: none\">\n    <!-- This is when you join a session and the other person has already changed to another URL: -->\n    <div id=\"togetherjs-template-url-change\" class=\"togetherjs-modal\">\n      <header> {{ gettext('Following to new URL...') }} </header>\n      <section>\n        <div class=\"togetherjs-person\"></div>\n        {{ gettext('Following') }}\n        <span class=\"togetherjs-person-name\"></span>\n        {{ gettext( \"to\" ) }} <a href=\"\" class=\"togetherjs-person-url togetherjs-person-url-title\"></a>\n      </section>\n    </div>\n\n    <!-- This is when someone invites you to their session: -->\n    <div id=\"togetherjs-template-invite\" class=\"togetherjs-chat-item\">\n      <div class=\"togetherjs-person\"></div>\n      <div>\n        <span class=\"togetherjs-person-name\"></span>\n        {{ gettext('has invited') }} <strong class=\"togetherjs-if-forEveryone\">{{ gettext('anyone') }}</strong>\n        <strong class=\"togetherjs-ifnot-forEveryone\">{{ gettext('you') }}</strong>\n        {{ gettext( \"to\" ) }} <a href=\"\" data-togetherjs-subattr-href=\"href\" class=\"togetherjs-sub-hrefTitle\" target=\"_blank\"></a>\n      </div>\n    </div>\n\n  </div>\n\n  <!-- The pointer at the side of a window: -->\n  <div id=\"togetherjs-window-pointer-right\" style=\"display: none\"></div>\n  <div id=\"togetherjs-window-pointer-left\" style=\"display: none\"></div>\n\n  <!-- The element that overlaps the background of the page during a modal dialog: -->\n  <div id=\"togetherjs-modal-background\" style=\"display: none\"></div>\n\n  <!-- Some miscellaneous templates -->\n  <div style=\"display: none\">\n\n    <!-- This is the cursor: -->\n    <div id=\"togetherjs-template-cursor\" class=\"togetherjs-cursor togetherjs\">\n      <!-- Note: images/cursor.svg is a copy of this (for editing): -->\n      <!-- crossbrowser svg dropshadow http://demosthenes.info/blog/600/Creating-a-True-CrossBrowser-Drop-Shadow- -->\n      <svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n      \t width=\"15px\" height=\"22.838px\" viewBox=\"96.344 146.692 15 22.838\" enable-background=\"new 96.344 146.692 15 22.838\"\n      \t xml:space=\"preserve\">\n      <path fill=\"#231F20\" d=\"M98.984,146.692c2.167,1.322,1.624,6.067,3.773,7.298c-0.072-0.488,2.512-0.931,3.097,0\n      \tc0.503,0.337,1.104-0.846,2.653,0.443c0.555,0.593,3.258,2.179,1.001,8.851c-0.446,1.316,2.854,0.135,1.169,2.619\n      \tc-3.748,5.521-9.455,2.787-9.062,1.746c1.06-2.809-6.889-4.885-4.97-9.896c0.834-2.559,2.898,0.653,2.923,0.29\n      \tc-0.434-1.07-2.608-5.541-2.923-6.985C96.587,150.793,95.342,147.033,98.984,146.692z\"/>\n      </svg>\n      <!-- <img class=\"togetherjs-cursor-img\" src=\"http://localhost:8080/togetherjs/images/cursor.svg\"> -->\n      <span class=\"togetherjs-cursor-container\">\n        <span class=\"togetherjs-cursor-name\"></span>\n        <span style=\"display:none\" class=\"togetherjs-cursor-typing\" id=\"togetherjs-cursor-typebox\">\n          <span class=\"togetherjs-typing-ellipse-one\">&#9679;</span><span class=\"togetherjs-typing-ellipse-two\">&#9679;</span><span class=\"togetherjs-typing-ellipse-three\">&#9679;</span>\n        </span>\n        <!-- Displayed when the cursor is below the screen: -->\n        <span class=\"togetherjs-cursor-down\">\n\n        </span>\n        <!-- Displayed when the cursor is above the screen: -->\n        <span class=\"togetherjs-cursor-up\">\n\n        </span>\n      </span>\n    </div>\n\n    <!-- This is the element that goes around focused form elements: -->\n    <div id=\"togetherjs-template-focus\">\n      <div class=\"togetherjs-focus togetherjs-person-bordercolor\"></div>\n    </div>\n\n    <!-- This is a click: -->\n    <div id=\"togetherjs-template-click\" class=\"togetherjs-click togetherjs\">\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "togetherjs/jqueryPlugins.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"jquery\"], function ($) {\n  // This isn't really a \"module\" since it just patches jQuery itself\n\n  // FIX ME Animations TO DO\n  // walkthrough animations go here\n  // animate participant cursor and box popping in when they enter the session\n  // animate participant cursor and box popping out when they leave the session\n  // animate the participant cursor -> rotate down when they're down the page\n  $.fn.rotateCursorDown = function () {\n    $('svg').animate({borderSpacing: -150, opacity: 1}, {\n      step: function(now, fx) {\n        if (fx.prop == \"borderSpacing\") {\n          $(this).css('-webkit-transform', 'rotate('+now+'deg)')\n            .css('-moz-transform', 'rotate('+now+'deg)')\n            .css('-ms-transform', 'rotate('+now+'deg)')\n            .css('-o-transform', 'rotate('+now+'deg)')\n            .css('transform', 'rotate('+now+'deg)');\n        } else {\n          $(this).css(fx.prop, now);\n        }\n      },\n      duration: 500\n    }, 'linear').promise().then(function () {\n      this.css('-webkit-transform', '');\n      this.css('-moz-transform', '');\n      this.css('-ms-transform', '');\n      this.css('-o-transform', '');\n      this.css('transform', '');\n      this.css(\"opacity\", \"\");\n    });\n  };\n\n  // animate the participant cursor -> rotate up when they're on the same frame as the user\n  $.fn.rotateCursorDown = function () {\n    $('.togetherjs-cursor svg').animate({borderSpacing: 0, opacity: 1}, {\n      step: function(now, fx) {\n        if (fx.prop == \"borderSpacing\") {\n          $(this).css('-webkit-transform', 'rotate('+now+'deg)')\n            .css('-moz-transform', 'rotate('+now+'deg)')\n            .css('-ms-transform', 'rotate('+now+'deg)')\n            .css('-o-transform', 'rotate('+now+'deg)')\n            .css('transform', 'rotate('+now+'deg)');\n        } else {\n          $(this).css(fx.prop, now);\n        }\n      },\n      duration: 500\n    }, 'linear').promise().then(function () {\n      this.css('-webkit-transform', '');\n      this.css('-moz-transform', '');\n      this.css('-ms-transform', '');\n      this.css('-o-transform', '');\n      this.css('transform', '');\n      this.css(\"opacity\", \"\");\n    });\n  };\n\n  // Move notification when another notification slides in //\n\n\n  /* Pop in window from dock button: */\n  $.fn.popinWindow = function () {\n\n    //mobile popout window with no animation\n    if($.browser.mobile) {\n\n       //starting position\n        this.css({\n          left: \"0px\",\n          opacity: 1,\n          \"zIndex\": 8888\n        });\n\n        //starting position for arrow\n        $('#togetherjs-window-pointer-right').css({\n          left: \"+=74px\",\n          opacity: 1,\n          \"zIndex\": 8888\n        });\n\n        //animate arrow out\n        $('#togetherjs-window-pointer-right').animate({\n          opacity: 1,\n          left: \"-=78px\"\n        }, {\n          duration:60, easing:\"linear\"\n        });\n        $('#togetherjs-window-pointer-right').queue();\n\n        //bounce arrow back\n        $('#togetherjs-window-pointer-right').animate({\n          left:'+=4px'\n        }, {\n          duration:60, easing:\"linear\"\n        });\n\n        //animate window out\n        this.animate({\n          opacity: 1,\n          left: \"0px\"\n        }, {\n          duration:60, easing:\"linear\"\n        });\n        this.queue();\n\n        //bounce window back\n        this.animate({\n          left:'0px'\n        }, {\n          duration:60, easing:\"linear\"\n        });\n    }\n\n    else {\n\n      //starting position\n      this.css({\n        left: \"+=74px\",\n        opacity: 1,\n        \"zIndex\": 8888\n      });\n\n      //starting position for arrow\n      $('#togetherjs-window-pointer-right').css({\n        left: \"+=74px\",\n        opacity: 1,\n        \"zIndex\": 8888\n      });\n\n      //animate arrow out\n      $('#togetherjs-window-pointer-right').animate({\n        opacity: 1,\n        left: \"-=78px\"\n      }, {\n        duration:60, easing:\"linear\"\n      });\n      $('#togetherjs-window-pointer-right').queue();\n\n      //bounce arrow back\n      $('#togetherjs-window-pointer-right').animate({\n        left:'+=4px'\n      }, {\n        duration:60, easing:\"linear\"\n      });\n\n      //animate window out\n      this.animate({\n        opacity: 1,\n        left: \"-=78px\"\n      }, {\n        duration:60, easing:\"linear\"\n      });\n      this.queue();\n\n      //bounce window back\n      this.animate({\n        left:'+=4px'\n      }, {\n        duration:60, easing:\"linear\"\n      });\n\n    }\n\n  };\n\n  /* Slide in notification window: */\n  $.fn.slideIn = function () {\n    this.css({\n      //top: \"240px\",\n      left: \"+=74px\",\n      opacity: 0,\n      \"zIndex\": 8888\n    });\n    return this.animate({\n      \"left\": \"-=74px\",\n      opacity: 1,\n      \"zIndex\": 9999\n    }, \"fast\");\n  };\n\n  /* Used to fade away notification windows + flip the bottom of them out: */\n  $.fn.fadeOut = function () {\n    this.animate({borderSpacing: -90, opacity: 0.5}, {\n      step: function(now, fx) {\n        if (fx.prop == \"borderSpacing\") {\n          $(this).css('-webkit-transform', 'perspective( 600px ) rotateX('+now+'deg)')\n            .css('-moz-transform', 'perspective( 600px ) rotateX('+now+'deg)')\n            .css('-ms-transform', 'perspective( 600px ) rotateX('+now+'deg)')\n            .css('-o-transform', 'perspective( 600px ) rotateX('+now+'deg)')\n            .css('transform', 'perspective( 600px ) rotateX('+now+'deg)');\n        } else {\n          $(this).css(fx.prop, now);\n        }\n      },\n      duration: 500\n    }, 'linear').promise().then(function () {\n      this.css('-webkit-transform', '');\n      this.css('-moz-transform', '');\n      this.css('-ms-transform', '');\n      this.css('-o-transform', '');\n      this.css('transform', '');\n      this.css(\"opacity\", \"\");\n    });\n    return this;\n  };\n\n  /* used when user goes down to participant cursor location on screen */\n  $.fn.easeTo = function (y) {\n    return this.animate({\n      scrollTop: y\n    }, {\n      duration: 400,\n      easing: \"swing\"\n    });\n  };\n\n  // avatar animate in\n  $.fn.animateDockEntry = function () {\n    var height = this.height();\n    var width = this.width();\n    var backgroundSize = height + 4;\n    var margin = parseInt(this.css(\"marginLeft\"), 10);\n\n    // set starting position CSS for avatar\n    this.css({\n      marginLeft: margin + width/2,\n      height: 0,\n      width: 0,\n      backgroundSize: \"0 0\"\n    });\n\n    var self = this;\n\n    //then animate avatar to the actual dimensions, and reset the values\n    this.animate({\n      marginLeft: margin,\n      height: height,\n      width: width,\n      backgroundSize: backgroundSize\n    }, {\n      duration: 600\n    }).promise().then(function () {\n      self.css({\n        marginLeft: \"\",\n        height: \"\",\n        width: \"\",\n        backgroundSize: \"\"\n      });\n    });\n    return this;\n  };\n\n  // avatar animate out, reverse of above\n  $.fn.animateDockExit = function () {\n\n    // get the current avatar dimenensions\n    var height = this.height();\n    var width = this.width();\n    var backgroundSize = height + 4;\n    var margin = parseInt(this.css(\"marginLeft\"), 10);\n\n    //then animate avatar to shrink to nothing, and reset the values again\n    // FIXME this needs to animate from the CENTER\n    this.animate({\n      marginLeft: margin + width/2,\n      height: 0,\n      width: 0,\n      backgroundSize: \"0 0\",\n      opacity: 0\n    }, 600 );\n\n    return this;\n\n  };\n\n  $.fn.animateCursorEntry = function () {\n    // Make the cursor bubble pop in\n  };\n\n  // keyboard typing animation\n  $.fn.animateKeyboard = function () {\n    var one = this.find(\".togetherjs-typing-ellipse-one\");\n    var two = this.find(\".togetherjs-typing-ellipse-two\");\n    var three = this.find(\".togetherjs-typing-ellipse-three\");\n    var count = -1;\n    var run = (function () {\n      count = (count+1) % 4;\n      if (count === 0) {\n        one.css(\"opacity\", 0.5);\n        two.css(\"opacity\", 0.5);\n        three.css(\"opacity\", 0.5);\n      } else if (count == 1) {\n        one.css(\"opacity\", 1);\n      } else if (count == 2) {\n        two.css(\"opacity\", 1);\n      } else { // count==3\n        three.css(\"opacity\", 1);\n      }\n    }).bind(this);\n    run();\n    var interval = setInterval(run, 300);\n    this.data(\"animateKeyboard\", interval);\n  };\n\n  $.fn.stopKeyboardAnimation = function () {\n    clearTimeout(this.data(\"animateKeyboard\"));\n    this.data(\"animateKeyboard\", null);\n  };\n\n  // FIXME: not sure if this is legit, but at least the modern mobile devices we\n  // care about should have this defined:\n  if (! $.browser) {\n    $.browser = {};\n  }\n  $.browser.mobile = window.orientation !== undefined;\n  if (navigator.userAgent.search(/mobile/i) != -1) {\n    // FIXME: At least on the Firefox OS simulator I need this\n    $.browser.mobile = true;\n  }\n\n  if ($.browser.mobile && window.matchMedia && ! window.matchMedia(\"screen and (max-screen-width: 480px)\").matches) {\n    // FIXME: for Firefox OS simulator really:\n    document.body.className += \" togetherjs-mobile-browser\";\n  }\n\n});\n"
  },
  {
    "path": "togetherjs/libs/almond.js",
    "content": "/**\n * almond 0.2.5 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/almond for details\n */\n//Going sloppy to avoid 'use strict' string cost, but strict practices should\n//be followed.\n/*jslint sloppy: true */\n/*global setTimeout: false */\n\nvar requirejs, require, define;\n(function (undef) {\n    var main, req, makeMap, handlers,\n        defined = {},\n        waiting = {},\n        config = {},\n        defining = {},\n        hasOwn = Object.prototype.hasOwnProperty,\n        aps = [].slice;\n\n    function hasProp(obj, prop) {\n        return hasOwn.call(obj, prop);\n    }\n\n    /**\n     * Given a relative module name, like ./something, normalize it to\n     * a real name that can be mapped to a path.\n     * @param {String} name the relative name\n     * @param {String} baseName a real name that the name arg is relative\n     * to.\n     * @returns {String} normalized name\n     */\n    function normalize(name, baseName) {\n        var nameParts, nameSegment, mapValue, foundMap,\n            foundI, foundStarMap, starI, i, j, part,\n            baseParts = baseName && baseName.split(\"/\"),\n            map = config.map,\n            starMap = (map && map['*']) || {};\n\n        //Adjust any relative paths.\n        if (name && name.charAt(0) === \".\") {\n            //If have a base name, try to normalize against it,\n            //otherwise, assume it is a top-level require that will\n            //be relative to baseUrl in the end.\n            if (baseName) {\n                //Convert baseName to array, and lop off the last part,\n                //so that . matches that \"directory\" and not name of the baseName's\n                //module. For instance, baseName of \"one/two/three\", maps to\n                //\"one/two/three.js\", but we want the directory, \"one/two\" for\n                //this normalization.\n                baseParts = baseParts.slice(0, baseParts.length - 1);\n\n                name = baseParts.concat(name.split(\"/\"));\n\n                //start trimDots\n                for (i = 0; i < name.length; i += 1) {\n                    part = name[i];\n                    if (part === \".\") {\n                        name.splice(i, 1);\n                        i -= 1;\n                    } else if (part === \"..\") {\n                        if (i === 1 && (name[2] === '..' || name[0] === '..')) {\n                            //End of the line. Keep at least one non-dot\n                            //path segment at the front so it can be mapped\n                            //correctly to disk. Otherwise, there is likely\n                            //no path mapping for a path starting with '..'.\n                            //This can still fail, but catches the most reasonable\n                            //uses of ..\n                            break;\n                        } else if (i > 0) {\n                            name.splice(i - 1, 2);\n                            i -= 2;\n                        }\n                    }\n                }\n                //end trimDots\n\n                name = name.join(\"/\");\n            } else if (name.indexOf('./') === 0) {\n                // No baseName, so this is ID is resolved relative\n                // to baseUrl, pull off the leading dot.\n                name = name.substring(2);\n            }\n        }\n\n        //Apply map config if available.\n        if ((baseParts || starMap) && map) {\n            nameParts = name.split('/');\n\n            for (i = nameParts.length; i > 0; i -= 1) {\n                nameSegment = nameParts.slice(0, i).join(\"/\");\n\n                if (baseParts) {\n                    //Find the longest baseName segment match in the config.\n                    //So, do joins on the biggest to smallest lengths of baseParts.\n                    for (j = baseParts.length; j > 0; j -= 1) {\n                        mapValue = map[baseParts.slice(0, j).join('/')];\n\n                        //baseName segment has  config, find if it has one for\n                        //this name.\n                        if (mapValue) {\n                            mapValue = mapValue[nameSegment];\n                            if (mapValue) {\n                                //Match, update name to the new value.\n                                foundMap = mapValue;\n                                foundI = i;\n                                break;\n                            }\n                        }\n                    }\n                }\n\n                if (foundMap) {\n                    break;\n                }\n\n                //Check for a star map match, but just hold on to it,\n                //if there is a shorter segment match later in a matching\n                //config, then favor over this star map.\n                if (!foundStarMap && starMap && starMap[nameSegment]) {\n                    foundStarMap = starMap[nameSegment];\n                    starI = i;\n                }\n            }\n\n            if (!foundMap && foundStarMap) {\n                foundMap = foundStarMap;\n                foundI = starI;\n            }\n\n            if (foundMap) {\n                nameParts.splice(0, foundI, foundMap);\n                name = nameParts.join('/');\n            }\n        }\n\n        return name;\n    }\n\n    function makeRequire(relName, forceSync) {\n        return function () {\n            //A version of a require function that passes a moduleName\n            //value for items that may need to\n            //look up paths relative to the moduleName\n            return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));\n        };\n    }\n\n    function makeNormalize(relName) {\n        return function (name) {\n            return normalize(name, relName);\n        };\n    }\n\n    function makeLoad(depName) {\n        return function (value) {\n            defined[depName] = value;\n        };\n    }\n\n    function callDep(name) {\n        if (hasProp(waiting, name)) {\n            var args = waiting[name];\n            delete waiting[name];\n            defining[name] = true;\n            main.apply(undef, args);\n        }\n\n        if (!hasProp(defined, name) && !hasProp(defining, name)) {\n            throw new Error('No ' + name);\n        }\n        return defined[name];\n    }\n\n    //Turns a plugin!resource to [plugin, resource]\n    //with the plugin being undefined if the name\n    //did not have a plugin prefix.\n    function splitPrefix(name) {\n        var prefix,\n            index = name ? name.indexOf('!') : -1;\n        if (index > -1) {\n            prefix = name.substring(0, index);\n            name = name.substring(index + 1, name.length);\n        }\n        return [prefix, name];\n    }\n\n    /**\n     * Makes a name map, normalizing the name, and using a plugin\n     * for normalization if necessary. Grabs a ref to plugin\n     * too, as an optimization.\n     */\n    makeMap = function (name, relName) {\n        var plugin,\n            parts = splitPrefix(name),\n            prefix = parts[0];\n\n        name = parts[1];\n\n        if (prefix) {\n            prefix = normalize(prefix, relName);\n            plugin = callDep(prefix);\n        }\n\n        //Normalize according\n        if (prefix) {\n            if (plugin && plugin.normalize) {\n                name = plugin.normalize(name, makeNormalize(relName));\n            } else {\n                name = normalize(name, relName);\n            }\n        } else {\n            name = normalize(name, relName);\n            parts = splitPrefix(name);\n            prefix = parts[0];\n            name = parts[1];\n            if (prefix) {\n                plugin = callDep(prefix);\n            }\n        }\n\n        //Using ridiculous property names for space reasons\n        return {\n            f: prefix ? prefix + '!' + name : name, //fullName\n            n: name,\n            pr: prefix,\n            p: plugin\n        };\n    };\n\n    function makeConfig(name) {\n        return function () {\n            return (config && config.config && config.config[name]) || {};\n        };\n    }\n\n    handlers = {\n        require: function (name) {\n            return makeRequire(name);\n        },\n        exports: function (name) {\n            var e = defined[name];\n            if (typeof e !== 'undefined') {\n                return e;\n            } else {\n                return (defined[name] = {});\n            }\n        },\n        module: function (name) {\n            return {\n                id: name,\n                uri: '',\n                exports: defined[name],\n                config: makeConfig(name)\n            };\n        }\n    };\n\n    main = function (name, deps, callback, relName) {\n        var cjsModule, depName, ret, map, i,\n            args = [],\n            usingExports;\n\n        //Use name if no relName\n        relName = relName || name;\n\n        //Call the callback to define the module, if necessary.\n        if (typeof callback === 'function') {\n\n            //Pull out the defined dependencies and pass the ordered\n            //values to the callback.\n            //Default to [require, exports, module] if no deps\n            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;\n            for (i = 0; i < deps.length; i += 1) {\n                map = makeMap(deps[i], relName);\n                depName = map.f;\n\n                //Fast path CommonJS standard dependencies.\n                if (depName === \"require\") {\n                    args[i] = handlers.require(name);\n                } else if (depName === \"exports\") {\n                    //CommonJS module spec 1.1\n                    args[i] = handlers.exports(name);\n                    usingExports = true;\n                } else if (depName === \"module\") {\n                    //CommonJS module spec 1.1\n                    cjsModule = args[i] = handlers.module(name);\n                } else if (hasProp(defined, depName) ||\n                           hasProp(waiting, depName) ||\n                           hasProp(defining, depName)) {\n                    args[i] = callDep(depName);\n                } else if (map.p) {\n                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});\n                    args[i] = defined[depName];\n                } else {\n                    throw new Error(name + ' missing ' + depName);\n                }\n            }\n\n            ret = callback.apply(defined[name], args);\n\n            if (name) {\n                //If setting exports via \"module\" is in play,\n                //favor that over return value and exports. After that,\n                //favor a non-undefined return value over exports use.\n                if (cjsModule && cjsModule.exports !== undef &&\n                        cjsModule.exports !== defined[name]) {\n                    defined[name] = cjsModule.exports;\n                } else if (ret !== undef || !usingExports) {\n                    //Use the return value from the function.\n                    defined[name] = ret;\n                }\n            }\n        } else if (name) {\n            //May just be an object definition for the module. Only\n            //worry about defining if have a module name.\n            defined[name] = callback;\n        }\n    };\n\n    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {\n        if (typeof deps === \"string\") {\n            if (handlers[deps]) {\n                //callback in this case is really relName\n                return handlers[deps](callback);\n            }\n            //Just return the module wanted. In this scenario, the\n            //deps arg is the module name, and second arg (if passed)\n            //is just the relName.\n            //Normalize module name, if it contains . or ..\n            return callDep(makeMap(deps, callback).f);\n        } else if (!deps.splice) {\n            //deps is a config object, not an array.\n            config = deps;\n            if (callback.splice) {\n                //callback is an array, which means it is a dependency list.\n                //Adjust args if there are dependencies\n                deps = callback;\n                callback = relName;\n                relName = null;\n            } else {\n                deps = undef;\n            }\n        }\n\n        //Support require(['a'])\n        callback = callback || function () {};\n\n        //If relName is a function, it is an errback handler,\n        //so remove it.\n        if (typeof relName === 'function') {\n            relName = forceSync;\n            forceSync = alt;\n        }\n\n        //Simulate async callback;\n        if (forceSync) {\n            main(undef, deps, callback, relName);\n        } else {\n            //Using a non-zero value because of concern for what old browsers\n            //do, and latest browsers \"upgrade\" to 4 if lower value is used:\n            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:\n            //If want a value immediately, use require('id') instead -- something\n            //that works in almond on the global level, but not guaranteed and\n            //unlikely to work in other AMD implementations.\n            setTimeout(function () {\n                main(undef, deps, callback, relName);\n            }, 4);\n        }\n\n        return req;\n    };\n\n    /**\n     * Just drops the config on the floor, but returns req in case\n     * the config return value is used.\n     */\n    req.config = function (cfg) {\n        config = cfg;\n        if (config.deps) {\n            req(config.deps, config.callback);\n        }\n        return req;\n    };\n\n    define = function (name, deps, callback) {\n\n        //This module may not have dependencies\n        if (!deps.splice) {\n            //deps is not an array, so probably means\n            //an object literal or factory function for\n            //the value. Adjust args.\n            callback = deps;\n            deps = [];\n        }\n\n        if (!hasProp(defined, name) && !hasProp(waiting, name)) {\n            waiting[name] = [name, deps, callback];\n        }\n    };\n\n    define.amd = {\n        jQuery: true\n    };\n}());\n"
  },
  {
    "path": "togetherjs/libs/require-nomin.js",
    "content": "/** vim: et:ts=4:sw=4:sts=4\n * @license RequireJS 2.1.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/requirejs for details\n */\n//Not using strict: uneven strict support in browsers, #392, and causes\n//problems with requirejs.exec()/transpiler plugins that may not be strict.\n/*jslint regexp: true, nomen: true, sloppy: true */\n/*global window, navigator, document, importScripts, setTimeout, opera */\n\nvar requirejs, require, define;\n(function (global) {\n    var req, s, head, baseElement, dataMain, src,\n        interactiveScript, currentlyAddingScript, mainScript, subPath,\n        version = '2.1.8',\n        commentRegExp = /(\\/\\*([\\s\\S]*?)\\*\\/|([^:]|^)\\/\\/(.*)$)/mg,\n        cjsRequireRegExp = /[^.]\\s*require\\s*\\(\\s*[\"']([^'\"\\s]+)[\"']\\s*\\)/g,\n        jsSuffixRegExp = /\\.js$/,\n        currDirRegExp = /^\\.\\//,\n        op = Object.prototype,\n        ostring = op.toString,\n        hasOwn = op.hasOwnProperty,\n        ap = Array.prototype,\n        apsp = ap.splice,\n        isBrowser = !!(typeof window !== 'undefined' && navigator && window.document),\n        isWebWorker = !isBrowser && typeof importScripts !== 'undefined',\n        //PS3 indicates loaded and complete, but need to wait for complete\n        //specifically. Sequence is 'loading', 'loaded', execution,\n        // then 'complete'. The UA check is unfortunate, but not sure how\n        //to feature test w/o causing perf issues.\n        readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?\n                      /^complete$/ : /^(complete|loaded)$/,\n        defContextName = '_',\n        //Oh the tragedy, detecting opera. See the usage of isOpera for reason.\n        isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',\n        contexts = {},\n        cfg = {},\n        globalDefQueue = [],\n        useInteractive = false;\n\n    function isFunction(it) {\n        return ostring.call(it) === '[object Function]';\n    }\n\n    function isArray(it) {\n        return ostring.call(it) === '[object Array]';\n    }\n\n    /**\n     * Helper function for iterating over an array. If the func returns\n     * a true value, it will break out of the loop.\n     */\n    function each(ary, func) {\n        if (ary) {\n            var i;\n            for (i = 0; i < ary.length; i += 1) {\n                if (ary[i] && func(ary[i], i, ary)) {\n                    break;\n                }\n            }\n        }\n    }\n\n    /**\n     * Helper function for iterating over an array backwards. If the func\n     * returns a true value, it will break out of the loop.\n     */\n    function eachReverse(ary, func) {\n        if (ary) {\n            var i;\n            for (i = ary.length - 1; i > -1; i -= 1) {\n                if (ary[i] && func(ary[i], i, ary)) {\n                    break;\n                }\n            }\n        }\n    }\n\n    function hasProp(obj, prop) {\n        return hasOwn.call(obj, prop);\n    }\n\n    function getOwn(obj, prop) {\n        return hasProp(obj, prop) && obj[prop];\n    }\n\n    /**\n     * Cycles over properties in an object and calls a function for each\n     * property value. If the function returns a truthy value, then the\n     * iteration is stopped.\n     */\n    function eachProp(obj, func) {\n        var prop;\n        for (prop in obj) {\n            if (hasProp(obj, prop)) {\n                if (func(obj[prop], prop)) {\n                    break;\n                }\n            }\n        }\n    }\n\n    /**\n     * Simple function to mix in properties from source into target,\n     * but only if target does not already have a property of the same name.\n     */\n    function mixin(target, source, force, deepStringMixin) {\n        if (source) {\n            eachProp(source, function (value, prop) {\n                if (force || !hasProp(target, prop)) {\n                    if (deepStringMixin && typeof value !== 'string') {\n                        if (!target[prop]) {\n                            target[prop] = {};\n                        }\n                        mixin(target[prop], value, force, deepStringMixin);\n                    } else {\n                        target[prop] = value;\n                    }\n                }\n            });\n        }\n        return target;\n    }\n\n    //Similar to Function.prototype.bind, but the 'this' object is specified\n    //first, since it is easier to read/figure out what 'this' will be.\n    function bind(obj, fn) {\n        return function () {\n            return fn.apply(obj, arguments);\n        };\n    }\n\n    function scripts() {\n        return document.getElementsByTagName('script');\n    }\n\n    function defaultOnError(err) {\n        throw err;\n    }\n\n    //Allow getting a global that expressed in\n    //dot notation, like 'a.b.c'.\n    function getGlobal(value) {\n        if (!value) {\n            return value;\n        }\n        var g = global;\n        each(value.split('.'), function (part) {\n            g = g[part];\n        });\n        return g;\n    }\n\n    /**\n     * Constructs an error with a pointer to an URL with more information.\n     * @param {String} id the error ID that maps to an ID on a web page.\n     * @param {String} message human readable error.\n     * @param {Error} [err] the original error, if there is one.\n     *\n     * @returns {Error}\n     */\n    function makeError(id, msg, err, requireModules) {\n        var e = new Error(msg + '\\nhttp://requirejs.org/docs/errors.html#' + id);\n        e.requireType = id;\n        e.requireModules = requireModules;\n        if (err) {\n            e.originalError = err;\n        }\n        return e;\n    }\n\n    if (typeof define !== 'undefined') {\n        //If a define is already in play via another AMD loader,\n        //do not overwrite.\n        return;\n    }\n\n    if (typeof requirejs !== 'undefined') {\n        if (isFunction(requirejs)) {\n            //Do not overwrite and existing requirejs instance.\n            return;\n        }\n        cfg = requirejs;\n        requirejs = undefined;\n    }\n\n    //Allow for a require config object\n    if (typeof require !== 'undefined' && !isFunction(require)) {\n        //assume it is a config object.\n        cfg = require;\n        require = undefined;\n    }\n\n    function newContext(contextName) {\n        var inCheckLoaded, Module, context, handlers,\n            checkLoadedTimeoutId,\n            config = {\n                //Defaults. Do not set a default for map\n                //config to speed up normalize(), which\n                //will run faster if there is no default.\n                waitSeconds: 7,\n                baseUrl: './',\n                paths: {},\n                pkgs: {},\n                shim: {},\n                config: {}\n            },\n            registry = {},\n            //registry of just enabled modules, to speed\n            //cycle breaking code when lots of modules\n            //are registered, but not activated.\n            enabledRegistry = {},\n            undefEvents = {},\n            defQueue = [],\n            defined = {},\n            urlFetched = {},\n            requireCounter = 1,\n            unnormalizedCounter = 1;\n\n        /**\n         * Trims the . and .. from an array of path segments.\n         * It will keep a leading path segment if a .. will become\n         * the first path segment, to help with module name lookups,\n         * which act like paths, but can be remapped. But the end result,\n         * all paths that use this function should look normalized.\n         * NOTE: this method MODIFIES the input array.\n         * @param {Array} ary the array of path segments.\n         */\n        function trimDots(ary) {\n            var i, part;\n            for (i = 0; ary[i]; i += 1) {\n                part = ary[i];\n                if (part === '.') {\n                    ary.splice(i, 1);\n                    i -= 1;\n                } else if (part === '..') {\n                    if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {\n                        //End of the line. Keep at least one non-dot\n                        //path segment at the front so it can be mapped\n                        //correctly to disk. Otherwise, there is likely\n                        //no path mapping for a path starting with '..'.\n                        //This can still fail, but catches the most reasonable\n                        //uses of ..\n                        break;\n                    } else if (i > 0) {\n                        ary.splice(i - 1, 2);\n                        i -= 2;\n                    }\n                }\n            }\n        }\n\n        /**\n         * Given a relative module name, like ./something, normalize it to\n         * a real name that can be mapped to a path.\n         * @param {String} name the relative name\n         * @param {String} baseName a real name that the name arg is relative\n         * to.\n         * @param {Boolean} applyMap apply the map config to the value. Should\n         * only be done if this normalization is for a dependency ID.\n         * @returns {String} normalized name\n         */\n        function normalize(name, baseName, applyMap) {\n            var pkgName, pkgConfig, mapValue, nameParts, i, j, nameSegment,\n                foundMap, foundI, foundStarMap, starI,\n                baseParts = baseName && baseName.split('/'),\n                normalizedBaseParts = baseParts,\n                map = config.map,\n                starMap = map && map['*'];\n\n            //Adjust any relative paths.\n            if (name && name.charAt(0) === '.') {\n                //If have a base name, try to normalize against it,\n                //otherwise, assume it is a top-level require that will\n                //be relative to baseUrl in the end.\n                if (baseName) {\n                    if (getOwn(config.pkgs, baseName)) {\n                        //If the baseName is a package name, then just treat it as one\n                        //name to concat the name with.\n                        normalizedBaseParts = baseParts = [baseName];\n                    } else {\n                        //Convert baseName to array, and lop off the last part,\n                        //so that . matches that 'directory' and not name of the baseName's\n                        //module. For instance, baseName of 'one/two/three', maps to\n                        //'one/two/three.js', but we want the directory, 'one/two' for\n                        //this normalization.\n                        normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);\n                    }\n\n                    name = normalizedBaseParts.concat(name.split('/'));\n                    trimDots(name);\n\n                    //Some use of packages may use a . path to reference the\n                    //'main' module name, so normalize for that.\n                    pkgConfig = getOwn(config.pkgs, (pkgName = name[0]));\n                    name = name.join('/');\n                    if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {\n                        name = pkgName;\n                    }\n                } else if (name.indexOf('./') === 0) {\n                    // No baseName, so this is ID is resolved relative\n                    // to baseUrl, pull off the leading dot.\n                    name = name.substring(2);\n                }\n            }\n\n            //Apply map config if available.\n            if (applyMap && map && (baseParts || starMap)) {\n                nameParts = name.split('/');\n\n                for (i = nameParts.length; i > 0; i -= 1) {\n                    nameSegment = nameParts.slice(0, i).join('/');\n\n                    if (baseParts) {\n                        //Find the longest baseName segment match in the config.\n                        //So, do joins on the biggest to smallest lengths of baseParts.\n                        for (j = baseParts.length; j > 0; j -= 1) {\n                            mapValue = getOwn(map, baseParts.slice(0, j).join('/'));\n\n                            //baseName segment has config, find if it has one for\n                            //this name.\n                            if (mapValue) {\n                                mapValue = getOwn(mapValue, nameSegment);\n                                if (mapValue) {\n                                    //Match, update name to the new value.\n                                    foundMap = mapValue;\n                                    foundI = i;\n                                    break;\n                                }\n                            }\n                        }\n                    }\n\n                    if (foundMap) {\n                        break;\n                    }\n\n                    //Check for a star map match, but just hold on to it,\n                    //if there is a shorter segment match later in a matching\n                    //config, then favor over this star map.\n                    if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {\n                        foundStarMap = getOwn(starMap, nameSegment);\n                        starI = i;\n                    }\n                }\n\n                if (!foundMap && foundStarMap) {\n                    foundMap = foundStarMap;\n                    foundI = starI;\n                }\n\n                if (foundMap) {\n                    nameParts.splice(0, foundI, foundMap);\n                    name = nameParts.join('/');\n                }\n            }\n\n            return name;\n        }\n\n        function removeScript(name) {\n            if (isBrowser) {\n                each(scripts(), function (scriptNode) {\n                    if (scriptNode.getAttribute('data-requiremodule') === name &&\n                            scriptNode.getAttribute('data-requirecontext') === context.contextName) {\n                        scriptNode.parentNode.removeChild(scriptNode);\n                        return true;\n                    }\n                });\n            }\n        }\n\n        function hasPathFallback(id) {\n            var pathConfig = getOwn(config.paths, id);\n            if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {\n                removeScript(id);\n                //Pop off the first array value, since it failed, and\n                //retry\n                pathConfig.shift();\n                context.require.undef(id);\n                context.require([id]);\n                return true;\n            }\n        }\n\n        //Turns a plugin!resource to [plugin, resource]\n        //with the plugin being undefined if the name\n        //did not have a plugin prefix.\n        function splitPrefix(name) {\n            var prefix,\n                index = name ? name.indexOf('!') : -1;\n            if (index > -1) {\n                prefix = name.substring(0, index);\n                name = name.substring(index + 1, name.length);\n            }\n            return [prefix, name];\n        }\n\n        /**\n         * Creates a module mapping that includes plugin prefix, module\n         * name, and path. If parentModuleMap is provided it will\n         * also normalize the name via require.normalize()\n         *\n         * @param {String} name the module name\n         * @param {String} [parentModuleMap] parent module map\n         * for the module name, used to resolve relative names.\n         * @param {Boolean} isNormalized: is the ID already normalized.\n         * This is true if this call is done for a define() module ID.\n         * @param {Boolean} applyMap: apply the map config to the ID.\n         * Should only be true if this map is for a dependency.\n         *\n         * @returns {Object}\n         */\n        function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {\n            var url, pluginModule, suffix, nameParts,\n                prefix = null,\n                parentName = parentModuleMap ? parentModuleMap.name : null,\n                originalName = name,\n                isDefine = true,\n                normalizedName = '';\n\n            //If no name, then it means it is a require call, generate an\n            //internal name.\n            if (!name) {\n                isDefine = false;\n                name = '_@r' + (requireCounter += 1);\n            }\n\n            nameParts = splitPrefix(name);\n            prefix = nameParts[0];\n            name = nameParts[1];\n\n            if (prefix) {\n                prefix = normalize(prefix, parentName, applyMap);\n                pluginModule = getOwn(defined, prefix);\n            }\n\n            //Account for relative paths if there is a base name.\n            if (name) {\n                if (prefix) {\n                    if (pluginModule && pluginModule.normalize) {\n                        //Plugin is loaded, use its normalize method.\n                        normalizedName = pluginModule.normalize(name, function (name) {\n                            return normalize(name, parentName, applyMap);\n                        });\n                    } else {\n                        normalizedName = normalize(name, parentName, applyMap);\n                    }\n                } else {\n                    //A regular module.\n                    normalizedName = normalize(name, parentName, applyMap);\n\n                    //Normalized name may be a plugin ID due to map config\n                    //application in normalize. The map config values must\n                    //already be normalized, so do not need to redo that part.\n                    nameParts = splitPrefix(normalizedName);\n                    prefix = nameParts[0];\n                    normalizedName = nameParts[1];\n                    isNormalized = true;\n\n                    url = context.nameToUrl(normalizedName);\n                }\n            }\n\n            //If the id is a plugin id that cannot be determined if it needs\n            //normalization, stamp it with a unique ID so two matching relative\n            //ids that may conflict can be separate.\n            suffix = prefix && !pluginModule && !isNormalized ?\n                     '_unnormalized' + (unnormalizedCounter += 1) :\n                     '';\n\n            return {\n                prefix: prefix,\n                name: normalizedName,\n                parentMap: parentModuleMap,\n                unnormalized: !!suffix,\n                url: url,\n                originalName: originalName,\n                isDefine: isDefine,\n                id: (prefix ?\n                        prefix + '!' + normalizedName :\n                        normalizedName) + suffix\n            };\n        }\n\n        function getModule(depMap) {\n            var id = depMap.id,\n                mod = getOwn(registry, id);\n\n            if (!mod) {\n                mod = registry[id] = new context.Module(depMap);\n            }\n\n            return mod;\n        }\n\n        function on(depMap, name, fn) {\n            var id = depMap.id,\n                mod = getOwn(registry, id);\n\n            if (hasProp(defined, id) &&\n                    (!mod || mod.defineEmitComplete)) {\n                if (name === 'defined') {\n                    fn(defined[id]);\n                }\n            } else {\n                mod = getModule(depMap);\n                if (mod.error && name === 'error') {\n                    fn(mod.error);\n                } else {\n                    mod.on(name, fn);\n                }\n            }\n        }\n\n        function onError(err, errback) {\n            var ids = err.requireModules,\n                notified = false;\n\n            if (errback) {\n                errback(err);\n            } else {\n                each(ids, function (id) {\n                    var mod = getOwn(registry, id);\n                    if (mod) {\n                        //Set error on module, so it skips timeout checks.\n                        mod.error = err;\n                        if (mod.events.error) {\n                            notified = true;\n                            mod.emit('error', err);\n                        }\n                    }\n                });\n\n                if (!notified) {\n                    req.onError(err);\n                }\n            }\n        }\n\n        /**\n         * Internal method to transfer globalQueue items to this context's\n         * defQueue.\n         */\n        function takeGlobalQueue() {\n            //Push all the globalDefQueue items into the context's defQueue\n            if (globalDefQueue.length) {\n                //Array splice in the values since the context code has a\n                //local var ref to defQueue, so cannot just reassign the one\n                //on context.\n                apsp.apply(defQueue,\n                           [defQueue.length - 1, 0].concat(globalDefQueue));\n                globalDefQueue = [];\n            }\n        }\n\n        handlers = {\n            'require': function (mod) {\n                if (mod.require) {\n                    return mod.require;\n                } else {\n                    return (mod.require = context.makeRequire(mod.map));\n                }\n            },\n            'exports': function (mod) {\n                mod.usingExports = true;\n                if (mod.map.isDefine) {\n                    if (mod.exports) {\n                        return mod.exports;\n                    } else {\n                        return (mod.exports = defined[mod.map.id] = {});\n                    }\n                }\n            },\n            'module': function (mod) {\n                if (mod.module) {\n                    return mod.module;\n                } else {\n                    return (mod.module = {\n                        id: mod.map.id,\n                        uri: mod.map.url,\n                        config: function () {\n                            var c,\n                                pkg = getOwn(config.pkgs, mod.map.id);\n                            // For packages, only support config targeted\n                            // at the main module.\n                            c = pkg ? getOwn(config.config, mod.map.id + '/' + pkg.main) :\n                                      getOwn(config.config, mod.map.id);\n                            return  c || {};\n                        },\n                        exports: defined[mod.map.id]\n                    });\n                }\n            }\n        };\n\n        function cleanRegistry(id) {\n            //Clean up machinery used for waiting modules.\n            delete registry[id];\n            delete enabledRegistry[id];\n        }\n\n        function breakCycle(mod, traced, processed) {\n            var id = mod.map.id;\n\n            if (mod.error) {\n                mod.emit('error', mod.error);\n            } else {\n                traced[id] = true;\n                each(mod.depMaps, function (depMap, i) {\n                    var depId = depMap.id,\n                        dep = getOwn(registry, depId);\n\n                    //Only force things that have not completed\n                    //being defined, so still in the registry,\n                    //and only if it has not been matched up\n                    //in the module already.\n                    if (dep && !mod.depMatched[i] && !processed[depId]) {\n                        if (getOwn(traced, depId)) {\n                            mod.defineDep(i, defined[depId]);\n                            mod.check(); //pass false?\n                        } else {\n                            breakCycle(dep, traced, processed);\n                        }\n                    }\n                });\n                processed[id] = true;\n            }\n        }\n\n        function checkLoaded() {\n            var map, modId, err, usingPathFallback,\n                waitInterval = config.waitSeconds * 1000,\n                //It is possible to disable the wait interval by using waitSeconds of 0.\n                expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),\n                noLoads = [],\n                reqCalls = [],\n                stillLoading = false,\n                needCycleCheck = true;\n\n            //Do not bother if this call was a result of a cycle break.\n            if (inCheckLoaded) {\n                return;\n            }\n\n            inCheckLoaded = true;\n\n            //Figure out the state of all the modules.\n            eachProp(enabledRegistry, function (mod) {\n                map = mod.map;\n                modId = map.id;\n\n                //Skip things that are not enabled or in error state.\n                if (!mod.enabled) {\n                    return;\n                }\n\n                if (!map.isDefine) {\n                    reqCalls.push(mod);\n                }\n\n                if (!mod.error) {\n                    //If the module should be executed, and it has not\n                    //been inited and time is up, remember it.\n                    if (!mod.inited && expired) {\n                        if (hasPathFallback(modId)) {\n                            usingPathFallback = true;\n                            stillLoading = true;\n                        } else {\n                            noLoads.push(modId);\n                            removeScript(modId);\n                        }\n                    } else if (!mod.inited && mod.fetched && map.isDefine) {\n                        stillLoading = true;\n                        if (!map.prefix) {\n                            //No reason to keep looking for unfinished\n                            //loading. If the only stillLoading is a\n                            //plugin resource though, keep going,\n                            //because it may be that a plugin resource\n                            //is waiting on a non-plugin cycle.\n                            return (needCycleCheck = false);\n                        }\n                    }\n                }\n            });\n\n            if (expired && noLoads.length) {\n                //If wait time expired, throw error of unloaded modules.\n                err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);\n                err.contextName = context.contextName;\n                return onError(err);\n            }\n\n            //Not expired, check for a cycle.\n            if (needCycleCheck) {\n                each(reqCalls, function (mod) {\n                    breakCycle(mod, {}, {});\n                });\n            }\n\n            //If still waiting on loads, and the waiting load is something\n            //other than a plugin resource, or there are still outstanding\n            //scripts, then just try back later.\n            if ((!expired || usingPathFallback) && stillLoading) {\n                //Something is still waiting to load. Wait for it, but only\n                //if a timeout is not already in effect.\n                if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {\n                    checkLoadedTimeoutId = setTimeout(function () {\n                        checkLoadedTimeoutId = 0;\n                        checkLoaded();\n                    }, 50);\n                }\n            }\n\n            inCheckLoaded = false;\n        }\n\n        Module = function (map) {\n            this.events = getOwn(undefEvents, map.id) || {};\n            this.map = map;\n            this.shim = getOwn(config.shim, map.id);\n            this.depExports = [];\n            this.depMaps = [];\n            this.depMatched = [];\n            this.pluginMaps = {};\n            this.depCount = 0;\n\n            /* this.exports this.factory\n               this.depMaps = [],\n               this.enabled, this.fetched\n            */\n        };\n\n        Module.prototype = {\n            init: function (depMaps, factory, errback, options) {\n                options = options || {};\n\n                //Do not do more inits if already done. Can happen if there\n                //are multiple define calls for the same module. That is not\n                //a normal, common case, but it is also not unexpected.\n                if (this.inited) {\n                    return;\n                }\n\n                this.factory = factory;\n\n                if (errback) {\n                    //Register for errors on this module.\n                    this.on('error', errback);\n                } else if (this.events.error) {\n                    //If no errback already, but there are error listeners\n                    //on this module, set up an errback to pass to the deps.\n                    errback = bind(this, function (err) {\n                        this.emit('error', err);\n                    });\n                }\n\n                //Do a copy of the dependency array, so that\n                //source inputs are not modified. For example\n                //\"shim\" deps are passed in here directly, and\n                //doing a direct modification of the depMaps array\n                //would affect that config.\n                this.depMaps = depMaps && depMaps.slice(0);\n\n                this.errback = errback;\n\n                //Indicate this module has be initialized\n                this.inited = true;\n\n                this.ignore = options.ignore;\n\n                //Could have option to init this module in enabled mode,\n                //or could have been previously marked as enabled. However,\n                //the dependencies are not known until init is called. So\n                //if enabled previously, now trigger dependencies as enabled.\n                if (options.enabled || this.enabled) {\n                    //Enable this module and dependencies.\n                    //Will call this.check()\n                    this.enable();\n                } else {\n                    this.check();\n                }\n            },\n\n            defineDep: function (i, depExports) {\n                //Because of cycles, defined callback for a given\n                //export can be called more than once.\n                if (!this.depMatched[i]) {\n                    this.depMatched[i] = true;\n                    this.depCount -= 1;\n                    this.depExports[i] = depExports;\n                }\n            },\n\n            fetch: function () {\n                if (this.fetched) {\n                    return;\n                }\n                this.fetched = true;\n\n                context.startTime = (new Date()).getTime();\n\n                var map = this.map;\n\n                //If the manager is for a plugin managed resource,\n                //ask the plugin to load it now.\n                if (this.shim) {\n                    context.makeRequire(this.map, {\n                        enableBuildCallback: true\n                    })(this.shim.deps || [], bind(this, function () {\n                        return map.prefix ? this.callPlugin() : this.load();\n                    }));\n                } else {\n                    //Regular dependency.\n                    return map.prefix ? this.callPlugin() : this.load();\n                }\n            },\n\n            load: function () {\n                var url = this.map.url;\n\n                //Regular dependency.\n                if (!urlFetched[url]) {\n                    urlFetched[url] = true;\n                    context.load(this.map.id, url);\n                }\n            },\n\n            /**\n             * Checks if the module is ready to define itself, and if so,\n             * define it.\n             */\n            check: function () {\n                if (!this.enabled || this.enabling) {\n                    return;\n                }\n\n                var err, cjsModule,\n                    id = this.map.id,\n                    depExports = this.depExports,\n                    exports = this.exports,\n                    factory = this.factory;\n\n                if (!this.inited) {\n                    this.fetch();\n                } else if (this.error) {\n                    this.emit('error', this.error);\n                } else if (!this.defining) {\n                    //The factory could trigger another require call\n                    //that would result in checking this module to\n                    //define itself again. If already in the process\n                    //of doing that, skip this work.\n                    this.defining = true;\n\n                    if (this.depCount < 1 && !this.defined) {\n                        if (isFunction(factory)) {\n                            //If there is an error listener, favor passing\n                            //to that instead of throwing an error. However,\n                            //only do it for define()'d  modules. require\n                            //errbacks should not be called for failures in\n                            //their callbacks (#699). However if a global\n                            //onError is set, use that.\n                            if ((this.events.error && this.map.isDefine) ||\n                                req.onError !== defaultOnError) {\n                                try {\n                                    exports = context.execCb(id, factory, depExports, exports);\n                                } catch (e) {\n                                    err = e;\n                                }\n                            } else {\n                                exports = context.execCb(id, factory, depExports, exports);\n                            }\n\n                            if (this.map.isDefine) {\n                                //If setting exports via 'module' is in play,\n                                //favor that over return value and exports. After that,\n                                //favor a non-undefined return value over exports use.\n                                cjsModule = this.module;\n                                if (cjsModule &&\n                                        cjsModule.exports !== undefined &&\n                                        //Make sure it is not already the exports value\n                                        cjsModule.exports !== this.exports) {\n                                    exports = cjsModule.exports;\n                                } else if (exports === undefined && this.usingExports) {\n                                    //exports already set the defined value.\n                                    exports = this.exports;\n                                }\n                            }\n\n                            if (err) {\n                                err.requireMap = this.map;\n                                err.requireModules = this.map.isDefine ? [this.map.id] : null;\n                                err.requireType = this.map.isDefine ? 'define' : 'require';\n                                return onError((this.error = err));\n                            }\n\n                        } else {\n                            //Just a literal value\n                            exports = factory;\n                        }\n\n                        this.exports = exports;\n\n                        if (this.map.isDefine && !this.ignore) {\n                            defined[id] = exports;\n\n                            if (req.onResourceLoad) {\n                                req.onResourceLoad(context, this.map, this.depMaps);\n                            }\n                        }\n\n                        //Clean up\n                        cleanRegistry(id);\n\n                        this.defined = true;\n                    }\n\n                    //Finished the define stage. Allow calling check again\n                    //to allow define notifications below in the case of a\n                    //cycle.\n                    this.defining = false;\n\n                    if (this.defined && !this.defineEmitted) {\n                        this.defineEmitted = true;\n                        this.emit('defined', this.exports);\n                        this.defineEmitComplete = true;\n                    }\n\n                }\n            },\n\n            callPlugin: function () {\n                var map = this.map,\n                    id = map.id,\n                    //Map already normalized the prefix.\n                    pluginMap = makeModuleMap(map.prefix);\n\n                //Mark this as a dependency for this plugin, so it\n                //can be traced for cycles.\n                this.depMaps.push(pluginMap);\n\n                on(pluginMap, 'defined', bind(this, function (plugin) {\n                    var load, normalizedMap, normalizedMod,\n                        name = this.map.name,\n                        parentName = this.map.parentMap ? this.map.parentMap.name : null,\n                        localRequire = context.makeRequire(map.parentMap, {\n                            enableBuildCallback: true\n                        });\n\n                    //If current map is not normalized, wait for that\n                    //normalized name to load instead of continuing.\n                    if (this.map.unnormalized) {\n                        //Normalize the ID if the plugin allows it.\n                        if (plugin.normalize) {\n                            name = plugin.normalize(name, function (name) {\n                                return normalize(name, parentName, true);\n                            }) || '';\n                        }\n\n                        //prefix and name should already be normalized, no need\n                        //for applying map config again either.\n                        normalizedMap = makeModuleMap(map.prefix + '!' + name,\n                                                      this.map.parentMap);\n                        on(normalizedMap,\n                            'defined', bind(this, function (value) {\n                                this.init([], function () { return value; }, null, {\n                                    enabled: true,\n                                    ignore: true\n                                });\n                            }));\n\n                        normalizedMod = getOwn(registry, normalizedMap.id);\n                        if (normalizedMod) {\n                            //Mark this as a dependency for this plugin, so it\n                            //can be traced for cycles.\n                            this.depMaps.push(normalizedMap);\n\n                            if (this.events.error) {\n                                normalizedMod.on('error', bind(this, function (err) {\n                                    this.emit('error', err);\n                                }));\n                            }\n                            normalizedMod.enable();\n                        }\n\n                        return;\n                    }\n\n                    load = bind(this, function (value) {\n                        this.init([], function () { return value; }, null, {\n                            enabled: true\n                        });\n                    });\n\n                    load.error = bind(this, function (err) {\n                        this.inited = true;\n                        this.error = err;\n                        err.requireModules = [id];\n\n                        //Remove temp unnormalized modules for this module,\n                        //since they will never be resolved otherwise now.\n                        eachProp(registry, function (mod) {\n                            if (mod.map.id.indexOf(id + '_unnormalized') === 0) {\n                                cleanRegistry(mod.map.id);\n                            }\n                        });\n\n                        onError(err);\n                    });\n\n                    //Allow plugins to load other code without having to know the\n                    //context or how to 'complete' the load.\n                    load.fromText = bind(this, function (text, textAlt) {\n                        /*jslint evil: true */\n                        var moduleName = map.name,\n                            moduleMap = makeModuleMap(moduleName),\n                            hasInteractive = useInteractive;\n\n                        //As of 2.1.0, support just passing the text, to reinforce\n                        //fromText only being called once per resource. Still\n                        //support old style of passing moduleName but discard\n                        //that moduleName in favor of the internal ref.\n                        if (textAlt) {\n                            text = textAlt;\n                        }\n\n                        //Turn off interactive script matching for IE for any define\n                        //calls in the text, then turn it back on at the end.\n                        if (hasInteractive) {\n                            useInteractive = false;\n                        }\n\n                        //Prime the system by creating a module instance for\n                        //it.\n                        getModule(moduleMap);\n\n                        //Transfer any config to this other module.\n                        if (hasProp(config.config, id)) {\n                            config.config[moduleName] = config.config[id];\n                        }\n\n                        try {\n                            req.exec(text);\n                        } catch (e) {\n                            return onError(makeError('fromtexteval',\n                                             'fromText eval for ' + id +\n                                            ' failed: ' + e,\n                                             e,\n                                             [id]));\n                        }\n\n                        if (hasInteractive) {\n                            useInteractive = true;\n                        }\n\n                        //Mark this as a dependency for the plugin\n                        //resource\n                        this.depMaps.push(moduleMap);\n\n                        //Support anonymous modules.\n                        context.completeLoad(moduleName);\n\n                        //Bind the value of that module to the value for this\n                        //resource ID.\n                        localRequire([moduleName], load);\n                    });\n\n                    //Use parentName here since the plugin's name is not reliable,\n                    //could be some weird string with no path that actually wants to\n                    //reference the parentName's path.\n                    plugin.load(map.name, localRequire, load, config);\n                }));\n\n                context.enable(pluginMap, this);\n                this.pluginMaps[pluginMap.id] = pluginMap;\n            },\n\n            enable: function () {\n                enabledRegistry[this.map.id] = this;\n                this.enabled = true;\n\n                //Set flag mentioning that the module is enabling,\n                //so that immediate calls to the defined callbacks\n                //for dependencies do not trigger inadvertent load\n                //with the depCount still being zero.\n                this.enabling = true;\n\n                //Enable each dependency\n                each(this.depMaps, bind(this, function (depMap, i) {\n                    var id, mod, handler;\n\n                    if (typeof depMap === 'string') {\n                        //Dependency needs to be converted to a depMap\n                        //and wired up to this module.\n                        depMap = makeModuleMap(depMap,\n                                               (this.map.isDefine ? this.map : this.map.parentMap),\n                                               false,\n                                               !this.skipMap);\n                        this.depMaps[i] = depMap;\n\n                        handler = getOwn(handlers, depMap.id);\n\n                        if (handler) {\n                            this.depExports[i] = handler(this);\n                            return;\n                        }\n\n                        this.depCount += 1;\n\n                        on(depMap, 'defined', bind(this, function (depExports) {\n                            this.defineDep(i, depExports);\n                            this.check();\n                        }));\n\n                        if (this.errback) {\n                            on(depMap, 'error', bind(this, this.errback));\n                        }\n                    }\n\n                    id = depMap.id;\n                    mod = registry[id];\n\n                    //Skip special modules like 'require', 'exports', 'module'\n                    //Also, don't call enable if it is already enabled,\n                    //important in circular dependency cases.\n                    if (!hasProp(handlers, id) && mod && !mod.enabled) {\n                        context.enable(depMap, this);\n                    }\n                }));\n\n                //Enable each plugin that is used in\n                //a dependency\n                eachProp(this.pluginMaps, bind(this, function (pluginMap) {\n                    var mod = getOwn(registry, pluginMap.id);\n                    if (mod && !mod.enabled) {\n                        context.enable(pluginMap, this);\n                    }\n                }));\n\n                this.enabling = false;\n\n                this.check();\n            },\n\n            on: function (name, cb) {\n                var cbs = this.events[name];\n                if (!cbs) {\n                    cbs = this.events[name] = [];\n                }\n                cbs.push(cb);\n            },\n\n            emit: function (name, evt) {\n                each(this.events[name], function (cb) {\n                    cb(evt);\n                });\n                if (name === 'error') {\n                    //Now that the error handler was triggered, remove\n                    //the listeners, since this broken Module instance\n                    //can stay around for a while in the registry.\n                    delete this.events[name];\n                }\n            }\n        };\n\n        function callGetModule(args) {\n            //Skip modules already defined.\n            if (!hasProp(defined, args[0])) {\n                getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);\n            }\n        }\n\n        function removeListener(node, func, name, ieName) {\n            //Favor detachEvent because of IE9\n            //issue, see attachEvent/addEventListener comment elsewhere\n            //in this file.\n            if (node.detachEvent && !isOpera) {\n                //Probably IE. If not it will throw an error, which will be\n                //useful to know.\n                if (ieName) {\n                    node.detachEvent(ieName, func);\n                }\n            } else {\n                node.removeEventListener(name, func, false);\n            }\n        }\n\n        /**\n         * Given an event from a script node, get the requirejs info from it,\n         * and then removes the event listeners on the node.\n         * @param {Event} evt\n         * @returns {Object}\n         */\n        function getScriptData(evt) {\n            //Using currentTarget instead of target for Firefox 2.0's sake. Not\n            //all old browsers will be supported, but this one was easy enough\n            //to support and still makes sense.\n            var node = evt.currentTarget || evt.srcElement;\n\n            //Remove the listeners once here.\n            removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');\n            removeListener(node, context.onScriptError, 'error');\n\n            return {\n                node: node,\n                id: node && node.getAttribute('data-requiremodule')\n            };\n        }\n\n        function intakeDefines() {\n            var args;\n\n            //Any defined modules in the global queue, intake them now.\n            takeGlobalQueue();\n\n            //Make sure any remaining defQueue items get properly processed.\n            while (defQueue.length) {\n                args = defQueue.shift();\n                if (args[0] === null) {\n                    return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));\n                } else {\n                    //args are id, deps, factory. Should be normalized by the\n                    //define() function.\n                    callGetModule(args);\n                }\n            }\n        }\n\n        context = {\n            config: config,\n            contextName: contextName,\n            registry: registry,\n            defined: defined,\n            urlFetched: urlFetched,\n            defQueue: defQueue,\n            Module: Module,\n            makeModuleMap: makeModuleMap,\n            nextTick: req.nextTick,\n            onError: onError,\n\n            /**\n             * Set a configuration for the context.\n             * @param {Object} cfg config object to integrate.\n             */\n            configure: function (cfg) {\n                //Make sure the baseUrl ends in a slash.\n                if (cfg.baseUrl) {\n                    if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {\n                        cfg.baseUrl += '/';\n                    }\n                }\n\n                //Save off the paths and packages since they require special processing,\n                //they are additive.\n                var pkgs = config.pkgs,\n                    shim = config.shim,\n                    objs = {\n                        paths: true,\n                        config: true,\n                        map: true\n                    };\n\n                eachProp(cfg, function (value, prop) {\n                    if (objs[prop]) {\n                        if (prop === 'map') {\n                            if (!config.map) {\n                                config.map = {};\n                            }\n                            mixin(config[prop], value, true, true);\n                        } else {\n                            mixin(config[prop], value, true);\n                        }\n                    } else {\n                        config[prop] = value;\n                    }\n                });\n\n                //Merge shim\n                if (cfg.shim) {\n                    eachProp(cfg.shim, function (value, id) {\n                        //Normalize the structure\n                        if (isArray(value)) {\n                            value = {\n                                deps: value\n                            };\n                        }\n                        if ((value.exports || value.init) && !value.exportsFn) {\n                            value.exportsFn = context.makeShimExports(value);\n                        }\n                        shim[id] = value;\n                    });\n                    config.shim = shim;\n                }\n\n                //Adjust packages if necessary.\n                if (cfg.packages) {\n                    each(cfg.packages, function (pkgObj) {\n                        var location;\n\n                        pkgObj = typeof pkgObj === 'string' ? { name: pkgObj } : pkgObj;\n                        location = pkgObj.location;\n\n                        //Create a brand new object on pkgs, since currentPackages can\n                        //be passed in again, and config.pkgs is the internal transformed\n                        //state for all package configs.\n                        pkgs[pkgObj.name] = {\n                            name: pkgObj.name,\n                            location: location || pkgObj.name,\n                            //Remove leading dot in main, so main paths are normalized,\n                            //and remove any trailing .js, since different package\n                            //envs have different conventions: some use a module name,\n                            //some use a file name.\n                            main: (pkgObj.main || 'main')\n                                  .replace(currDirRegExp, '')\n                                  .replace(jsSuffixRegExp, '')\n                        };\n                    });\n\n                    //Done with modifications, assing packages back to context config\n                    config.pkgs = pkgs;\n                }\n\n                //If there are any \"waiting to execute\" modules in the registry,\n                //update the maps for them, since their info, like URLs to load,\n                //may have changed.\n                eachProp(registry, function (mod, id) {\n                    //If module already has init called, since it is too\n                    //late to modify them, and ignore unnormalized ones\n                    //since they are transient.\n                    if (!mod.inited && !mod.map.unnormalized) {\n                        mod.map = makeModuleMap(id);\n                    }\n                });\n\n                //If a deps array or a config callback is specified, then call\n                //require with those args. This is useful when require is defined as a\n                //config object before require.js is loaded.\n                if (cfg.deps || cfg.callback) {\n                    context.require(cfg.deps || [], cfg.callback);\n                }\n            },\n\n            makeShimExports: function (value) {\n                function fn() {\n                    var ret;\n                    if (value.init) {\n                        ret = value.init.apply(global, arguments);\n                    }\n                    return ret || (value.exports && getGlobal(value.exports));\n                }\n                return fn;\n            },\n\n            makeRequire: function (relMap, options) {\n                options = options || {};\n\n                function localRequire(deps, callback, errback) {\n                    var id, map, requireMod;\n\n                    if (options.enableBuildCallback && callback && isFunction(callback)) {\n                        callback.__requireJsBuild = true;\n                    }\n\n                    if (typeof deps === 'string') {\n                        if (isFunction(callback)) {\n                            //Invalid call\n                            return onError(makeError('requireargs', 'Invalid require call'), errback);\n                        }\n\n                        //If require|exports|module are requested, get the\n                        //value for them from the special handlers. Caveat:\n                        //this only works while module is being defined.\n                        if (relMap && hasProp(handlers, deps)) {\n                            return handlers[deps](registry[relMap.id]);\n                        }\n\n                        //Synchronous access to one module. If require.get is\n                        //available (as in the Node adapter), prefer that.\n                        if (req.get) {\n                            return req.get(context, deps, relMap, localRequire);\n                        }\n\n                        //Normalize module name, if it contains . or ..\n                        map = makeModuleMap(deps, relMap, false, true);\n                        id = map.id;\n\n                        if (!hasProp(defined, id)) {\n                            return onError(makeError('notloaded', 'Module name \"' +\n                                        id +\n                                        '\" has not been loaded yet for context: ' +\n                                        contextName +\n                                        (relMap ? '' : '. Use require([])')));\n                        }\n                        return defined[id];\n                    }\n\n                    //Grab defines waiting in the global queue.\n                    intakeDefines();\n\n                    //Mark all the dependencies as needing to be loaded.\n                    context.nextTick(function () {\n                        //Some defines could have been added since the\n                        //require call, collect them.\n                        intakeDefines();\n\n                        requireMod = getModule(makeModuleMap(null, relMap));\n\n                        //Store if map config should be applied to this require\n                        //call for dependencies.\n                        requireMod.skipMap = options.skipMap;\n\n                        requireMod.init(deps, callback, errback, {\n                            enabled: true\n                        });\n\n                        checkLoaded();\n                    });\n\n                    return localRequire;\n                }\n\n                mixin(localRequire, {\n                    isBrowser: isBrowser,\n\n                    /**\n                     * Converts a module name + .extension into an URL path.\n                     * *Requires* the use of a module name. It does not support using\n                     * plain URLs like nameToUrl.\n                     */\n                    toUrl: function (moduleNamePlusExt) {\n                        var ext,\n                            index = moduleNamePlusExt.lastIndexOf('.'),\n                            segment = moduleNamePlusExt.split('/')[0],\n                            isRelative = segment === '.' || segment === '..';\n\n                        //Have a file extension alias, and it is not the\n                        //dots from a relative path.\n                        if (index !== -1 && (!isRelative || index > 1)) {\n                            ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);\n                            moduleNamePlusExt = moduleNamePlusExt.substring(0, index);\n                        }\n\n                        return context.nameToUrl(normalize(moduleNamePlusExt,\n                                                relMap && relMap.id, true), ext,  true);\n                    },\n\n                    defined: function (id) {\n                        return hasProp(defined, makeModuleMap(id, relMap, false, true).id);\n                    },\n\n                    specified: function (id) {\n                        id = makeModuleMap(id, relMap, false, true).id;\n                        return hasProp(defined, id) || hasProp(registry, id);\n                    }\n                });\n\n                //Only allow undef on top level require calls\n                if (!relMap) {\n                    localRequire.undef = function (id) {\n                        //Bind any waiting define() calls to this context,\n                        //fix for #408\n                        takeGlobalQueue();\n\n                        var map = makeModuleMap(id, relMap, true),\n                            mod = getOwn(registry, id);\n\n                        delete defined[id];\n                        delete urlFetched[map.url];\n                        delete undefEvents[id];\n\n                        if (mod) {\n                            //Hold on to listeners in case the\n                            //module will be attempted to be reloaded\n                            //using a different config.\n                            if (mod.events.defined) {\n                                undefEvents[id] = mod.events;\n                            }\n\n                            cleanRegistry(id);\n                        }\n                    };\n                }\n\n                return localRequire;\n            },\n\n            /**\n             * Called to enable a module if it is still in the registry\n             * awaiting enablement. A second arg, parent, the parent module,\n             * is passed in for context, when this method is overriden by\n             * the optimizer. Not shown here to keep code compact.\n             */\n            enable: function (depMap) {\n                var mod = getOwn(registry, depMap.id);\n                if (mod) {\n                    getModule(depMap).enable();\n                }\n            },\n\n            /**\n             * Internal method used by environment adapters to complete a load event.\n             * A load event could be a script load or just a load pass from a synchronous\n             * load call.\n             * @param {String} moduleName the name of the module to potentially complete.\n             */\n            completeLoad: function (moduleName) {\n                var found, args, mod,\n                    shim = getOwn(config.shim, moduleName) || {},\n                    shExports = shim.exports;\n\n                takeGlobalQueue();\n\n                while (defQueue.length) {\n                    args = defQueue.shift();\n                    if (args[0] === null) {\n                        args[0] = moduleName;\n                        //If already found an anonymous module and bound it\n                        //to this name, then this is some other anon module\n                        //waiting for its completeLoad to fire.\n                        if (found) {\n                            break;\n                        }\n                        found = true;\n                    } else if (args[0] === moduleName) {\n                        //Found matching define call for this script!\n                        found = true;\n                    }\n\n                    callGetModule(args);\n                }\n\n                //Do this after the cycle of callGetModule in case the result\n                //of those calls/init calls changes the registry.\n                mod = getOwn(registry, moduleName);\n\n                if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {\n                    if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {\n                        if (hasPathFallback(moduleName)) {\n                            return;\n                        } else {\n                            return onError(makeError('nodefine',\n                                             'No define call for ' + moduleName,\n                                             null,\n                                             [moduleName]));\n                        }\n                    } else {\n                        //A script that does not call define(), so just simulate\n                        //the call for it.\n                        callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);\n                    }\n                }\n\n                checkLoaded();\n            },\n\n            /**\n             * Converts a module name to a file path. Supports cases where\n             * moduleName may actually be just an URL.\n             * Note that it **does not** call normalize on the moduleName,\n             * it is assumed to have already been normalized. This is an\n             * internal API, not a public one. Use toUrl for the public API.\n             */\n            nameToUrl: function (moduleName, ext, skipExt) {\n                var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,\n                    parentPath;\n\n                //If a colon is in the URL, it indicates a protocol is used and it is just\n                //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)\n                //or ends with .js, then assume the user meant to use an url and not a module id.\n                //The slash is important for protocol-less URLs as well as full paths.\n                if (req.jsExtRegExp.test(moduleName)) {\n                    //Just a plain path, not module name lookup, so just return it.\n                    //Add extension if it is included. This is a bit wonky, only non-.js things pass\n                    //an extension, this method probably needs to be reworked.\n                    url = moduleName + (ext || '');\n                } else {\n                    //A module that needs to be converted to a path.\n                    paths = config.paths;\n                    pkgs = config.pkgs;\n\n                    syms = moduleName.split('/');\n                    //For each module name segment, see if there is a path\n                    //registered for it. Start with most specific name\n                    //and work up from it.\n                    for (i = syms.length; i > 0; i -= 1) {\n                        parentModule = syms.slice(0, i).join('/');\n                        pkg = getOwn(pkgs, parentModule);\n                        parentPath = getOwn(paths, parentModule);\n                        if (parentPath) {\n                            //If an array, it means there are a few choices,\n                            //Choose the one that is desired\n                            if (isArray(parentPath)) {\n                                parentPath = parentPath[0];\n                            }\n                            syms.splice(0, i, parentPath);\n                            break;\n                        } else if (pkg) {\n                            //If module name is just the package name, then looking\n                            //for the main module.\n                            if (moduleName === pkg.name) {\n                                pkgPath = pkg.location + '/' + pkg.main;\n                            } else {\n                                pkgPath = pkg.location;\n                            }\n                            syms.splice(0, i, pkgPath);\n                            break;\n                        }\n                    }\n\n                    //Join the path parts together, then figure out if baseUrl is needed.\n                    url = syms.join('/');\n                    url += (ext || (/\\?/.test(url) || skipExt ? '' : '.js'));\n                    url = (url.charAt(0) === '/' || url.match(/^[\\w\\+\\.\\-]+:/) ? '' : config.baseUrl) + url;\n                }\n\n                return config.urlArgs ? url +\n                                        ((url.indexOf('?') === -1 ? '?' : '&') +\n                                         config.urlArgs) : url;\n            },\n\n            //Delegates to req.load. Broken out as a separate function to\n            //allow overriding in the optimizer.\n            load: function (id, url) {\n                req.load(context, id, url);\n            },\n\n            /**\n             * Executes a module callback function. Broken out as a separate function\n             * solely to allow the build system to sequence the files in the built\n             * layer in the right sequence.\n             *\n             * @private\n             */\n            execCb: function (name, callback, args, exports) {\n                return callback.apply(exports, args);\n            },\n\n            /**\n             * callback for script loads, used to check status of loading.\n             *\n             * @param {Event} evt the event from the browser for the script\n             * that was loaded.\n             */\n            onScriptLoad: function (evt) {\n                //Using currentTarget instead of target for Firefox 2.0's sake. Not\n                //all old browsers will be supported, but this one was easy enough\n                //to support and still makes sense.\n                if (evt.type === 'load' ||\n                        (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {\n                    //Reset interactive script so a script node is not held onto for\n                    //to long.\n                    interactiveScript = null;\n\n                    //Pull out the name of the module and the context.\n                    var data = getScriptData(evt);\n                    context.completeLoad(data.id);\n                }\n            },\n\n            /**\n             * Callback for script errors.\n             */\n            onScriptError: function (evt) {\n                var data = getScriptData(evt);\n                if (!hasPathFallback(data.id)) {\n                    return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id]));\n                }\n            }\n        };\n\n        context.require = context.makeRequire();\n        return context;\n    }\n\n    /**\n     * Main entry point.\n     *\n     * If the only argument to require is a string, then the module that\n     * is represented by that string is fetched for the appropriate context.\n     *\n     * If the first argument is an array, then it will be treated as an array\n     * of dependency string names to fetch. An optional function callback can\n     * be specified to execute when all of those dependencies are available.\n     *\n     * Make a local req variable to help Caja compliance (it assumes things\n     * on a require that are not standardized), and to give a short\n     * name for minification/local scope use.\n     */\n    req = requirejs = function (deps, callback, errback, optional) {\n\n        //Find the right context, use default\n        var context, config,\n            contextName = defContextName;\n\n        // Determine if have config object in the call.\n        if (!isArray(deps) && typeof deps !== 'string') {\n            // deps is a config object\n            config = deps;\n            if (isArray(callback)) {\n                // Adjust args if there are dependencies\n                deps = callback;\n                callback = errback;\n                errback = optional;\n            } else {\n                deps = [];\n            }\n        }\n\n        if (config && config.context) {\n            contextName = config.context;\n        }\n\n        context = getOwn(contexts, contextName);\n        if (!context) {\n            context = contexts[contextName] = req.s.newContext(contextName);\n        }\n\n        if (config) {\n            context.configure(config);\n        }\n\n        return context.require(deps, callback, errback);\n    };\n\n    /**\n     * Support require.config() to make it easier to cooperate with other\n     * AMD loaders on globally agreed names.\n     */\n    req.config = function (config) {\n        return req(config);\n    };\n\n    /**\n     * Execute something after the current tick\n     * of the event loop. Override for other envs\n     * that have a better solution than setTimeout.\n     * @param  {Function} fn function to execute later.\n     */\n    req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {\n        setTimeout(fn, 4);\n    } : function (fn) { fn(); };\n\n    /**\n     * Export require as a global, but only if it does not already exist.\n     */\n    if (!require) {\n        require = req;\n    }\n\n    req.version = version;\n\n    //Used to filter out dependencies that are already paths.\n    req.jsExtRegExp = /^\\/|:|\\?|\\.js$/;\n    req.isBrowser = isBrowser;\n    s = req.s = {\n        contexts: contexts,\n        newContext: newContext\n    };\n\n    //Create default context.\n    req({});\n\n    //Exports some context-sensitive methods on global require.\n    each([\n        'toUrl',\n        'undef',\n        'defined',\n        'specified'\n    ], function (prop) {\n        //Reference from contexts instead of early binding to default context,\n        //so that during builds, the latest instance of the default context\n        //with its config gets used.\n        req[prop] = function () {\n            var ctx = contexts[defContextName];\n            return ctx.require[prop].apply(ctx, arguments);\n        };\n    });\n\n    if (isBrowser) {\n        head = s.head = document.getElementsByTagName('head')[0];\n        //If BASE tag is in play, using appendChild is a problem for IE6.\n        //When that browser dies, this can be removed. Details in this jQuery bug:\n        //http://dev.jquery.com/ticket/2709\n        baseElement = document.getElementsByTagName('base')[0];\n        if (baseElement) {\n            head = s.head = baseElement.parentNode;\n        }\n    }\n\n    /**\n     * Any errors that require explicitly generates will be passed to this\n     * function. Intercept/override it if you want custom error handling.\n     * @param {Error} err the error object.\n     */\n    req.onError = defaultOnError;\n\n    /**\n     * Creates the node for the load command. Only used in browser envs.\n     */\n    req.createNode = function (config, moduleName, url) {\n        var node = config.xhtml ?\n                document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :\n                document.createElement('script');\n        node.type = config.scriptType || 'text/javascript';\n        node.charset = 'utf-8';\n        node.async = true;\n        return node;\n    };\n\n    /**\n     * Does the request to load a module for the browser case.\n     * Make this a separate function to allow other environments\n     * to override it.\n     *\n     * @param {Object} context the require context to find state.\n     * @param {String} moduleName the name of the module.\n     * @param {Object} url the URL to the module.\n     */\n    req.load = function (context, moduleName, url) {\n        var config = (context && context.config) || {},\n            node;\n        if (isBrowser) {\n            //In the browser so use a script tag\n            node = req.createNode(config, moduleName, url);\n\n            node.setAttribute('data-requirecontext', context.contextName);\n            node.setAttribute('data-requiremodule', moduleName);\n\n            //Set up load listener. Test attachEvent first because IE9 has\n            //a subtle issue in its addEventListener and script onload firings\n            //that do not match the behavior of all other browsers with\n            //addEventListener support, which fire the onload event for a\n            //script right after the script execution. See:\n            //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution\n            //UNFORTUNATELY Opera implements attachEvent but does not follow the script\n            //script execution mode.\n            if (node.attachEvent &&\n                    //Check if node.attachEvent is artificially added by custom script or\n                    //natively supported by browser\n                    //read https://github.com/jrburke/requirejs/issues/187\n                    //if we can NOT find [native code] then it must NOT natively supported.\n                    //in IE8, node.attachEvent does not have toString()\n                    //Note the test for \"[native code\" with no closing brace, see:\n                    //https://github.com/jrburke/requirejs/issues/273\n                    !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&\n                    !isOpera) {\n                //Probably IE. IE (at least 6-8) do not fire\n                //script onload right after executing the script, so\n                //we cannot tie the anonymous define call to a name.\n                //However, IE reports the script as being in 'interactive'\n                //readyState at the time of the define call.\n                useInteractive = true;\n\n                node.attachEvent('onreadystatechange', context.onScriptLoad);\n                //It would be great to add an error handler here to catch\n                //404s in IE9+. However, onreadystatechange will fire before\n                //the error handler, so that does not help. If addEventListener\n                //is used, then IE will fire error before load, but we cannot\n                //use that pathway given the connect.microsoft.com issue\n                //mentioned above about not doing the 'script execute,\n                //then fire the script load event listener before execute\n                //next script' that other browsers do.\n                //Best hope: IE10 fixes the issues,\n                //and then destroys all installs of IE 6-9.\n                //node.attachEvent('onerror', context.onScriptError);\n            } else {\n                node.addEventListener('load', context.onScriptLoad, false);\n                node.addEventListener('error', context.onScriptError, false);\n            }\n            node.src = url;\n\n            //For some cache cases in IE 6-8, the script executes before the end\n            //of the appendChild execution, so to tie an anonymous define\n            //call to the module name (which is stored on the node), hold on\n            //to a reference to this node, but clear after the DOM insertion.\n            currentlyAddingScript = node;\n            if (baseElement) {\n                head.insertBefore(node, baseElement);\n            } else {\n                head.appendChild(node);\n            }\n            currentlyAddingScript = null;\n\n            return node;\n        } else if (isWebWorker) {\n            try {\n                //In a web worker, use importScripts. This is not a very\n                //efficient use of importScripts, importScripts will block until\n                //its script is downloaded and evaluated. However, if web workers\n                //are in play, the expectation that a build has been done so that\n                //only one script needs to be loaded anyway. This may need to be\n                //reevaluated if other use cases become common.\n                importScripts(url);\n\n                //Account for anonymous modules\n                context.completeLoad(moduleName);\n            } catch (e) {\n                context.onError(makeError('importscripts',\n                                'importScripts failed for ' +\n                                    moduleName + ' at ' + url,\n                                e,\n                                [moduleName]));\n            }\n        }\n    };\n\n    function getInteractiveScript() {\n        if (interactiveScript && interactiveScript.readyState === 'interactive') {\n            return interactiveScript;\n        }\n\n        eachReverse(scripts(), function (script) {\n            if (script.readyState === 'interactive') {\n                return (interactiveScript = script);\n            }\n        });\n        return interactiveScript;\n    }\n\n    //Look for a data-main script attribute, which could also adjust the baseUrl.\n    if (isBrowser) {\n        //Figure out baseUrl. Get it from the script tag with require.js in it.\n        eachReverse(scripts(), function (script) {\n            //Set the 'head' where we can append children by\n            //using the script's parent.\n            if (!head) {\n                head = script.parentNode;\n            }\n\n            //Look for a data-main attribute to set main script for the page\n            //to load. If it is there, the path to data main becomes the\n            //baseUrl, if it is not already set.\n            dataMain = script.getAttribute('data-main');\n            if (dataMain) {\n                //Preserve dataMain in case it is a path (i.e. contains '?')\n                mainScript = dataMain;\n\n                //Set final baseUrl if there is not already an explicit one.\n                if (!cfg.baseUrl) {\n                    //Pull off the directory of data-main for use as the\n                    //baseUrl.\n                    src = mainScript.split('/');\n                    mainScript = src.pop();\n                    subPath = src.length ? src.join('/')  + '/' : './';\n\n                    cfg.baseUrl = subPath;\n                }\n\n                //Strip off any trailing .js since mainScript is now\n                //like a module name.\n                mainScript = mainScript.replace(jsSuffixRegExp, '');\n\n                 //If mainScript is still a path, fall back to dataMain\n                if (req.jsExtRegExp.test(mainScript)) {\n                    mainScript = dataMain;\n                }\n\n                //Put the data-main script in the files to load.\n                cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];\n\n                return true;\n            }\n        });\n    }\n\n    /**\n     * The function that handles definitions of modules. Differs from\n     * require() in that a string for the module should be the first argument,\n     * and the function to execute after dependencies are loaded should\n     * return a value to define the module corresponding to the first argument's\n     * name.\n     */\n    define = function (name, deps, callback) {\n        var node, context;\n\n        //Allow for anonymous modules\n        if (typeof name !== 'string') {\n            //Adjust args appropriately\n            callback = deps;\n            deps = name;\n            name = null;\n        }\n\n        //This module may not have dependencies\n        if (!isArray(deps)) {\n            callback = deps;\n            deps = null;\n        }\n\n        //If no name, and callback is a function, then figure out if it a\n        //CommonJS thing with dependencies.\n        if (!deps && isFunction(callback)) {\n            deps = [];\n            //Remove comments from the callback string,\n            //look for require calls, and pull them into the dependencies,\n            //but only if there are function args.\n            if (callback.length) {\n                callback\n                    .toString()\n                    .replace(commentRegExp, '')\n                    .replace(cjsRequireRegExp, function (match, dep) {\n                        deps.push(dep);\n                    });\n\n                //May be a CommonJS thing even without require calls, but still\n                //could use exports, and module. Avoid doing exports and module\n                //work though if it just needs require.\n                //REQUIRES the function to expect the CommonJS variables in the\n                //order listed below.\n                deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);\n            }\n        }\n\n        //If in IE 6-8 and hit an anonymous define() call, do the interactive\n        //work.\n        if (useInteractive) {\n            node = currentlyAddingScript || getInteractiveScript();\n            if (node) {\n                if (!name) {\n                    name = node.getAttribute('data-requiremodule');\n                }\n                context = contexts[node.getAttribute('data-requirecontext')];\n            }\n        }\n\n        //Always save off evaluating the def call until the script onload handler.\n        //This allows multiple modules to be in a file without prematurely\n        //tracing dependencies, and allows for anonymous module support,\n        //where the module name is not known until the script onload event\n        //occurs. If no context, use the global queue, and get it processed\n        //in the onscript load callback.\n        (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);\n    };\n\n    define.amd = {\n        jQuery: true\n    };\n\n\n    /**\n     * Executes the text. Normally just uses eval, but can be modified\n     * to use a better, environment-specific call. Only used for transpiling\n     * loader plugins, not for plain JS modules.\n     * @param {String} text the text to execute/evaluate.\n     */\n    req.exec = function (text) {\n        /*jslint evil: true */\n        return eval(text);\n    };\n\n    //Set up with config info.\n    req(cfg);\n}(this));\n"
  },
  {
    "path": "togetherjs/libs/require.js",
    "content": "/*\n RequireJS 2.1.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n Available via the MIT or new BSD license.\n see: http://github.com/jrburke/requirejs for details\n*/\nvar requirejs,require,define;\n(function(Z){function H(b){return\"[object Function]\"===L.call(b)}function I(b){return\"[object Array]\"===L.call(b)}function y(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function M(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function s(b,c){return ga.call(b,c)}function l(b,c){return s(b,c)&&b[c]}function F(b,c){for(var d in b)if(s(b,d)&&c(b[d],d))break}function Q(b,c,d,h){c&&F(c,function(c,j){if(d||!s(b,j))h&&\"string\"!==typeof c?(b[j]||(b[j]={}),Q(b[j],\nc,d,h)):b[j]=c});return b}function u(b,c){return function(){return c.apply(b,arguments)}}function aa(b){throw b;}function ba(b){if(!b)return b;var c=Z;y(b.split(\".\"),function(b){c=c[b]});return c}function A(b,c,d,h){c=Error(c+\"\\nhttp://requirejs.org/docs/errors.html#\"+b);c.requireType=b;c.requireModules=h;d&&(c.originalError=d);return c}function ha(b){function c(a,f,b){var e,m,c,g,d,h,j,i=f&&f.split(\"/\");e=i;var n=k.map,p=n&&n[\"*\"];if(a&&\".\"===a.charAt(0))if(f){e=l(k.pkgs,f)?i=[f]:i.slice(0,i.length-\n1);f=a=e.concat(a.split(\"/\"));for(e=0;f[e];e+=1)if(m=f[e],\".\"===m)f.splice(e,1),e-=1;else if(\"..\"===m)if(1===e&&(\"..\"===f[2]||\"..\"===f[0]))break;else 0<e&&(f.splice(e-1,2),e-=2);e=l(k.pkgs,f=a[0]);a=a.join(\"/\");e&&a===f+\"/\"+e.main&&(a=f)}else 0===a.indexOf(\"./\")&&(a=a.substring(2));if(b&&n&&(i||p)){f=a.split(\"/\");for(e=f.length;0<e;e-=1){c=f.slice(0,e).join(\"/\");if(i)for(m=i.length;0<m;m-=1)if(b=l(n,i.slice(0,m).join(\"/\")))if(b=l(b,c)){g=b;d=e;break}if(g)break;!h&&(p&&l(p,c))&&(h=l(p,c),j=e)}!g&&\nh&&(g=h,d=j);g&&(f.splice(0,d,g),a=f.join(\"/\"))}return a}function d(a){z&&y(document.getElementsByTagName(\"script\"),function(f){if(f.getAttribute(\"data-requiremodule\")===a&&f.getAttribute(\"data-requirecontext\")===i.contextName)return f.parentNode.removeChild(f),!0})}function h(a){var f=l(k.paths,a);if(f&&I(f)&&1<f.length)return d(a),f.shift(),i.require.undef(a),i.require([a]),!0}function $(a){var f,b=a?a.indexOf(\"!\"):-1;-1<b&&(f=a.substring(0,b),a=a.substring(b+1,a.length));return[f,a]}function n(a,\nf,b,e){var m,B,g=null,d=f?f.name:null,h=a,j=!0,k=\"\";a||(j=!1,a=\"_@r\"+(L+=1));a=$(a);g=a[0];a=a[1];g&&(g=c(g,d,e),B=l(r,g));a&&(g?k=B&&B.normalize?B.normalize(a,function(a){return c(a,d,e)}):c(a,d,e):(k=c(a,d,e),a=$(k),g=a[0],k=a[1],b=!0,m=i.nameToUrl(k)));b=g&&!B&&!b?\"_unnormalized\"+(M+=1):\"\";return{prefix:g,name:k,parentMap:f,unnormalized:!!b,url:m,originalName:h,isDefine:j,id:(g?g+\"!\"+k:k)+b}}function q(a){var f=a.id,b=l(p,f);b||(b=p[f]=new i.Module(a));return b}function t(a,f,b){var e=a.id,m=l(p,\ne);if(s(r,e)&&(!m||m.defineEmitComplete))\"defined\"===f&&b(r[e]);else if(m=q(a),m.error&&\"error\"===f)b(m.error);else m.on(f,b)}function v(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(y(b,function(f){if(f=l(p,f))f.error=a,f.events.error&&(e=!0,f.emit(\"error\",a))}),!e)j.onError(a)}function w(){R.length&&(ia.apply(G,[G.length-1,0].concat(R)),R=[])}function x(a){delete p[a];delete T[a]}function E(a,f,b){var e=a.map.id;a.error?a.emit(\"error\",a.error):(f[e]=!0,y(a.depMaps,function(e,c){var g=e.id,\nd=l(p,g);d&&(!a.depMatched[c]&&!b[g])&&(l(f,g)?(a.defineDep(c,r[g]),a.check()):E(d,f,b))}),b[e]=!0)}function C(){var a,f,b,e,m=(b=1E3*k.waitSeconds)&&i.startTime+b<(new Date).getTime(),c=[],g=[],j=!1,l=!0;if(!U){U=!0;F(T,function(b){a=b.map;f=a.id;if(b.enabled&&(a.isDefine||g.push(b),!b.error))if(!b.inited&&m)h(f)?j=e=!0:(c.push(f),d(f));else if(!b.inited&&(b.fetched&&a.isDefine)&&(j=!0,!a.prefix))return l=!1});if(m&&c.length)return b=A(\"timeout\",\"Load timeout for modules: \"+c,null,c),b.contextName=\ni.contextName,v(b);l&&y(g,function(a){E(a,{},{})});if((!m||e)&&j)if((z||da)&&!V)V=setTimeout(function(){V=0;C()},50);U=!1}}function D(a){s(r,a[0])||q(n(a[0],null,!0)).init(a[1],a[2])}function J(a){var a=a.currentTarget||a.srcElement,b=i.onScriptLoad;a.detachEvent&&!W?a.detachEvent(\"onreadystatechange\",b):a.removeEventListener(\"load\",b,!1);b=i.onScriptError;(!a.detachEvent||W)&&a.removeEventListener(\"error\",b,!1);return{node:a,id:a&&a.getAttribute(\"data-requiremodule\")}}function K(){var a;for(w();G.length;){a=\nG.shift();if(null===a[0])return v(A(\"mismatch\",\"Mismatched anonymous define() module: \"+a[a.length-1]));D(a)}}var U,X,i,N,V,k={waitSeconds:7,baseUrl:\"./\",paths:{},pkgs:{},shim:{},config:{}},p={},T={},Y={},G=[],r={},S={},L=1,M=1;N={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=r[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){var b=\nl(k.pkgs,a.map.id);return(b?l(k.config,a.map.id+\"/\"+b.main):l(k.config,a.map.id))||{}},exports:r[a.map.id]}}};X=function(a){this.events=l(Y,a.id)||{};this.map=a;this.shim=l(k.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};X.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on(\"error\",c);else this.events.error&&(c=u(this,function(a){this.emit(\"error\",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;\nthis.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],u(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=\nthis.map.url;S[a]||(S[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,m=this.factory;if(this.inited)if(this.error)this.emit(\"error\",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(H(m)){if(this.events.error&&this.map.isDefine||j.onError!==aa)try{e=i.execCb(c,m,b,e)}catch(d){a=d}else e=i.execCb(c,m,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==\nthis.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?\"define\":\"require\",v(this.error=a)}else e=m;this.exports=e;if(this.map.isDefine&&!this.ignore&&(r[c]=e,j.onResourceLoad))j.onResourceLoad(i,this.map,this.depMaps);x(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit(\"defined\",this.exports),this.defineEmitComplete=\n!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=n(a.prefix);this.depMaps.push(d);t(d,\"defined\",u(this,function(e){var m,d;d=this.map.name;var g=this.map.parentMap?this.map.parentMap.name:null,h=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,g,!0)})||\"\"),e=n(a.prefix+\"!\"+d,this.map.parentMap),t(e,\"defined\",u(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),\nd=l(p,e.id)){this.depMaps.push(e);if(this.events.error)d.on(\"error\",u(this,function(a){this.emit(\"error\",a)}));d.enable()}}else m=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),m.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];F(p,function(a){0===a.map.id.indexOf(b+\"_unnormalized\")&&x(a.map.id)});v(a)}),m.fromText=u(this,function(e,c){var d=a.name,g=n(d),B=O;c&&(e=c);B&&(O=!1);q(g);s(k.config,b)&&(k.config[d]=k.config[b]);try{j.exec(e)}catch(ca){return v(A(\"fromtexteval\",\n\"fromText eval for \"+b+\" failed: \"+ca,ca,[b]))}B&&(O=!0);this.depMaps.push(g);i.completeLoad(d);h([d],m)}),e.load(a.name,h,m,k)}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){T[this.map.id]=this;this.enabling=this.enabled=!0;y(this.depMaps,u(this,function(a,b){var c,e;if(\"string\"===typeof a){a=n(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=l(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;t(a,\"defined\",u(this,function(a){this.defineDep(b,\na);this.check()}));this.errback&&t(a,\"error\",u(this,this.errback))}c=a.id;e=p[c];!s(N,c)&&(e&&!e.enabled)&&i.enable(a,this)}));F(this.pluginMaps,u(this,function(a){var b=l(p,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){y(this.events[a],function(a){a(b)});\"error\"===a&&delete this.events[a]}};i={config:k,contextName:b,registry:p,defined:r,urlFetched:S,defQueue:G,Module:X,makeModuleMap:n,\nnextTick:j.nextTick,onError:v,configure:function(a){a.baseUrl&&\"/\"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+=\"/\");var b=k.pkgs,c=k.shim,e={paths:!0,config:!0,map:!0};F(a,function(a,b){e[b]?\"map\"===b?(k.map||(k.map={}),Q(k[b],a,!0,!0)):Q(k[b],a,!0):k[b]=a});a.shim&&(F(a.shim,function(a,b){I(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);c[b]=a}),k.shim=c);a.packages&&(y(a.packages,function(a){a=\"string\"===typeof a?{name:a}:a;b[a.name]={name:a.name,\nlocation:a.location||a.name,main:(a.main||\"main\").replace(ja,\"\").replace(ea,\"\")}}),k.pkgs=b);F(p,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=n(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Z,arguments));return b||a.exports&&ba(a.exports)}},makeRequire:function(a,f){function d(e,c,h){var g,k;f.enableBuildCallback&&(c&&H(c))&&(c.__requireJsBuild=!0);if(\"string\"===typeof e){if(H(c))return v(A(\"requireargs\",\n\"Invalid require call\"),h);if(a&&s(N,e))return N[e](p[a.id]);if(j.get)return j.get(i,e,a,d);g=n(e,a,!1,!0);g=g.id;return!s(r,g)?v(A(\"notloaded\",'Module name \"'+g+'\" has not been loaded yet for context: '+b+(a?\"\":\". Use require([])\"))):r[g]}K();i.nextTick(function(){K();k=q(n(null,a));k.skipMap=f.skipMap;k.init(e,c,h,{enabled:!0});C()});return d}f=f||{};Q(d,{isBrowser:z,toUrl:function(b){var d,f=b.lastIndexOf(\".\"),g=b.split(\"/\")[0];if(-1!==f&&(!(\".\"===g||\"..\"===g)||1<f))d=b.substring(f,b.length),b=\nb.substring(0,f);return i.nameToUrl(c(b,a&&a.id,!0),d,!0)},defined:function(b){return s(r,n(b,a,!1,!0).id)},specified:function(b){b=n(b,a,!1,!0).id;return s(r,b)||s(p,b)}});a||(d.undef=function(b){w();var c=n(b,a,!0),f=l(p,b);delete r[b];delete S[c.url];delete Y[b];f&&(f.events.defined&&(Y[b]=f.events),x(b))});return d},enable:function(a){l(p,a.id)&&q(a).enable()},completeLoad:function(a){var b,c,e=l(k.shim,a)||{},d=e.exports;for(w();G.length;){c=G.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===\na&&(b=!0);D(c)}c=l(p,a);if(!b&&!s(r,a)&&c&&!c.inited){if(k.enforceDefine&&(!d||!ba(d)))return h(a)?void 0:v(A(\"nodefine\",\"No define call for \"+a,null,[a]));D([a,e.deps||[],e.exportsFn])}C()},nameToUrl:function(a,b,c){var e,d,h,g,i,n;if(j.jsExtRegExp.test(a))g=a+(b||\"\");else{e=k.paths;d=k.pkgs;g=a.split(\"/\");for(i=g.length;0<i;i-=1)if(n=g.slice(0,i).join(\"/\"),h=l(d,n),n=l(e,n)){I(n)&&(n=n[0]);g.splice(0,i,n);break}else if(h){a=a===h.name?h.location+\"/\"+h.main:h.location;g.splice(0,i,a);break}g=g.join(\"/\");\ng+=b||(/\\?/.test(g)||c?\"\":\".js\");g=(\"/\"===g.charAt(0)||g.match(/^[\\w\\+\\.\\-]+:/)?\"\":k.baseUrl)+g}return k.urlArgs?g+((-1===g.indexOf(\"?\")?\"?\":\"&\")+k.urlArgs):g},load:function(a,b){j.load(i,a,b)},execCb:function(a,b,c,e){return b.apply(e,c)},onScriptLoad:function(a){if(\"load\"===a.type||ka.test((a.currentTarget||a.srcElement).readyState))P=null,a=J(a),i.completeLoad(a.id)},onScriptError:function(a){var b=J(a);if(!h(b.id))return v(A(\"scripterror\",\"Script error for: \"+b.id,a,[b.id]))}};i.require=i.makeRequire();\nreturn i}var j,w,x,C,J,D,P,K,q,fa,la=/(\\/\\*([\\s\\S]*?)\\*\\/|([^:]|^)\\/\\/(.*)$)/mg,ma=/[^.]\\s*require\\s*\\(\\s*[\"']([^'\"\\s]+)[\"']\\s*\\)/g,ea=/\\.js$/,ja=/^\\.\\//;w=Object.prototype;var L=w.toString,ga=w.hasOwnProperty,ia=Array.prototype.splice,z=!!(\"undefined\"!==typeof window&&navigator&&window.document),da=!z&&\"undefined\"!==typeof importScripts,ka=z&&\"PLAYSTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/,W=\"undefined\"!==typeof opera&&\"[object Opera]\"===opera.toString(),E={},t={},R=[],O=\n!1;if(\"undefined\"===typeof define){if(\"undefined\"!==typeof requirejs){if(H(requirejs))return;t=requirejs;requirejs=void 0}\"undefined\"!==typeof require&&!H(require)&&(t=require,require=void 0);j=requirejs=function(b,c,d,h){var q,n=\"_\";!I(b)&&\"string\"!==typeof b&&(q=b,I(c)?(b=c,c=d,d=h):b=[]);q&&q.context&&(n=q.context);(h=l(E,n))||(h=E[n]=j.s.newContext(n));q&&h.configure(q);return h.require(b,c,d)};j.config=function(b){return j(b)};j.nextTick=\"undefined\"!==typeof setTimeout?function(b){setTimeout(b,\n4)}:function(b){b()};require||(require=j);j.version=\"2.1.8\";j.jsExtRegExp=/^\\/|:|\\?|\\.js$/;j.isBrowser=z;w=j.s={contexts:E,newContext:ha};j({});y([\"toUrl\",\"undef\",\"defined\",\"specified\"],function(b){j[b]=function(){var c=E._;return c.require[b].apply(c,arguments)}});if(z&&(x=w.head=document.getElementsByTagName(\"head\")[0],C=document.getElementsByTagName(\"base\")[0]))x=w.head=C.parentNode;j.onError=aa;j.createNode=function(b){var c=b.xhtml?document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"html:script\"):\ndocument.createElement(\"script\");c.type=b.scriptType||\"text/javascript\";c.charset=\"utf-8\";c.async=!0;return c};j.load=function(b,c,d){var h=b&&b.config||{};if(z)return h=j.createNode(h,c,d),h.setAttribute(\"data-requirecontext\",b.contextName),h.setAttribute(\"data-requiremodule\",c),h.attachEvent&&!(h.attachEvent.toString&&0>h.attachEvent.toString().indexOf(\"[native code\"))&&!W?(O=!0,h.attachEvent(\"onreadystatechange\",b.onScriptLoad)):(h.addEventListener(\"load\",b.onScriptLoad,!1),h.addEventListener(\"error\",\nb.onScriptError,!1)),h.src=d,K=h,C?x.insertBefore(h,C):x.appendChild(h),K=null,h;if(da)try{importScripts(d),b.completeLoad(c)}catch(l){b.onError(A(\"importscripts\",\"importScripts failed for \"+c+\" at \"+d,l,[c]))}};z&&M(document.getElementsByTagName(\"script\"),function(b){x||(x=b.parentNode);if(J=b.getAttribute(\"data-main\"))return q=J,t.baseUrl||(D=q.split(\"/\"),q=D.pop(),fa=D.length?D.join(\"/\")+\"/\":\"./\",t.baseUrl=fa),q=q.replace(ea,\"\"),j.jsExtRegExp.test(q)&&(q=J),t.deps=t.deps?t.deps.concat(q):[q],!0});\ndefine=function(b,c,d){var h,j;\"string\"!==typeof b&&(d=c,c=b,b=null);I(c)||(d=c,c=null);!c&&H(d)&&(c=[],d.length&&(d.toString().replace(la,\"\").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?[\"require\"]:[\"require\",\"exports\",\"module\"]).concat(c)));if(O){if(!(h=K))P&&\"interactive\"===P.readyState||M(document.getElementsByTagName(\"script\"),function(b){if(\"interactive\"===b.readyState)return P=b}),h=P;h&&(b||(b=h.getAttribute(\"data-requiremodule\")),j=E[h.getAttribute(\"data-requirecontext\")])}(j?j.defQueue:\nR).push([b,c,d])};define.amd={jQuery:!0};j.exec=function(b){return eval(b)};j(t)}})(this);\n"
  },
  {
    "path": "togetherjs/libs/tinycolor.js",
    "content": "// TinyColor v0.9.13\n// https://github.com/bgrins/TinyColor\n// 2012-11-28, Brian Grinstead, MIT License\n\n(function(root) {\n\nvar trimLeft = /^[\\s,#]+/,\n    trimRight = /\\s+$/,\n    tinyCounter = 0,\n    math = Math,\n    mathRound = math.round,\n    mathMin = math.min,\n    mathMax = math.max,\n    mathRandom = math.random;\n\nfunction tinycolor (color, opts) {\n\n    color = (color) ? color : '';\n\n    // If input is already a tinycolor, return itself\n    if (typeof color == \"object\" && color.hasOwnProperty(\"_tc_id\")) {\n       return color;\n    }\n\n    var rgb = inputToRGB(color);\n    var r = rgb.r,\n        g = rgb.g,\n        b = rgb.b,\n        a = rgb.a,\n        roundA = mathRound(100*a) / 100,\n        format = rgb.format;\n\n    // Don't let the range of [0,255] come back in [0,1].\n    // Potentially lose a little bit of precision here, but will fix issues where\n    // .5 gets interpreted as half of the total, instead of half of 1\n    // If it was supposed to be 128, this was already taken care of by `inputToRgb`\n    if (r < 1) { r = mathRound(r); }\n    if (g < 1) { g = mathRound(g); }\n    if (b < 1) { b = mathRound(b); }\n\n    return {\n        ok: rgb.ok,\n        format: format,\n        _tc_id: tinyCounter++,\n        alpha: a,\n        toHsv: function() {\n            var hsv = rgbToHsv(r, g, b);\n            return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a };\n        },\n        toHsvString: function() {\n            var hsv = rgbToHsv(r, g, b);\n            var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);\n            return (a == 1) ?\n              \"hsv(\"  + h + \", \" + s + \"%, \" + v + \"%)\" :\n              \"hsva(\" + h + \", \" + s + \"%, \" + v + \"%, \"+ roundA + \")\";\n        },\n        toHsl: function() {\n            var hsl = rgbToHsl(r, g, b);\n            return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a };\n        },\n        toHslString: function() {\n            var hsl = rgbToHsl(r, g, b);\n            var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);\n            return (a == 1) ?\n              \"hsl(\"  + h + \", \" + s + \"%, \" + l + \"%)\" :\n              \"hsla(\" + h + \", \" + s + \"%, \" + l + \"%, \"+ roundA + \")\";\n        },\n        toHex: function() {\n            return rgbToHex(r, g, b);\n        },\n        toHexString: function() {\n            return '#' + rgbToHex(r, g, b);\n        },\n        toRgb: function() {\n            return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a };\n        },\n        toRgbString: function() {\n            return (a == 1) ?\n              \"rgb(\"  + mathRound(r) + \", \" + mathRound(g) + \", \" + mathRound(b) + \")\" :\n              \"rgba(\" + mathRound(r) + \", \" + mathRound(g) + \", \" + mathRound(b) + \", \" + roundA + \")\";\n        },\n        toPercentageRgb: function() {\n            return { r: mathRound(bound01(r, 255) * 100) + \"%\", g: mathRound(bound01(g, 255) * 100) + \"%\", b: mathRound(bound01(b, 255) * 100) + \"%\", a: a };\n        },\n        toPercentageRgbString: function() {\n            return (a == 1) ?\n              \"rgb(\"  + mathRound(bound01(r, 255) * 100) + \"%, \" + mathRound(bound01(g, 255) * 100) + \"%, \" + mathRound(bound01(b, 255) * 100) + \"%)\" :\n              \"rgba(\" + mathRound(bound01(r, 255) * 100) + \"%, \" + mathRound(bound01(g, 255) * 100) + \"%, \" + mathRound(bound01(b, 255) * 100) + \"%, \" + roundA + \")\";\n        },\n        toName: function() {\n            return hexNames[rgbToHex(r, g, b)] || false;\n        },\n        toFilter: function() {\n            var hex = rgbToHex(r, g, b);\n            var secondHex = hex;\n            var alphaHex = Math.round(parseFloat(a) * 255).toString(16);\n            var secondAlphaHex = alphaHex;\n            var gradientType = opts && opts.gradientType ? \"GradientType = 1, \" : \"\";\n\n            if (secondColor) {\n                var s = tinycolor(secondColor);\n                secondHex = s.toHex();\n                secondAlphaHex = Math.round(parseFloat(s.alpha) * 255).toString(16);\n            }\n\n            return \"progid:DXImageTransform.Microsoft.gradient(\"+gradientType+\"startColorstr=#\" + pad2(alphaHex) + hex + \",endColorstr=#\" + pad2(secondAlphaHex) + secondHex + \")\";\n        },\n        toString: function(format) {\n            format = format || this.format;\n            var formattedString = false;\n            if (format === \"rgb\") {\n                formattedString = this.toRgbString();\n            }\n            if (format === \"prgb\") {\n                formattedString = this.toPercentageRgbString();\n            }\n            if (format === \"hex\") {\n                formattedString = this.toHexString();\n            }\n            if (format === \"name\") {\n                formattedString = this.toName();\n            }\n            if (format === \"hsl\") {\n                formattedString = this.toHslString();\n            }\n            if (format === \"hsv\") {\n                formattedString = this.toHsvString();\n            }\n\n            return formattedString || this.toHexString();\n        }\n    };\n}\n\n// If input is an object, force 1 into \"1.0\" to handle ratios properly\n// String input requires \"1.0\" as input, so 1 will be treated as 1\ntinycolor.fromRatio = function(color) {\n    if (typeof color == \"object\") {\n        var newColor = {};\n        for (var i in color) {\n            newColor[i] = convertToPercentage(color[i]);\n        }\n        color = newColor;\n    }\n\n    return tinycolor(color);\n};\n\n// Given a string or object, convert that input to RGB\n// Possible string inputs:\n//\n//     \"red\"\n//     \"#f00\" or \"f00\"\n//     \"#ff0000\" or \"ff0000\"\n//     \"rgb 255 0 0\" or \"rgb (255, 0, 0)\"\n//     \"rgb 1.0 0 0\" or \"rgb (1, 0, 0)\"\n//     \"rgba (255, 0, 0, 1)\" or \"rgba 255, 0, 0, 1\"\n//     \"rgba (1.0, 0, 0, 1)\" or \"rgba 1.0, 0, 0, 1\"\n//     \"hsl(0, 100%, 50%)\" or \"hsl 0 100% 50%\"\n//     \"hsla(0, 100%, 50%, 1)\" or \"hsla 0 100% 50%, 1\"\n//     \"hsv(0, 100%, 100%)\" or \"hsv 0 100% 100%\"\n//\nfunction inputToRGB(color) {\n\n    var rgb = { r: 255, g: 255, b: 255 };\n    var a = 1;\n    var ok = false;\n    var format = false;\n\n    if (typeof color == \"string\") {\n        color = stringInputToObject(color);\n    }\n\n    if (typeof color == \"object\") {\n        if (color.hasOwnProperty(\"r\") && color.hasOwnProperty(\"g\") && color.hasOwnProperty(\"b\")) {\n            rgb = rgbToRgb(color.r, color.g, color.b);\n            ok = true;\n            format = String(color.r).substr(-1) === \"%\" ? \"prgb\" : \"rgb\";\n        }\n        else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"v\")) {\n            color.s = convertToPercentage(color.s);\n            color.v = convertToPercentage(color.v);\n            rgb = hsvToRgb(color.h, color.s, color.v);\n            ok = true;\n            format = \"hsv\";\n        }\n        else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"l\")) {\n            color.s = convertToPercentage(color.s);\n            color.l = convertToPercentage(color.l);\n            rgb = hslToRgb(color.h, color.s, color.l);\n            ok = true;\n            format = \"hsl\";\n        }\n\n        if (color.hasOwnProperty(\"a\")) {\n            a = color.a;\n        }\n    }\n\n    a = parseFloat(a);\n\n    // Handle invalid alpha characters by setting to 1\n    if (isNaN(a) || a < 0 || a > 1) {\n        a = 1;\n    }\n\n    return {\n        ok: ok,\n        format: color.format || format,\n        r: mathMin(255, mathMax(rgb.r, 0)),\n        g: mathMin(255, mathMax(rgb.g, 0)),\n        b: mathMin(255, mathMax(rgb.b, 0)),\n        a: a\n    };\n}\n\n\n\n// Conversion Functions\n// --------------------\n\n// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\n// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>\n\n// `rgbToRgb`\n// Handle bounds / percentage checking to conform to CSS color spec\n// <http://www.w3.org/TR/css3-color/>\n// *Assumes:* r, g, b in [0, 255] or [0, 1]\n// *Returns:* { r, g, b } in [0, 255]\nfunction rgbToRgb(r, g, b){\n    return {\n        r: bound01(r, 255) * 255,\n        g: bound01(g, 255) * 255,\n        b: bound01(b, 255) * 255\n    };\n}\n\n// `rgbToHsl`\n// Converts an RGB color value to HSL.\n// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n// *Returns:* { h, s, l } in [0,1]\nfunction rgbToHsl(r, g, b) {\n\n    r = bound01(r, 255);\n    g = bound01(g, 255);\n    b = bound01(b, 255);\n\n    var max = mathMax(r, g, b), min = mathMin(r, g, b);\n    var h, s, l = (max + min) / 2;\n\n    if(max == min) {\n        h = s = 0; // achromatic\n    }\n    else {\n        var d = max - min;\n        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n        switch(max) {\n            case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n            case g: h = (b - r) / d + 2; break;\n            case b: h = (r - g) / d + 4; break;\n        }\n\n        h /= 6;\n    }\n\n    return { h: h, s: s, l: l };\n}\n\n// `hslToRgb`\n// Converts an HSL color value to RGB.\n// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n// *Returns:* { r, g, b } in the set [0, 255]\nfunction hslToRgb(h, s, l) {\n    var r, g, b;\n\n    h = bound01(h, 360);\n    s = bound01(s, 100);\n    l = bound01(l, 100);\n\n    function hue2rgb(p, q, t) {\n        if(t < 0) t += 1;\n        if(t > 1) t -= 1;\n        if(t < 1/6) return p + (q - p) * 6 * t;\n        if(t < 1/2) return q;\n        if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;\n        return p;\n    }\n\n    if(s === 0) {\n        r = g = b = l; // achromatic\n    }\n    else {\n        var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n        var p = 2 * l - q;\n        r = hue2rgb(p, q, h + 1/3);\n        g = hue2rgb(p, q, h);\n        b = hue2rgb(p, q, h - 1/3);\n    }\n\n    return { r: r * 255, g: g * 255, b: b * 255 };\n}\n\n// `rgbToHsv`\n// Converts an RGB color value to HSV\n// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]\n// *Returns:* { h, s, v } in [0,1]\nfunction rgbToHsv(r, g, b) {\n\n    r = bound01(r, 255);\n    g = bound01(g, 255);\n    b = bound01(b, 255);\n\n    var max = mathMax(r, g, b), min = mathMin(r, g, b);\n    var h, s, v = max;\n\n    var d = max - min;\n    s = max === 0 ? 0 : d / max;\n\n    if(max == min) {\n        h = 0; // achromatic\n    }\n    else {\n        switch(max) {\n            case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n            case g: h = (b - r) / d + 2; break;\n            case b: h = (r - g) / d + 4; break;\n        }\n        h /= 6;\n    }\n    return { h: h, s: s, v: v };\n}\n\n// `hsvToRgb`\n// Converts an HSV color value to RGB.\n// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]\n// *Returns:* { r, g, b } in the set [0, 255]\n function hsvToRgb(h, s, v) {\n\n    h = bound01(h, 360) * 6;\n    s = bound01(s, 100);\n    v = bound01(v, 100);\n\n    var i = math.floor(h),\n        f = h - i,\n        p = v * (1 - s),\n        q = v * (1 - f * s),\n        t = v * (1 - (1 - f) * s),\n        mod = i % 6,\n        r = [v, q, p, p, t, v][mod],\n        g = [t, v, v, q, p, p][mod],\n        b = [p, p, t, v, v, q][mod];\n\n    return { r: r * 255, g: g * 255, b: b * 255 };\n}\n\n// `rgbToHex`\n// Converts an RGB color to hex\n// Assumes r, g, and b are contained in the set [0, 255]\n// Returns a 3 or 6 character hex\nfunction rgbToHex(r, g, b) {\n    var hex = [\n        pad2(mathRound(r).toString(16)),\n        pad2(mathRound(g).toString(16)),\n        pad2(mathRound(b).toString(16))\n    ];\n\n    // Return a 3 character hex if possible\n    if (hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {\n        return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);\n    }\n\n    return hex.join(\"\");\n}\n\n// `equals`\n// Can be called with any tinycolor input\ntinycolor.equals = function (color1, color2) {\n    if (!color1 || !color2) { return false; }\n    return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();\n};\ntinycolor.random = function() {\n    return tinycolor.fromRatio({\n        r: mathRandom(),\n        g: mathRandom(),\n        b: mathRandom()\n    });\n};\n\n\n// Modification Functions\n// ----------------------\n// Thanks to less.js for some of the basics here\n// <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>\n\n\ntinycolor.desaturate = function (color, amount) {\n    var hsl = tinycolor(color).toHsl();\n    hsl.s -= ((amount || 10) / 100);\n    hsl.s = clamp01(hsl.s);\n    return tinycolor(hsl);\n};\ntinycolor.saturate = function (color, amount) {\n    var hsl = tinycolor(color).toHsl();\n    hsl.s += ((amount || 10) / 100);\n    hsl.s = clamp01(hsl.s);\n    return tinycolor(hsl);\n};\ntinycolor.greyscale = function(color) {\n    return tinycolor.desaturate(color, 100);\n};\ntinycolor.lighten = function(color, amount) {\n    var hsl = tinycolor(color).toHsl();\n    hsl.l += ((amount || 10) / 100);\n    hsl.l = clamp01(hsl.l);\n    return tinycolor(hsl);\n};\ntinycolor.darken = function (color, amount) {\n    var hsl = tinycolor(color).toHsl();\n    hsl.l -= ((amount || 10) / 100);\n    hsl.l = clamp01(hsl.l);\n    return tinycolor(hsl);\n};\ntinycolor.complement = function(color) {\n    var hsl = tinycolor(color).toHsl();\n    hsl.h = (hsl.h + 180) % 360;\n    return tinycolor(hsl);\n};\n\n\n// Combination Functions\n// ---------------------\n// Thanks to jQuery xColor for some of the ideas behind these\n// <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>\n\ntinycolor.triad = function(color) {\n    var hsl = tinycolor(color).toHsl();\n    var h = hsl.h;\n    return [\n        tinycolor(color),\n        tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),\n        tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })\n    ];\n};\ntinycolor.tetrad = function(color) {\n    var hsl = tinycolor(color).toHsl();\n    var h = hsl.h;\n    return [\n        tinycolor(color),\n        tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),\n        tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),\n        tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })\n    ];\n};\ntinycolor.splitcomplement = function(color) {\n    var hsl = tinycolor(color).toHsl();\n    var h = hsl.h;\n    return [\n        tinycolor(color),\n        tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),\n        tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})\n    ];\n};\ntinycolor.analogous = function(color, results, slices) {\n    results = results || 6;\n    slices = slices || 30;\n\n    var hsl = tinycolor(color).toHsl();\n    var part = 360 / slices;\n    var ret = [tinycolor(color)];\n\n    for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {\n        hsl.h = (hsl.h + part) % 360;\n        ret.push(tinycolor(hsl));\n    }\n    return ret;\n};\ntinycolor.monochromatic = function(color, results) {\n    results = results || 6;\n    var hsv = tinycolor(color).toHsv();\n    var h = hsv.h, s = hsv.s, v = hsv.v;\n    var ret = [];\n    var modification = 1 / results;\n\n    while (results--) {\n        ret.push(tinycolor({ h: h, s: s, v: v}));\n        v = (v + modification) % 1;\n    }\n\n    return ret;\n};\n// Readability based on W3C recommendations: http://www.w3.org/TR/AERT#color-contrast\n// Returns object with two properties:\n//   .brightness: the difference in brightness between the two colors\n//   .color: the difference in color/hue between the two colors\n// An \"acceptable\" color is considered to have a brightness difference of 125 and a\n// color difference of 500\ntinycolor.readability = function(color1, color2) {\n    var a = tinycolor(color1).toRgb(), b = tinycolor(color2).toRgb();\n    var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000;\n    var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000;\n    var colorDiff = (\n        Math.max(a.r, b.r) - Math.min(a.r, b.r) +\n        Math.max(a.g, b.g) - Math.min(a.g, b.g) +\n        Math.max(a.b, b.b) - Math.min(a.b, b.b));\n    return {\n        brightness: Math.abs(brightnessA - brightnessB),\n        color: colorDiff\n    };\n};\n// True if using color1 over color2 (or vice versa) is \"readable\"\n// Based on: http://www.w3.org/TR/AERT#color-contrast\n// Example:\n//   tinycolor.readable(\"#000\", \"#111\") => false\ntinycolor.readable = function(color1, color2) {\n    var readability = tinycolor.readability(color1, color2);\n    return readability.brightness > 125 && readability.color > 500;\n};\n// Given a base color and a list of possible foreground or background\n// colors for that base, returns the most readable color.\n// Example:\n//   tinycolor.mostReadable(\"#123\", [\"#fff\", \"#000\"]) => \"#000\"\ntinycolor.mostReadable = function(baseColor, colorList) {\n    var bestColor;\n    var bestScore = 0;\n    var bestIsReadable = false;\n    for (var i=0; i < colorList.length; i++) {\n        var readability = tinycolor.readability(baseColor, colorList[i]);\n        var readable = readability.brightness > 125 && readability.color > 500;\n        // We normalize both around the \"acceptable\" breaking point,\n        // but rank brightness constrast higher than hue.  Why?  I'm\n        // not sure, seems reasonable.\n        var score = 3 * (readability.brightness / 125) + (readability.color / 500);\n        if ((readable && ! bestIsReadable) ||\n            (readable && bestIsReadable && score > bestScore) ||\n            ((! readable) && (! bestIsReadable) && score > bestScore)) {\n            bestIsReadable = readable;\n            bestScore = score;\n            bestColor = colorList[i];\n        }\n    }\n    return bestColor;\n};\n\n\n// Big List of Colors\n// ---------\n// <http://www.w3.org/TR/css3-color/#svg-color>\nvar names = tinycolor.names = {\n    aliceblue: \"f0f8ff\",\n    antiquewhite: \"faebd7\",\n    aqua: \"0ff\",\n    aquamarine: \"7fffd4\",\n    azure: \"f0ffff\",\n    beige: \"f5f5dc\",\n    bisque: \"ffe4c4\",\n    black: \"000\",\n    blanchedalmond: \"ffebcd\",\n    blue: \"00f\",\n    blueviolet: \"8a2be2\",\n    brown: \"a52a2a\",\n    burlywood: \"deb887\",\n    burntsienna: \"ea7e5d\",\n    cadetblue: \"5f9ea0\",\n    chartreuse: \"7fff00\",\n    chocolate: \"d2691e\",\n    coral: \"ff7f50\",\n    cornflowerblue: \"6495ed\",\n    cornsilk: \"fff8dc\",\n    crimson: \"dc143c\",\n    cyan: \"0ff\",\n    darkblue: \"00008b\",\n    darkcyan: \"008b8b\",\n    darkgoldenrod: \"b8860b\",\n    darkgray: \"a9a9a9\",\n    darkgreen: \"006400\",\n    darkgrey: \"a9a9a9\",\n    darkkhaki: \"bdb76b\",\n    darkmagenta: \"8b008b\",\n    darkolivegreen: \"556b2f\",\n    darkorange: \"ff8c00\",\n    darkorchid: \"9932cc\",\n    darkred: \"8b0000\",\n    darksalmon: \"e9967a\",\n    darkseagreen: \"8fbc8f\",\n    darkslateblue: \"483d8b\",\n    darkslategray: \"2f4f4f\",\n    darkslategrey: \"2f4f4f\",\n    darkturquoise: \"00ced1\",\n    darkviolet: \"9400d3\",\n    deeppink: \"ff1493\",\n    deepskyblue: \"00bfff\",\n    dimgray: \"696969\",\n    dimgrey: \"696969\",\n    dodgerblue: \"1e90ff\",\n    firebrick: \"b22222\",\n    floralwhite: \"fffaf0\",\n    forestgreen: \"228b22\",\n    fuchsia: \"f0f\",\n    gainsboro: \"dcdcdc\",\n    ghostwhite: \"f8f8ff\",\n    gold: \"ffd700\",\n    goldenrod: \"daa520\",\n    gray: \"808080\",\n    green: \"008000\",\n    greenyellow: \"adff2f\",\n    grey: \"808080\",\n    honeydew: \"f0fff0\",\n    hotpink: \"ff69b4\",\n    indianred: \"cd5c5c\",\n    indigo: \"4b0082\",\n    ivory: \"fffff0\",\n    khaki: \"f0e68c\",\n    lavender: \"e6e6fa\",\n    lavenderblush: \"fff0f5\",\n    lawngreen: \"7cfc00\",\n    lemonchiffon: \"fffacd\",\n    lightblue: \"add8e6\",\n    lightcoral: \"f08080\",\n    lightcyan: \"e0ffff\",\n    lightgoldenrodyellow: \"fafad2\",\n    lightgray: \"d3d3d3\",\n    lightgreen: \"90ee90\",\n    lightgrey: \"d3d3d3\",\n    lightpink: \"ffb6c1\",\n    lightsalmon: \"ffa07a\",\n    lightseagreen: \"20b2aa\",\n    lightskyblue: \"87cefa\",\n    lightslategray: \"789\",\n    lightslategrey: \"789\",\n    lightsteelblue: \"b0c4de\",\n    lightyellow: \"ffffe0\",\n    lime: \"0f0\",\n    limegreen: \"32cd32\",\n    linen: \"faf0e6\",\n    magenta: \"f0f\",\n    maroon: \"800000\",\n    mediumaquamarine: \"66cdaa\",\n    mediumblue: \"0000cd\",\n    mediumorchid: \"ba55d3\",\n    mediumpurple: \"9370db\",\n    mediumseagreen: \"3cb371\",\n    mediumslateblue: \"7b68ee\",\n    mediumspringgreen: \"00fa9a\",\n    mediumturquoise: \"48d1cc\",\n    mediumvioletred: \"c71585\",\n    midnightblue: \"191970\",\n    mintcream: \"f5fffa\",\n    mistyrose: \"ffe4e1\",\n    moccasin: \"ffe4b5\",\n    navajowhite: \"ffdead\",\n    navy: \"000080\",\n    oldlace: \"fdf5e6\",\n    olive: \"808000\",\n    olivedrab: \"6b8e23\",\n    orange: \"ffa500\",\n    orangered: \"ff4500\",\n    orchid: \"da70d6\",\n    palegoldenrod: \"eee8aa\",\n    palegreen: \"98fb98\",\n    paleturquoise: \"afeeee\",\n    palevioletred: \"db7093\",\n    papayawhip: \"ffefd5\",\n    peachpuff: \"ffdab9\",\n    peru: \"cd853f\",\n    pink: \"ffc0cb\",\n    plum: \"dda0dd\",\n    powderblue: \"b0e0e6\",\n    purple: \"800080\",\n    red: \"f00\",\n    rosybrown: \"bc8f8f\",\n    royalblue: \"4169e1\",\n    saddlebrown: \"8b4513\",\n    salmon: \"fa8072\",\n    sandybrown: \"f4a460\",\n    seagreen: \"2e8b57\",\n    seashell: \"fff5ee\",\n    sienna: \"a0522d\",\n    silver: \"c0c0c0\",\n    skyblue: \"87ceeb\",\n    slateblue: \"6a5acd\",\n    slategray: \"708090\",\n    slategrey: \"708090\",\n    snow: \"fffafa\",\n    springgreen: \"00ff7f\",\n    steelblue: \"4682b4\",\n    tan: \"d2b48c\",\n    teal: \"008080\",\n    thistle: \"d8bfd8\",\n    tomato: \"ff6347\",\n    turquoise: \"40e0d0\",\n    violet: \"ee82ee\",\n    wheat: \"f5deb3\",\n    white: \"fff\",\n    whitesmoke: \"f5f5f5\",\n    yellow: \"ff0\",\n    yellowgreen: \"9acd32\"\n};\n\n// Make it easy to access colors via `hexNames[hex]`\nvar hexNames = tinycolor.hexNames = flip(names);\n\n\n// Utilities\n// ---------\n\n// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`\nfunction flip(o) {\n    var flipped = { };\n    for (var i in o) {\n        if (o.hasOwnProperty(i)) {\n            flipped[o[i]] = i;\n        }\n    }\n    return flipped;\n}\n\n// Take input from [0, n] and return it as [0, 1]\nfunction bound01(n, max) {\n    if (isOnePointZero(n)) { n = \"100%\"; }\n\n    var processPercent = isPercentage(n);\n    n = mathMin(max, mathMax(0, parseFloat(n)));\n\n    // Automatically convert percentage into number\n    if (processPercent) {\n        n = parseInt(n * max, 10) / 100;\n    }\n\n    // Handle floating point rounding errors\n    if ((math.abs(n - max) < 0.000001)) {\n        return 1;\n    }\n\n    // Convert into [0, 1] range if it isn't already\n    return (n % max) / parseFloat(max);\n}\n\n// Force a number between 0 and 1\nfunction clamp01(val) {\n    return mathMin(1, mathMax(0, val));\n}\n\n// Parse an integer into hex\nfunction parseHex(val) {\n    return parseInt(val, 16);\n}\n\n// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\n// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>\nfunction isOnePointZero(n) {\n    return typeof n == \"string\" && n.indexOf('.') != -1 && parseFloat(n) === 1;\n}\n\n// Check to see if string passed in is a percentage\nfunction isPercentage(n) {\n    return typeof n === \"string\" && n.indexOf('%') != -1;\n}\n\n// Force a hex value to have 2 characters\nfunction pad2(c) {\n    return c.length == 1 ? '0' + c : '' + c;\n}\n\n// Replace a decimal with it's percentage value\nfunction convertToPercentage(n) {\n    if (n <= 1) {\n        n = (n * 100) + \"%\";\n    }\n\n    return n;\n}\n\nvar matchers = (function() {\n\n    // <http://www.w3.org/TR/css3-values/#integers>\n    var CSS_INTEGER = \"[-\\\\+]?\\\\d+%?\";\n\n    // <http://www.w3.org/TR/css3-values/#number-value>\n    var CSS_NUMBER = \"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\";\n\n    // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.\n    var CSS_UNIT = \"(?:\" + CSS_NUMBER + \")|(?:\" + CSS_INTEGER + \")\";\n\n    // Actual matching.\n    // Parentheses and commas are optional, but not required.\n    // Whitespace can take the place of commas or opening paren\n    var PERMISSIVE_MATCH3 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n    var PERMISSIVE_MATCH4 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n\n    return {\n        rgb: new RegExp(\"rgb\" + PERMISSIVE_MATCH3),\n        rgba: new RegExp(\"rgba\" + PERMISSIVE_MATCH4),\n        hsl: new RegExp(\"hsl\" + PERMISSIVE_MATCH3),\n        hsla: new RegExp(\"hsla\" + PERMISSIVE_MATCH4),\n        hsv: new RegExp(\"hsv\" + PERMISSIVE_MATCH3),\n        hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n        hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n    };\n})();\n\n// `stringInputToObject`\n// Permissive string parsing.  Take in a number of formats, and output an object\n// based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`\nfunction stringInputToObject(color) {\n\n    color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();\n    var named = false;\n    if (names[color]) {\n        color = names[color];\n        named = true;\n    }\n    else if (color == 'transparent') {\n        return { r: 0, g: 0, b: 0, a: 0 };\n    }\n\n    // Try to match string input using regular expressions.\n    // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]\n    // Just return an object and let the conversion functions handle that.\n    // This way the result will be the same whether the tinycolor is initialized with string or object.\n    var match;\n    if ((match = matchers.rgb.exec(color))) {\n        return { r: match[1], g: match[2], b: match[3] };\n    }\n    if ((match = matchers.rgba.exec(color))) {\n        return { r: match[1], g: match[2], b: match[3], a: match[4] };\n    }\n    if ((match = matchers.hsl.exec(color))) {\n        return { h: match[1], s: match[2], l: match[3] };\n    }\n    if ((match = matchers.hsla.exec(color))) {\n        return { h: match[1], s: match[2], l: match[3], a: match[4] };\n    }\n    if ((match = matchers.hsv.exec(color))) {\n        return { h: match[1], s: match[2], v: match[3] };\n    }\n    if ((match = matchers.hex6.exec(color))) {\n        return {\n            r: parseHex(match[1]),\n            g: parseHex(match[2]),\n            b: parseHex(match[3]),\n            format: named ? \"name\" : \"hex\"\n        };\n    }\n    if ((match = matchers.hex3.exec(color))) {\n        return {\n            r: parseHex(match[1] + '' + match[1]),\n            g: parseHex(match[2] + '' + match[2]),\n            b: parseHex(match[3] + '' + match[3]),\n            format: named ? \"name\" : \"hex\"\n        };\n    }\n\n    return false;\n}\n\n// Node: Export function\nif (typeof module !== \"undefined\" && module.exports) {\n    module.exports = tinycolor;\n}\n// AMD/requirejs: Define the module\nelse if (typeof define !== \"undefined\") {\n    define(function () {return tinycolor;});\n}\n// Browser: Expose to window\nelse {\n    root.tinycolor = tinycolor;\n}\n\n})(this);\n"
  },
  {
    "path": "togetherjs/libs/walkabout/README.md",
    "content": "walkabout.js\n============\n\nAn automatic jQuery app tester.\n\nThis code figures out what your application is paying attention to,\nand does it.  It fills in fields with random values.  It finds the\nevents you listen for and fires those events.  It finds internal links\n(like `<a href=\"#foo\">`) and clicks them.  It's a little like a fuzz\ntester for your app.\n\nYou can use it like so:\n\n```javascript\n// This makes something like $('#some-input').val() return random values:\njQuery.fn.val.patch();\n\n// Now, fiddle around, do 100 random things:\nWalkabout.runManyActions({\n  times: 100\n});\n```\n\nYou can hint about what's a valid input for something:\n\nYou can add `data-walkabout-disable=\"1\"` to any element to suppress\nactivation of that element or any of its children.\n\nYou can use `data-walkabout-eventname=\"...\"` to set attributes on the\nevent that is created, such as `data-walkabout-keyup=\"{which: 13}\"`\n\nYou can use `data-walkabout-options=\"['a', 'b']\"` to give the valid inputs\nfor a field.\n\nYou can use `data-walkabout-edit-value=\"type paste delete move\"` to\nhave Walkabout do edit operations inside a `textarea` or `input\ntype=text`.  You give a space-separated list of the things to do: type\na key at the cursor (and fire keyup), paste at the cursor (and fire\npaste), delete the selection or delete before or after the cursor, or\nmove the cursor around.\n\n\nBookmarklet\n-----------\n\nIf you want to try walkabout.js on some random jQuery site, you can\nuse the [bookmarklet](http://ianb.github.com/walkabout.js).  This will\nload Walkabout and also start a simple UI to start the runs.  In\naddition to starting a run it'll also track any uncaught errors and\nany calls to `console.warn()` or `console.error()`.\n\n\nNon-jQuery Support\n------------------\n\nThere's some experimental support for working with code that doesn't\nuse jQuery.  It *might* work with other frameworks, but is more\nintended to work with code that doesn't use a framework.\n\nThis technique uses code rewriting to capture calls to\n`.addEventListener()` and `.value`.  The code can't use any tricks, it\nneeds to actually use those literal names -- which is usually fine in\n\"normal\" code, but might not be in fancy or optimized code.  E.g.,\n`el[\"addEventListener\"](...)` would not be found.\n\nYou can use `Walkabout.rewriteListeners(code)` to rewrite the code.\n\nThe code transformation looks like this:\n\n```javascript\ndocument.getElementById(\"el\").addEventListener(\"click\", function () {}, true);\nvar value = document.getElementById(\"textarea\").value;\n\n// Becomes:\nWalkabout.addEventListener(document.getElementById(\"el\"), \"click\", function () {}, true);\nvar value = Walkabout.value(document.getElementById(\"textarea\"));\n```\n\nAnd to find actions you use `Walkabout.findActions(element)`.\n\n\nOptions\n-------\n\nBy default Walkabout will only go to links on the current page (i.e.,\n`href=\"#something\"`).  This is because it will lose its context and\npotentially not load on the next page.  But if you want Walkabout to\nmove to other pages you can use `Walkabout.options.anyLocalLinks =\ntrue`\n\nOr set it to something like `\"/dir/\"` which will only follow links\nunder `/dir/`.\n\nIf you use `Walkabout.options.loadPersistent = true` then it will save\nthe state in localStorage and continue where it left of when another\npage is loaded.\n\n\nProxy Server\n------------\n\nAn application could include `walkabout.js` on its own, and if it\ndoesn't use jQuery it could also run `Walkabout.rewriteListeners()` on\nall its code.  But maybe you don't feel like doing that, maybe you\nwant to try it out without all that work.  Also, by default Walkabout\nwill try to stay on the current page, but in the proxy mode because it\nknows Walkabout will load on each page, it will freely move about the\nsite.\n\nThere is a proxy server `node-proxy.js` that makes this easier.  As\nyou might guess, you have to install Node.js to use it.\n\nThe server expects to receive requests for the website you want to\nactually access.  To do this you have to edit `/etc/hosts` to point\nthe request locally, e.g.:\n\n```\n127.0.0.1 site-to-test.com\n```\n\nThen when you access `http://site-to-test.com` it will connect\nlocally, and the proxy server in turn will forward the request to the\nactual server.  Any HTML responses will have the Walkabout Javascript\nadded, and Javascript will be rewritten.\n\nNote that it binds to port 80, and so you must run it as root.  This\nisn't awesome, pull requests to drop root welcome.  A tool like\n[authbind](http://en.wikipedia.org/wiki/Authbind) also could help.\n\nWhen you are done you should definitely stop the server, and undo the\n`/etc/hosts` entry.\n\nNote many live sites seem to notice the proxy, though I don't know\nhow.  I seem to be blocked from news.ycombinator.com now after using\nit in my own testing.  Any ideas welcome.\n\nYou can control the proxy with environmental variables: `$PORT` for\nthe port to bind to (default 80), `$BIND` for the interface to bind to\n(default 127.0.0.1; 0.0.0.0 means all interfaces), and `$PORT_ALIASES`\nwhich looks like `domain1:8088;domain2:8080` which lets you proxy from\none port to another (helpful sometimes when you need to proxy to a\nserver running locally).\n\n\nTo Do\n-----\n\nLots of stuff, of course.  But:\n\n- Sometimes the validation options (like `data-walkabout-options`)\n  should be obeyed, and sometimes they should be ignored.  Obeying\n  them progresses you through the site, disobeying them does some fuzz\n  testing.\n\n- Not all form controls get triggered, I think.  E.g., checkboxes\n  don't get checked.\n\n- `.val()` should figure out better what's a reasonable return value.\n  E.g., a textarea returns multi-line strings, a checkbox returns\n  true/false.\n\n- The generator could have smarts about what scripts are successful\n  and which are not.  Starting with a successful script (that\n  progresses you through the application), and then tweaking that\n  script and increasing randomness at the end of the script.\n\n- We could look at code coverage as a score.  Or we could even just\n  look at event coverage - hidden elements often have events bound,\n  but we know they have to be visible to be triggered.\n\n- Something more Gaussian with the values generated.  Like, sometimes\n  you should make a 100 character input.  But maybe not as often as a\n  10 character input.  And sometimes a 1 character input.\n\n- z-index effects whether some actions can happen - e.g., an element\n  might be visible but not clickable because of overlays.  We should\n  test for that.\n"
  },
  {
    "path": "togetherjs/libs/walkabout/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>walkabout.js: automated randomized Javascript frontend testing</title>\n    <script src=\"walkabout.js\"></script>\n    <script>\n\nwindow.addEventListener(\"load\", function () {\n  document.getElementById(\"bookmarklet\").href = Walkabout.makeBookmarklet();\n}, false);\n\n    </script>\n    <style>\n\nbody {\n  font-family: sans-serif;\n}\n\n#page {\n  max-width: 40em;\n  position: absolute;\n  left: 50%;\n  margin-left: -20em;\n}\n\n    </style>\n  </head>\n  <body>\n\n    <div id=\"page\">\n\n    <h1>Walkabout.js</h1>\n\n    <p>walkabout.js is a library to do automated randomized Javascript\n    testing (you might consider it \"fuzz\" testing).  It figures out\n    what the application is listening for the user to do, and does\n    things randomly.</p>\n\n    <p>For more information\n    see <a href=\"http://github.com/ianb/walkabout.js\">the github\n    page</a>. </p>\n\n    <p>There is a bookmarklet for use with jQuery apps:</p>\n\n    <p style=\"text-align: center\">\n      <a id=\"bookmarklet\" style=\"font-size: 200%; border: 2px solid #000; border-radius: 3px; padding: 0.3em;\" href=\"\">walkabout</a>\n    </p>\n\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/libs/walkabout/lib/esprima.js",
    "content": "/*\n  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>\n  Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>\n  Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>\n  Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>\n  Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>\n  Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>\n  Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n/*jslint bitwise:true plusplus:true */\n/*global esprima:true, define:true, exports:true, window: true,\nthrowError: true, createLiteral: true, generateStatement: true,\nparseAssignmentExpression: true, parseBlock: true, parseExpression: true,\nparseFunctionDeclaration: true, parseFunctionExpression: true,\nparseFunctionSourceElements: true, parseVariableIdentifier: true,\nparseLeftHandSideExpression: true,\nparseStatement: true, parseSourceElement: true */\n\n(function (factory) {\n    'use strict';\n\n    // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,\n    // and plain browser loading,\n    if (typeof define === 'function' && define.amd) {\n        define(['exports'], factory);\n    } else if (typeof exports !== 'undefined') {\n        factory(exports);\n    } else {\n        factory((window.esprima = {}));\n    }\n}(function (exports) {\n    'use strict';\n\n    var Token,\n        TokenName,\n        Syntax,\n        PropertyKind,\n        Messages,\n        Regex,\n        source,\n        strict,\n        index,\n        lineNumber,\n        lineStart,\n        length,\n        buffer,\n        state,\n        extra;\n\n    Token = {\n        BooleanLiteral: 1,\n        EOF: 2,\n        Identifier: 3,\n        Keyword: 4,\n        NullLiteral: 5,\n        NumericLiteral: 6,\n        Punctuator: 7,\n        StringLiteral: 8\n    };\n\n    TokenName = {};\n    TokenName[Token.BooleanLiteral] = 'Boolean';\n    TokenName[Token.EOF] = '<end>';\n    TokenName[Token.Identifier] = 'Identifier';\n    TokenName[Token.Keyword] = 'Keyword';\n    TokenName[Token.NullLiteral] = 'Null';\n    TokenName[Token.NumericLiteral] = 'Numeric';\n    TokenName[Token.Punctuator] = 'Punctuator';\n    TokenName[Token.StringLiteral] = 'String';\n\n    Syntax = {\n        AssignmentExpression: 'AssignmentExpression',\n        ArrayExpression: 'ArrayExpression',\n        BlockStatement: 'BlockStatement',\n        BinaryExpression: 'BinaryExpression',\n        BreakStatement: 'BreakStatement',\n        CallExpression: 'CallExpression',\n        CatchClause: 'CatchClause',\n        ConditionalExpression: 'ConditionalExpression',\n        ContinueStatement: 'ContinueStatement',\n        DoWhileStatement: 'DoWhileStatement',\n        DebuggerStatement: 'DebuggerStatement',\n        EmptyStatement: 'EmptyStatement',\n        ExpressionStatement: 'ExpressionStatement',\n        ForStatement: 'ForStatement',\n        ForInStatement: 'ForInStatement',\n        FunctionDeclaration: 'FunctionDeclaration',\n        FunctionExpression: 'FunctionExpression',\n        Identifier: 'Identifier',\n        IfStatement: 'IfStatement',\n        Literal: 'Literal',\n        LabeledStatement: 'LabeledStatement',\n        LogicalExpression: 'LogicalExpression',\n        MemberExpression: 'MemberExpression',\n        NewExpression: 'NewExpression',\n        ObjectExpression: 'ObjectExpression',\n        Program: 'Program',\n        Property: 'Property',\n        ReturnStatement: 'ReturnStatement',\n        SequenceExpression: 'SequenceExpression',\n        SwitchStatement: 'SwitchStatement',\n        SwitchCase: 'SwitchCase',\n        ThisExpression: 'ThisExpression',\n        ThrowStatement: 'ThrowStatement',\n        TryStatement: 'TryStatement',\n        UnaryExpression: 'UnaryExpression',\n        UpdateExpression: 'UpdateExpression',\n        VariableDeclaration: 'VariableDeclaration',\n        VariableDeclarator: 'VariableDeclarator',\n        WhileStatement: 'WhileStatement',\n        WithStatement: 'WithStatement'\n    };\n\n    PropertyKind = {\n        Data: 1,\n        Get: 2,\n        Set: 4\n    };\n\n    // Error messages should be identical to V8.\n    Messages = {\n        UnexpectedToken:  'Unexpected token %0',\n        UnexpectedNumber:  'Unexpected number',\n        UnexpectedString:  'Unexpected string',\n        UnexpectedIdentifier:  'Unexpected identifier',\n        UnexpectedReserved:  'Unexpected reserved word',\n        UnexpectedEOS:  'Unexpected end of input',\n        NewlineAfterThrow:  'Illegal newline after throw',\n        InvalidRegExp: 'Invalid regular expression',\n        UnterminatedRegExp:  'Invalid regular expression: missing /',\n        InvalidLHSInAssignment:  'Invalid left-hand side in assignment',\n        InvalidLHSInForIn:  'Invalid left-hand side in for-in',\n        MultipleDefaultsInSwitch: 'More than one default clause in switch statement',\n        NoCatchOrFinally:  'Missing catch or finally after try',\n        UnknownLabel: 'Undefined label \\'%0\\'',\n        Redeclaration: '%0 \\'%1\\' has already been declared',\n        IllegalContinue: 'Illegal continue statement',\n        IllegalBreak: 'Illegal break statement',\n        IllegalReturn: 'Illegal return statement',\n        StrictModeWith:  'Strict mode code may not include a with statement',\n        StrictCatchVariable:  'Catch variable may not be eval or arguments in strict mode',\n        StrictVarName:  'Variable name may not be eval or arguments in strict mode',\n        StrictParamName:  'Parameter name eval or arguments is not allowed in strict mode',\n        StrictParamDupe: 'Strict mode function may not have duplicate parameter names',\n        StrictFunctionName:  'Function name may not be eval or arguments in strict mode',\n        StrictOctalLiteral:  'Octal literals are not allowed in strict mode.',\n        StrictDelete:  'Delete of an unqualified identifier in strict mode.',\n        StrictDuplicateProperty:  'Duplicate data property in object literal not allowed in strict mode',\n        AccessorDataProperty:  'Object literal may not have data and accessor property with the same name',\n        AccessorGetSet:  'Object literal may not have multiple get/set accessors with the same name',\n        StrictLHSAssignment:  'Assignment to eval or arguments is not allowed in strict mode',\n        StrictLHSPostfix:  'Postfix increment/decrement may not have eval or arguments operand in strict mode',\n        StrictLHSPrefix:  'Prefix increment/decrement may not have eval or arguments operand in strict mode',\n        StrictReservedWord:  'Use of future reserved word in strict mode'\n    };\n\n    // See also tools/generate-unicode-regex.py.\n    Regex = {\n        NonAsciiIdentifierStart: new RegExp('[\\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        NonAsciiIdentifierPart: new RegExp('[\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0300-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u0483-\\u0487\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0610-\\u061a\\u0620-\\u0669\\u066e-\\u06d3\\u06d5-\\u06dc\\u06df-\\u06e8\\u06ea-\\u06fc\\u06ff\\u0710-\\u074a\\u074d-\\u07b1\\u07c0-\\u07f5\\u07fa\\u0800-\\u082d\\u0840-\\u085b\\u08a0\\u08a2-\\u08ac\\u08e4-\\u08fe\\u0900-\\u0963\\u0966-\\u096f\\u0971-\\u0977\\u0979-\\u097f\\u0981-\\u0983\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bc-\\u09c4\\u09c7\\u09c8\\u09cb-\\u09ce\\u09d7\\u09dc\\u09dd\\u09df-\\u09e3\\u09e6-\\u09f1\\u0a01-\\u0a03\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a59-\\u0a5c\\u0a5e\\u0a66-\\u0a75\\u0a81-\\u0a83\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abc-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ad0\\u0ae0-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3c-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5c\\u0b5d\\u0b5f-\\u0b63\\u0b66-\\u0b6f\\u0b71\\u0b82\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd0\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d-\\u0c44\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c58\\u0c59\\u0c60-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbc-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0cde\\u0ce0-\\u0ce3\\u0ce6-\\u0cef\\u0cf1\\u0cf2\\u0d02\\u0d03\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d-\\u0d44\\u0d46-\\u0d48\\u0d4a-\\u0d4e\\u0d57\\u0d60-\\u0d63\\u0d66-\\u0d6f\\u0d7a-\\u0d7f\\u0d82\\u0d83\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e01-\\u0e3a\\u0e40-\\u0e4e\\u0e50-\\u0e59\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb9\\u0ebb-\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0edc-\\u0edf\\u0f00\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f3e-\\u0f47\\u0f49-\\u0f6c\\u0f71-\\u0f84\\u0f86-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1049\\u1050-\\u109d\\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\\u135d-\\u135f\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176c\\u176e-\\u1770\\u1772\\u1773\\u1780-\\u17d3\\u17d7\\u17dc\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1920-\\u192b\\u1930-\\u193b\\u1946-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19b0-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a1b\\u1a20-\\u1a5e\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1aa7\\u1b00-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1b80-\\u1bf3\\u1c00-\\u1c37\\u1c40-\\u1c49\\u1c4d-\\u1c7d\\u1cd0-\\u1cd2\\u1cd4-\\u1cf6\\u1d00-\\u1de6\\u1dfc-\\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\\u200c\\u200d\\u203f\\u2040\\u2054\\u2071\\u207f\\u2090-\\u209c\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\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-\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d7f-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2de0-\\u2dff\\u2e2f\\u3005-\\u3007\\u3021-\\u302f\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u3099\\u309a\\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-\\ua62b\\ua640-\\ua66f\\ua674-\\ua67d\\ua67f-\\ua697\\ua69f-\\ua6f1\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua827\\ua840-\\ua873\\ua880-\\ua8c4\\ua8d0-\\ua8d9\\ua8e0-\\ua8f7\\ua8fb\\ua900-\\ua92d\\ua930-\\ua953\\ua960-\\ua97c\\ua980-\\ua9c0\\ua9cf-\\ua9d9\\uaa00-\\uaa36\\uaa40-\\uaa4d\\uaa50-\\uaa59\\uaa60-\\uaa76\\uaa7a\\uaa7b\\uaa80-\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaef\\uaaf2-\\uaaf6\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabea\\uabec\\uabed\\uabf0-\\uabf9\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff10-\\uff19\\uff21-\\uff3a\\uff3f\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc]')\n    };\n\n    // Ensure the condition is true, otherwise throw an error.\n    // This is only to have a better contract semantic, i.e. another safety net\n    // to catch a logic error. The condition shall be fulfilled in normal case.\n    // Do NOT use this to enforce a certain condition on any user input.\n\n    function assert(condition, message) {\n        if (!condition) {\n            throw new Error('ASSERT: ' + message);\n        }\n    }\n\n    function sliceSource(from, to) {\n        return source.slice(from, to);\n    }\n\n    if (typeof 'esprima'[0] === 'undefined') {\n        sliceSource = function sliceArraySource(from, to) {\n            return source.slice(from, to).join('');\n        };\n    }\n\n    function isDecimalDigit(ch) {\n        return '0123456789'.indexOf(ch) >= 0;\n    }\n\n    function isHexDigit(ch) {\n        return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;\n    }\n\n    function isOctalDigit(ch) {\n        return '01234567'.indexOf(ch) >= 0;\n    }\n\n\n    // 7.2 White Space\n\n    function isWhiteSpace(ch) {\n        return (ch === ' ') || (ch === '\\u0009') || (ch === '\\u000B') ||\n            (ch === '\\u000C') || (ch === '\\u00A0') ||\n            (ch.charCodeAt(0) >= 0x1680 &&\n             '\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\uFEFF'.indexOf(ch) >= 0);\n    }\n\n    // 7.3 Line Terminators\n\n    function isLineTerminator(ch) {\n        return (ch === '\\n' || ch === '\\r' || ch === '\\u2028' || ch === '\\u2029');\n    }\n\n    // 7.6 Identifier Names and Identifiers\n\n    function isIdentifierStart(ch) {\n        return (ch === '$') || (ch === '_') || (ch === '\\\\') ||\n            (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||\n            ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));\n    }\n\n    function isIdentifierPart(ch) {\n        return (ch === '$') || (ch === '_') || (ch === '\\\\') ||\n            (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||\n            ((ch >= '0') && (ch <= '9')) ||\n            ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));\n    }\n\n    // 7.6.1.2 Future Reserved Words\n\n    function isFutureReservedWord(id) {\n        switch (id) {\n\n        // Future reserved words.\n        case 'class':\n        case 'enum':\n        case 'export':\n        case 'extends':\n        case 'import':\n        case 'super':\n            return true;\n        }\n\n        return false;\n    }\n\n    function isStrictModeReservedWord(id) {\n        switch (id) {\n\n        // Strict Mode reserved words.\n        case 'implements':\n        case 'interface':\n        case 'package':\n        case 'private':\n        case 'protected':\n        case 'public':\n        case 'static':\n        case 'yield':\n        case 'let':\n            return true;\n        }\n\n        return false;\n    }\n\n    function isRestrictedWord(id) {\n        return id === 'eval' || id === 'arguments';\n    }\n\n    // 7.6.1.1 Keywords\n\n    function isKeyword(id) {\n        var keyword = false;\n        switch (id.length) {\n        case 2:\n            keyword = (id === 'if') || (id === 'in') || (id === 'do');\n            break;\n        case 3:\n            keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');\n            break;\n        case 4:\n            keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with');\n            break;\n        case 5:\n            keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw');\n            break;\n        case 6:\n            keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch');\n            break;\n        case 7:\n            keyword = (id === 'default') || (id === 'finally');\n            break;\n        case 8:\n            keyword = (id === 'function') || (id === 'continue') || (id === 'debugger');\n            break;\n        case 10:\n            keyword = (id === 'instanceof');\n            break;\n        }\n\n        if (keyword) {\n            return true;\n        }\n\n        switch (id) {\n        // Future reserved words.\n        // 'const' is specialized as Keyword in V8.\n        case 'const':\n            return true;\n\n        // For compatiblity to SpiderMonkey and ES.next\n        case 'yield':\n        case 'let':\n            return true;\n        }\n\n        if (strict && isStrictModeReservedWord(id)) {\n            return true;\n        }\n\n        return isFutureReservedWord(id);\n    }\n\n    // Return the next character and move forward.\n\n    function nextChar() {\n        return source[index++];\n    }\n\n    // 7.4 Comments\n\n    function skipComment() {\n        var ch, blockComment, lineComment;\n\n        blockComment = false;\n        lineComment = false;\n\n        while (index < length) {\n            ch = source[index];\n\n            if (lineComment) {\n                ch = nextChar();\n                if (isLineTerminator(ch)) {\n                    lineComment = false;\n                    if (ch === '\\r' && source[index] === '\\n') {\n                        ++index;\n                    }\n                    ++lineNumber;\n                    lineStart = index;\n                }\n            } else if (blockComment) {\n                if (isLineTerminator(ch)) {\n                    if (ch === '\\r' && source[index + 1] === '\\n') {\n                        ++index;\n                    }\n                    ++lineNumber;\n                    ++index;\n                    lineStart = index;\n                    if (index >= length) {\n                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                    }\n                } else {\n                    ch = nextChar();\n                    if (index >= length) {\n                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                    }\n                    if (ch === '*') {\n                        ch = source[index];\n                        if (ch === '/') {\n                            ++index;\n                            blockComment = false;\n                        }\n                    }\n                }\n            } else if (ch === '/') {\n                ch = source[index + 1];\n                if (ch === '/') {\n                    index += 2;\n                    lineComment = true;\n                } else if (ch === '*') {\n                    index += 2;\n                    blockComment = true;\n                    if (index >= length) {\n                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                    }\n                } else {\n                    break;\n                }\n            } else if (isWhiteSpace(ch)) {\n                ++index;\n            } else if (isLineTerminator(ch)) {\n                ++index;\n                if (ch ===  '\\r' && source[index] === '\\n') {\n                    ++index;\n                }\n                ++lineNumber;\n                lineStart = index;\n            } else {\n                break;\n            }\n        }\n    }\n\n    function scanHexEscape(prefix) {\n        var i, len, ch, code = 0;\n\n        len = (prefix === 'u') ? 4 : 2;\n        for (i = 0; i < len; ++i) {\n            if (index < length && isHexDigit(source[index])) {\n                ch = nextChar();\n                code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());\n            } else {\n                return '';\n            }\n        }\n        return String.fromCharCode(code);\n    }\n\n    function scanIdentifier() {\n        var ch, start, id, restore;\n\n        ch = source[index];\n        if (!isIdentifierStart(ch)) {\n            return;\n        }\n\n        start = index;\n        if (ch === '\\\\') {\n            ++index;\n            if (source[index] !== 'u') {\n                return;\n            }\n            ++index;\n            restore = index;\n            ch = scanHexEscape('u');\n            if (ch) {\n                if (ch === '\\\\' || !isIdentifierStart(ch)) {\n                    return;\n                }\n                id = ch;\n            } else {\n                index = restore;\n                id = 'u';\n            }\n        } else {\n            id = nextChar();\n        }\n\n        while (index < length) {\n            ch = source[index];\n            if (!isIdentifierPart(ch)) {\n                break;\n            }\n            if (ch === '\\\\') {\n                ++index;\n                if (source[index] !== 'u') {\n                    return;\n                }\n                ++index;\n                restore = index;\n                ch = scanHexEscape('u');\n                if (ch) {\n                    if (ch === '\\\\' || !isIdentifierPart(ch)) {\n                        return;\n                    }\n                    id += ch;\n                } else {\n                    index = restore;\n                    id += 'u';\n                }\n            } else {\n                id += nextChar();\n            }\n        }\n\n        // There is no keyword or literal with only one character.\n        // Thus, it must be an identifier.\n        if (id.length === 1) {\n            return {\n                type: Token.Identifier,\n                value: id,\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        if (isKeyword(id)) {\n            return {\n                type: Token.Keyword,\n                value: id,\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        // 7.8.1 Null Literals\n\n        if (id === 'null') {\n            return {\n                type: Token.NullLiteral,\n                value: id,\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        // 7.8.2 Boolean Literals\n\n        if (id === 'true' || id === 'false') {\n            return {\n                type: Token.BooleanLiteral,\n                value: id,\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        return {\n            type: Token.Identifier,\n            value: id,\n            lineNumber: lineNumber,\n            lineStart: lineStart,\n            range: [start, index]\n        };\n    }\n\n    // 7.7 Punctuators\n\n    function scanPunctuator() {\n        var start = index,\n            ch1 = source[index],\n            ch2,\n            ch3,\n            ch4;\n\n        // Check for most common single-character punctuators.\n\n        if (ch1 === ';' || ch1 === '{' || ch1 === '}') {\n            ++index;\n            return {\n                type: Token.Punctuator,\n                value: ch1,\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        if (ch1 === ',' || ch1 === '(' || ch1 === ')') {\n            ++index;\n            return {\n                type: Token.Punctuator,\n                value: ch1,\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        // Dot (.) can also start a floating-point number, hence the need\n        // to check the next character.\n\n        ch2 = source[index + 1];\n        if (ch1 === '.' && !isDecimalDigit(ch2)) {\n            return {\n                type: Token.Punctuator,\n                value: nextChar(),\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        // Peek more characters.\n\n        ch3 = source[index + 2];\n        ch4 = source[index + 3];\n\n        // 4-character punctuator: >>>=\n\n        if (ch1 === '>' && ch2 === '>' && ch3 === '>') {\n            if (ch4 === '=') {\n                index += 4;\n                return {\n                    type: Token.Punctuator,\n                    value: '>>>=',\n                    lineNumber: lineNumber,\n                    lineStart: lineStart,\n                    range: [start, index]\n                };\n            }\n        }\n\n        // 3-character punctuators: === !== >>> <<= >>=\n\n        if (ch1 === '=' && ch2 === '=' && ch3 === '=') {\n            index += 3;\n            return {\n                type: Token.Punctuator,\n                value: '===',\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        if (ch1 === '!' && ch2 === '=' && ch3 === '=') {\n            index += 3;\n            return {\n                type: Token.Punctuator,\n                value: '!==',\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        if (ch1 === '>' && ch2 === '>' && ch3 === '>') {\n            index += 3;\n            return {\n                type: Token.Punctuator,\n                value: '>>>',\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        if (ch1 === '<' && ch2 === '<' && ch3 === '=') {\n            index += 3;\n            return {\n                type: Token.Punctuator,\n                value: '<<=',\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        if (ch1 === '>' && ch2 === '>' && ch3 === '=') {\n            index += 3;\n            return {\n                type: Token.Punctuator,\n                value: '>>=',\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n\n        // 2-character punctuators: <= >= == != ++ -- << >> && ||\n        // += -= *= %= &= |= ^= /=\n\n        if (ch2 === '=') {\n            if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {\n                index += 2;\n                return {\n                    type: Token.Punctuator,\n                    value: ch1 + ch2,\n                    lineNumber: lineNumber,\n                    lineStart: lineStart,\n                    range: [start, index]\n                };\n            }\n        }\n\n        if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {\n            if ('+-<>&|'.indexOf(ch2) >= 0) {\n                index += 2;\n                return {\n                    type: Token.Punctuator,\n                    value: ch1 + ch2,\n                    lineNumber: lineNumber,\n                    lineStart: lineStart,\n                    range: [start, index]\n                };\n            }\n        }\n\n        // The remaining 1-character punctuators.\n\n        if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) {\n            return {\n                type: Token.Punctuator,\n                value: nextChar(),\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [start, index]\n            };\n        }\n    }\n\n    // 7.8.3 Numeric Literals\n\n    function scanNumericLiteral() {\n        var number, start, ch;\n\n        ch = source[index];\n        assert(isDecimalDigit(ch) || (ch === '.'),\n            'Numeric literal must start with a decimal digit or a decimal point');\n\n        start = index;\n        number = '';\n        if (ch !== '.') {\n            number = nextChar();\n            ch = source[index];\n\n            // Hex number starts with '0x'.\n            // Octal number starts with '0'.\n            if (number === '0') {\n                if (ch === 'x' || ch === 'X') {\n                    number += nextChar();\n                    while (index < length) {\n                        ch = source[index];\n                        if (!isHexDigit(ch)) {\n                            break;\n                        }\n                        number += nextChar();\n                    }\n\n                    if (number.length <= 2) {\n                        // only 0x\n                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                    }\n\n                    if (index < length) {\n                        ch = source[index];\n                        if (isIdentifierStart(ch)) {\n                            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                        }\n                    }\n                    return {\n                        type: Token.NumericLiteral,\n                        value: parseInt(number, 16),\n                        lineNumber: lineNumber,\n                        lineStart: lineStart,\n                        range: [start, index]\n                    };\n                } else if (isOctalDigit(ch)) {\n                    number += nextChar();\n                    while (index < length) {\n                        ch = source[index];\n                        if (!isOctalDigit(ch)) {\n                            break;\n                        }\n                        number += nextChar();\n                    }\n\n                    if (index < length) {\n                        ch = source[index];\n                        if (isIdentifierStart(ch) || isDecimalDigit(ch)) {\n                            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                        }\n                    }\n                    return {\n                        type: Token.NumericLiteral,\n                        value: parseInt(number, 8),\n                        octal: true,\n                        lineNumber: lineNumber,\n                        lineStart: lineStart,\n                        range: [start, index]\n                    };\n                }\n\n                // decimal number starts with '0' such as '09' is illegal.\n                if (isDecimalDigit(ch)) {\n                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                }\n            }\n\n            while (index < length) {\n                ch = source[index];\n                if (!isDecimalDigit(ch)) {\n                    break;\n                }\n                number += nextChar();\n            }\n        }\n\n        if (ch === '.') {\n            number += nextChar();\n            while (index < length) {\n                ch = source[index];\n                if (!isDecimalDigit(ch)) {\n                    break;\n                }\n                number += nextChar();\n            }\n        }\n\n        if (ch === 'e' || ch === 'E') {\n            number += nextChar();\n\n            ch = source[index];\n            if (ch === '+' || ch === '-') {\n                number += nextChar();\n            }\n\n            ch = source[index];\n            if (isDecimalDigit(ch)) {\n                number += nextChar();\n                while (index < length) {\n                    ch = source[index];\n                    if (!isDecimalDigit(ch)) {\n                        break;\n                    }\n                    number += nextChar();\n                }\n            } else {\n                ch = 'character ' + ch;\n                if (index >= length) {\n                    ch = '<end>';\n                }\n                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n            }\n        }\n\n        if (index < length) {\n            ch = source[index];\n            if (isIdentifierStart(ch)) {\n                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n            }\n        }\n\n        return {\n            type: Token.NumericLiteral,\n            value: parseFloat(number),\n            lineNumber: lineNumber,\n            lineStart: lineStart,\n            range: [start, index]\n        };\n    }\n\n    // 7.8.4 String Literals\n\n    function scanStringLiteral() {\n        var str = '', quote, start, ch, code, unescaped, restore, octal = false;\n\n        quote = source[index];\n        assert((quote === '\\'' || quote === '\"'),\n            'String literal must starts with a quote');\n\n        start = index;\n        ++index;\n\n        while (index < length) {\n            ch = nextChar();\n\n            if (ch === quote) {\n                quote = '';\n                break;\n            } else if (ch === '\\\\') {\n                ch = nextChar();\n                if (!isLineTerminator(ch)) {\n                    switch (ch) {\n                    case 'n':\n                        str += '\\n';\n                        break;\n                    case 'r':\n                        str += '\\r';\n                        break;\n                    case 't':\n                        str += '\\t';\n                        break;\n                    case 'u':\n                    case 'x':\n                        restore = index;\n                        unescaped = scanHexEscape(ch);\n                        if (unescaped) {\n                            str += unescaped;\n                        } else {\n                            index = restore;\n                            str += ch;\n                        }\n                        break;\n                    case 'b':\n                        str += '\\b';\n                        break;\n                    case 'f':\n                        str += '\\f';\n                        break;\n                    case 'v':\n                        str += '\\v';\n                        break;\n\n                    default:\n                        if (isOctalDigit(ch)) {\n                            code = '01234567'.indexOf(ch);\n\n                            // \\0 is not octal escape sequence\n                            if (code !== 0) {\n                                octal = true;\n                            }\n\n                            if (index < length && isOctalDigit(source[index])) {\n                                octal = true;\n                                code = code * 8 + '01234567'.indexOf(nextChar());\n\n                                // 3 digits are only allowed when string starts\n                                // with 0, 1, 2, 3\n                                if ('0123'.indexOf(ch) >= 0 &&\n                                        index < length &&\n                                        isOctalDigit(source[index])) {\n                                    code = code * 8 + '01234567'.indexOf(nextChar());\n                                }\n                            }\n                            str += String.fromCharCode(code);\n                        } else {\n                            str += ch;\n                        }\n                        break;\n                    }\n                } else {\n                    ++lineNumber;\n                    if (ch ===  '\\r' && source[index] === '\\n') {\n                        ++index;\n                    }\n                }\n            } else if (isLineTerminator(ch)) {\n                break;\n            } else {\n                str += ch;\n            }\n        }\n\n        if (quote !== '') {\n            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n        }\n\n        return {\n            type: Token.StringLiteral,\n            value: str,\n            octal: octal,\n            lineNumber: lineNumber,\n            lineStart: lineStart,\n            range: [start, index]\n        };\n    }\n\n    function scanRegExp() {\n        var str = '', ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;\n\n        buffer = null;\n        skipComment();\n\n        start = index;\n        ch = source[index];\n        assert(ch === '/', 'Regular expression literal must start with a slash');\n        str = nextChar();\n\n        while (index < length) {\n            ch = nextChar();\n            str += ch;\n            if (classMarker) {\n                if (ch === ']') {\n                    classMarker = false;\n                }\n            } else {\n                if (ch === '\\\\') {\n                    ch = nextChar();\n                    // ECMA-262 7.8.5\n                    if (isLineTerminator(ch)) {\n                        throwError({}, Messages.UnterminatedRegExp);\n                    }\n                    str += ch;\n                } else if (ch === '/') {\n                    terminated = true;\n                    break;\n                } else if (ch === '[') {\n                    classMarker = true;\n                } else if (isLineTerminator(ch)) {\n                    throwError({}, Messages.UnterminatedRegExp);\n                }\n            }\n        }\n\n        if (!terminated) {\n            throwError({}, Messages.UnterminatedRegExp);\n        }\n\n        // Exclude leading and trailing slash.\n        pattern = str.substr(1, str.length - 2);\n\n        flags = '';\n        while (index < length) {\n            ch = source[index];\n            if (!isIdentifierPart(ch)) {\n                break;\n            }\n\n            ++index;\n            if (ch === '\\\\' && index < length) {\n                ch = source[index];\n                if (ch === 'u') {\n                    ++index;\n                    restore = index;\n                    ch = scanHexEscape('u');\n                    if (ch) {\n                        flags += ch;\n                        str += '\\\\u';\n                        for (; restore < index; ++restore) {\n                            str += source[restore];\n                        }\n                    } else {\n                        index = restore;\n                        flags += 'u';\n                        str += '\\\\u';\n                    }\n                } else {\n                    str += '\\\\';\n                }\n            } else {\n                flags += ch;\n                str += ch;\n            }\n        }\n\n        try {\n            value = new RegExp(pattern, flags);\n        } catch (e) {\n            throwError({}, Messages.InvalidRegExp);\n        }\n\n        return {\n            literal: str,\n            value: value,\n            range: [start, index]\n        };\n    }\n\n    function isIdentifierName(token) {\n        return token.type === Token.Identifier ||\n            token.type === Token.Keyword ||\n            token.type === Token.BooleanLiteral ||\n            token.type === Token.NullLiteral;\n    }\n\n    function advance() {\n        var ch, token;\n\n        skipComment();\n\n        if (index >= length) {\n            return {\n                type: Token.EOF,\n                lineNumber: lineNumber,\n                lineStart: lineStart,\n                range: [index, index]\n            };\n        }\n\n        token = scanPunctuator();\n        if (typeof token !== 'undefined') {\n            return token;\n        }\n\n        ch = source[index];\n\n        if (ch === '\\'' || ch === '\"') {\n            return scanStringLiteral();\n        }\n\n        if (ch === '.' || isDecimalDigit(ch)) {\n            return scanNumericLiteral();\n        }\n\n        token = scanIdentifier();\n        if (typeof token !== 'undefined') {\n            return token;\n        }\n\n        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n    }\n\n    function lex() {\n        var token;\n\n        if (buffer) {\n            index = buffer.range[1];\n            lineNumber = buffer.lineNumber;\n            lineStart = buffer.lineStart;\n            token = buffer;\n            buffer = null;\n            return token;\n        }\n\n        buffer = null;\n        return advance();\n    }\n\n    function lookahead() {\n        var pos, line, start;\n\n        if (buffer !== null) {\n            return buffer;\n        }\n\n        pos = index;\n        line = lineNumber;\n        start = lineStart;\n        buffer = advance();\n        index = pos;\n        lineNumber = line;\n        lineStart = start;\n\n        return buffer;\n    }\n\n    // Return true if there is a line terminator before the next token.\n\n    function peekLineTerminator() {\n        var pos, line, start, found;\n\n        pos = index;\n        line = lineNumber;\n        start = lineStart;\n        skipComment();\n        found = lineNumber !== line;\n        index = pos;\n        lineNumber = line;\n        lineStart = start;\n\n        return found;\n    }\n\n    // Throw an exception\n\n    function throwError(token, messageFormat) {\n        var error,\n            args = Array.prototype.slice.call(arguments, 2),\n            msg = messageFormat.replace(\n                /%(\\d)/g,\n                function (whole, index) {\n                    return args[index] || '';\n                }\n            );\n\n        if (typeof token.lineNumber === 'number') {\n            error = new Error('Line ' + token.lineNumber + ': ' + msg);\n            error.index = token.range[0];\n            error.lineNumber = token.lineNumber;\n            error.column = token.range[0] - lineStart + 1;\n        } else {\n            error = new Error('Line ' + lineNumber + ': ' + msg);\n            error.index = index;\n            error.lineNumber = lineNumber;\n            error.column = index - lineStart + 1;\n        }\n\n        throw error;\n    }\n\n    function throwErrorTolerant() {\n        try {\n            throwError.apply(null, arguments);\n        } catch (e) {\n            if (extra.errors) {\n                extra.errors.push(e);\n            } else {\n                throw e;\n            }\n        }\n    }\n\n\n    // Throw an exception because of the token.\n\n    function throwUnexpected(token) {\n        if (token.type === Token.EOF) {\n            throwError(token, Messages.UnexpectedEOS);\n        }\n\n        if (token.type === Token.NumericLiteral) {\n            throwError(token, Messages.UnexpectedNumber);\n        }\n\n        if (token.type === Token.StringLiteral) {\n            throwError(token, Messages.UnexpectedString);\n        }\n\n        if (token.type === Token.Identifier) {\n            throwError(token, Messages.UnexpectedIdentifier);\n        }\n\n        if (token.type === Token.Keyword) {\n            if (isFutureReservedWord(token.value)) {\n                throwError(token, Messages.UnexpectedReserved);\n            } else if (strict && isStrictModeReservedWord(token.value)) {\n                throwErrorTolerant(token, Messages.StrictReservedWord);\n                return;\n            }\n            throwError(token, Messages.UnexpectedToken, token.value);\n        }\n\n        // BooleanLiteral, NullLiteral, or Punctuator.\n        throwError(token, Messages.UnexpectedToken, token.value);\n    }\n\n    // Expect the next token to match the specified punctuator.\n    // If not, an exception will be thrown.\n\n    function expect(value) {\n        var token = lex();\n        if (token.type !== Token.Punctuator || token.value !== value) {\n            throwUnexpected(token);\n        }\n    }\n\n    // Expect the next token to match the specified keyword.\n    // If not, an exception will be thrown.\n\n    function expectKeyword(keyword) {\n        var token = lex();\n        if (token.type !== Token.Keyword || token.value !== keyword) {\n            throwUnexpected(token);\n        }\n    }\n\n    // Return true if the next token matches the specified punctuator.\n\n    function match(value) {\n        var token = lookahead();\n        return token.type === Token.Punctuator && token.value === value;\n    }\n\n    // Return true if the next token matches the specified keyword\n\n    function matchKeyword(keyword) {\n        var token = lookahead();\n        return token.type === Token.Keyword && token.value === keyword;\n    }\n\n    // Return true if the next token is an assignment operator\n\n    function matchAssign() {\n        var token = lookahead(),\n            op = token.value;\n\n        if (token.type !== Token.Punctuator) {\n            return false;\n        }\n        return op === '=' ||\n            op === '*=' ||\n            op === '/=' ||\n            op === '%=' ||\n            op === '+=' ||\n            op === '-=' ||\n            op === '<<=' ||\n            op === '>>=' ||\n            op === '>>>=' ||\n            op === '&=' ||\n            op === '^=' ||\n            op === '|=';\n    }\n\n    function consumeSemicolon() {\n        var token, line;\n\n        // Catch the very common case first.\n        if (source[index] === ';') {\n            lex();\n            return;\n        }\n\n        line = lineNumber;\n        skipComment();\n        if (lineNumber !== line) {\n            return;\n        }\n\n        if (match(';')) {\n            lex();\n            return;\n        }\n\n        token = lookahead();\n        if (token.type !== Token.EOF && !match('}')) {\n            throwUnexpected(token);\n        }\n        return;\n    }\n\n    // Return true if provided expression is LeftHandSideExpression\n\n    function isLeftHandSide(expr) {\n        return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;\n    }\n\n    // 11.1.4 Array Initialiser\n\n    function parseArrayInitialiser() {\n        var elements = [];\n\n        expect('[');\n\n        while (!match(']')) {\n            if (match(',')) {\n                lex();\n                elements.push(null);\n            } else {\n                elements.push(parseAssignmentExpression());\n\n                if (!match(']')) {\n                    expect(',');\n                }\n            }\n        }\n\n        expect(']');\n\n        return {\n            type: Syntax.ArrayExpression,\n            elements: elements\n        };\n    }\n\n    // 11.1.5 Object Initialiser\n\n    function parsePropertyFunction(param, first) {\n        var previousStrict, body;\n\n        previousStrict = strict;\n        body = parseFunctionSourceElements();\n        if (first && strict && isRestrictedWord(param[0].name)) {\n            throwErrorTolerant(first, Messages.StrictParamName);\n        }\n        strict = previousStrict;\n\n        return {\n            type: Syntax.FunctionExpression,\n            id: null,\n            params: param,\n            defaults: [],\n            body: body,\n            rest: null,\n            generator: false,\n            expression: false\n        };\n    }\n\n    function parseObjectPropertyKey() {\n        var token = lex();\n\n        // Note: This function is called only from parseObjectProperty(), where\n        // EOF and Punctuator tokens are already filtered out.\n\n        if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {\n            if (strict && token.octal) {\n                throwErrorTolerant(token, Messages.StrictOctalLiteral);\n            }\n            return createLiteral(token);\n        }\n\n        return {\n            type: Syntax.Identifier,\n            name: token.value\n        };\n    }\n\n    function parseObjectProperty() {\n        var token, key, id, param;\n\n        token = lookahead();\n\n        if (token.type === Token.Identifier) {\n\n            id = parseObjectPropertyKey();\n\n            // Property Assignment: Getter and Setter.\n\n            if (token.value === 'get' && !match(':')) {\n                key = parseObjectPropertyKey();\n                expect('(');\n                expect(')');\n                return {\n                    type: Syntax.Property,\n                    key: key,\n                    value: parsePropertyFunction([]),\n                    kind: 'get'\n                };\n            } else if (token.value === 'set' && !match(':')) {\n                key = parseObjectPropertyKey();\n                expect('(');\n                token = lookahead();\n                if (token.type !== Token.Identifier) {\n                    throwUnexpected(lex());\n                }\n                param = [ parseVariableIdentifier() ];\n                expect(')');\n                return {\n                    type: Syntax.Property,\n                    key: key,\n                    value: parsePropertyFunction(param, token),\n                    kind: 'set'\n                };\n            } else {\n                expect(':');\n                return {\n                    type: Syntax.Property,\n                    key: id,\n                    value: parseAssignmentExpression(),\n                    kind: 'init'\n                };\n            }\n        } else if (token.type === Token.EOF || token.type === Token.Punctuator) {\n            throwUnexpected(token);\n        } else {\n            key = parseObjectPropertyKey();\n            expect(':');\n            return {\n                type: Syntax.Property,\n                key: key,\n                value: parseAssignmentExpression(),\n                kind: 'init'\n            };\n        }\n    }\n\n    function parseObjectInitialiser() {\n        var properties = [], property, name, kind, map = {}, toString = String;\n\n        expect('{');\n\n        while (!match('}')) {\n            property = parseObjectProperty();\n\n            if (property.key.type === Syntax.Identifier) {\n                name = property.key.name;\n            } else {\n                name = toString(property.key.value);\n            }\n            kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;\n            if (Object.prototype.hasOwnProperty.call(map, name)) {\n                if (map[name] === PropertyKind.Data) {\n                    if (strict && kind === PropertyKind.Data) {\n                        throwErrorTolerant({}, Messages.StrictDuplicateProperty);\n                    } else if (kind !== PropertyKind.Data) {\n                        throwErrorTolerant({}, Messages.AccessorDataProperty);\n                    }\n                } else {\n                    if (kind === PropertyKind.Data) {\n                        throwErrorTolerant({}, Messages.AccessorDataProperty);\n                    } else if (map[name] & kind) {\n                        throwErrorTolerant({}, Messages.AccessorGetSet);\n                    }\n                }\n                map[name] |= kind;\n            } else {\n                map[name] = kind;\n            }\n\n            properties.push(property);\n\n            if (!match('}')) {\n                expect(',');\n            }\n        }\n\n        expect('}');\n\n        return {\n            type: Syntax.ObjectExpression,\n            properties: properties\n        };\n    }\n\n    // 11.1 Primary Expressions\n\n    function parsePrimaryExpression() {\n        var expr,\n            token = lookahead(),\n            type = token.type;\n\n        if (type === Token.Identifier) {\n            return {\n                type: Syntax.Identifier,\n                name: lex().value\n            };\n        }\n\n        if (type === Token.StringLiteral || type === Token.NumericLiteral) {\n            if (strict && token.octal) {\n                throwErrorTolerant(token, Messages.StrictOctalLiteral);\n            }\n            return createLiteral(lex());\n        }\n\n        if (type === Token.Keyword) {\n            if (matchKeyword('this')) {\n                lex();\n                return {\n                    type: Syntax.ThisExpression\n                };\n            }\n\n            if (matchKeyword('function')) {\n                return parseFunctionExpression();\n            }\n        }\n\n        if (type === Token.BooleanLiteral) {\n            lex();\n            token.value = (token.value === 'true');\n            return createLiteral(token);\n        }\n\n        if (type === Token.NullLiteral) {\n            lex();\n            token.value = null;\n            return createLiteral(token);\n        }\n\n        if (match('[')) {\n            return parseArrayInitialiser();\n        }\n\n        if (match('{')) {\n            return parseObjectInitialiser();\n        }\n\n        if (match('(')) {\n            lex();\n            state.lastParenthesized = expr = parseExpression();\n            expect(')');\n            return expr;\n        }\n\n        if (match('/') || match('/=')) {\n            return createLiteral(scanRegExp());\n        }\n\n        return throwUnexpected(lex());\n    }\n\n    // 11.2 Left-Hand-Side Expressions\n\n    function parseArguments() {\n        var args = [];\n\n        expect('(');\n\n        if (!match(')')) {\n            while (index < length) {\n                args.push(parseAssignmentExpression());\n                if (match(')')) {\n                    break;\n                }\n                expect(',');\n            }\n        }\n\n        expect(')');\n\n        return args;\n    }\n\n    function parseNonComputedProperty() {\n        var token = lex();\n\n        if (!isIdentifierName(token)) {\n            throwUnexpected(token);\n        }\n\n        return {\n            type: Syntax.Identifier,\n            name: token.value\n        };\n    }\n\n    function parseNonComputedMember() {\n        expect('.');\n\n        return parseNonComputedProperty();\n    }\n\n    function parseComputedMember() {\n        var expr;\n\n        expect('[');\n\n        expr = parseExpression();\n\n        expect(']');\n\n        return expr;\n    }\n\n    function parseNewExpression() {\n        var expr;\n\n        expectKeyword('new');\n\n        expr = {\n            type: Syntax.NewExpression,\n            callee: parseLeftHandSideExpression(),\n            'arguments': []\n        };\n\n        if (match('(')) {\n            expr['arguments'] = parseArguments();\n        }\n\n        return expr;\n    }\n\n    function parseLeftHandSideExpressionAllowCall() {\n        var expr;\n\n        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();\n\n        while (match('.') || match('[') || match('(')) {\n            if (match('(')) {\n                expr = {\n                    type: Syntax.CallExpression,\n                    callee: expr,\n                    'arguments': parseArguments()\n                };\n            } else if (match('[')) {\n                expr = {\n                    type: Syntax.MemberExpression,\n                    computed: true,\n                    object: expr,\n                    property: parseComputedMember()\n                };\n            } else {\n                expr = {\n                    type: Syntax.MemberExpression,\n                    computed: false,\n                    object: expr,\n                    property: parseNonComputedMember()\n                };\n            }\n        }\n\n        return expr;\n    }\n\n\n    function parseLeftHandSideExpression() {\n        var expr;\n\n        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();\n\n        while (match('.') || match('[')) {\n            if (match('[')) {\n                expr = {\n                    type: Syntax.MemberExpression,\n                    computed: true,\n                    object: expr,\n                    property: parseComputedMember()\n                };\n            } else {\n                expr = {\n                    type: Syntax.MemberExpression,\n                    computed: false,\n                    object: expr,\n                    property: parseNonComputedMember()\n                };\n            }\n        }\n\n        return expr;\n    }\n\n    // 11.3 Postfix Expressions\n\n    function parsePostfixExpression() {\n        var expr = parseLeftHandSideExpressionAllowCall();\n\n        if ((match('++') || match('--')) && !peekLineTerminator()) {\n            // 11.3.1, 11.3.2\n            if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {\n                throwErrorTolerant({}, Messages.StrictLHSPostfix);\n            }\n\n            if (!isLeftHandSide(expr)) {\n                throwError({}, Messages.InvalidLHSInAssignment);\n            }\n\n            expr = {\n                type: Syntax.UpdateExpression,\n                operator: lex().value,\n                argument: expr,\n                prefix: false\n            };\n        }\n\n        return expr;\n    }\n\n    // 11.4 Unary Operators\n\n    function parseUnaryExpression() {\n        var token, expr;\n\n        if (match('++') || match('--')) {\n            token = lex();\n            expr = parseUnaryExpression();\n            // 11.4.4, 11.4.5\n            if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {\n                throwErrorTolerant({}, Messages.StrictLHSPrefix);\n            }\n\n            if (!isLeftHandSide(expr)) {\n                throwError({}, Messages.InvalidLHSInAssignment);\n            }\n\n            expr = {\n                type: Syntax.UpdateExpression,\n                operator: token.value,\n                argument: expr,\n                prefix: true\n            };\n            return expr;\n        }\n\n        if (match('+') || match('-') || match('~') || match('!')) {\n            expr = {\n                type: Syntax.UnaryExpression,\n                operator: lex().value,\n                argument: parseUnaryExpression()\n            };\n            return expr;\n        }\n\n        if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {\n            expr = {\n                type: Syntax.UnaryExpression,\n                operator: lex().value,\n                argument: parseUnaryExpression()\n            };\n            if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {\n                throwErrorTolerant({}, Messages.StrictDelete);\n            }\n            return expr;\n        }\n\n        return parsePostfixExpression();\n    }\n\n    // 11.5 Multiplicative Operators\n\n    function parseMultiplicativeExpression() {\n        var expr = parseUnaryExpression();\n\n        while (match('*') || match('/') || match('%')) {\n            expr = {\n                type: Syntax.BinaryExpression,\n                operator: lex().value,\n                left: expr,\n                right: parseUnaryExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    // 11.6 Additive Operators\n\n    function parseAdditiveExpression() {\n        var expr = parseMultiplicativeExpression();\n\n        while (match('+') || match('-')) {\n            expr = {\n                type: Syntax.BinaryExpression,\n                operator: lex().value,\n                left: expr,\n                right: parseMultiplicativeExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    // 11.7 Bitwise Shift Operators\n\n    function parseShiftExpression() {\n        var expr = parseAdditiveExpression();\n\n        while (match('<<') || match('>>') || match('>>>')) {\n            expr = {\n                type: Syntax.BinaryExpression,\n                operator: lex().value,\n                left: expr,\n                right: parseAdditiveExpression()\n            };\n        }\n\n        return expr;\n    }\n    // 11.8 Relational Operators\n\n    function parseRelationalExpression() {\n        var expr, previousAllowIn;\n\n        previousAllowIn = state.allowIn;\n        state.allowIn = true;\n\n        expr = parseShiftExpression();\n\n        while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) {\n            expr = {\n                type: Syntax.BinaryExpression,\n                operator: lex().value,\n                left: expr,\n                right: parseShiftExpression()\n            };\n        }\n\n        state.allowIn = previousAllowIn;\n        return expr;\n    }\n\n    // 11.9 Equality Operators\n\n    function parseEqualityExpression() {\n        var expr = parseRelationalExpression();\n\n        while (match('==') || match('!=') || match('===') || match('!==')) {\n            expr = {\n                type: Syntax.BinaryExpression,\n                operator: lex().value,\n                left: expr,\n                right: parseRelationalExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    // 11.10 Binary Bitwise Operators\n\n    function parseBitwiseANDExpression() {\n        var expr = parseEqualityExpression();\n\n        while (match('&')) {\n            lex();\n            expr = {\n                type: Syntax.BinaryExpression,\n                operator: '&',\n                left: expr,\n                right: parseEqualityExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    function parseBitwiseXORExpression() {\n        var expr = parseBitwiseANDExpression();\n\n        while (match('^')) {\n            lex();\n            expr = {\n                type: Syntax.BinaryExpression,\n                operator: '^',\n                left: expr,\n                right: parseBitwiseANDExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    function parseBitwiseORExpression() {\n        var expr = parseBitwiseXORExpression();\n\n        while (match('|')) {\n            lex();\n            expr = {\n                type: Syntax.BinaryExpression,\n                operator: '|',\n                left: expr,\n                right: parseBitwiseXORExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    // 11.11 Binary Logical Operators\n\n    function parseLogicalANDExpression() {\n        var expr = parseBitwiseORExpression();\n\n        while (match('&&')) {\n            lex();\n            expr = {\n                type: Syntax.LogicalExpression,\n                operator: '&&',\n                left: expr,\n                right: parseBitwiseORExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    function parseLogicalORExpression() {\n        var expr = parseLogicalANDExpression();\n\n        while (match('||')) {\n            lex();\n            expr = {\n                type: Syntax.LogicalExpression,\n                operator: '||',\n                left: expr,\n                right: parseLogicalANDExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    // 11.12 Conditional Operator\n\n    function parseConditionalExpression() {\n        var expr, previousAllowIn, consequent;\n\n        expr = parseLogicalORExpression();\n\n        if (match('?')) {\n            lex();\n            previousAllowIn = state.allowIn;\n            state.allowIn = true;\n            consequent = parseAssignmentExpression();\n            state.allowIn = previousAllowIn;\n            expect(':');\n\n            expr = {\n                type: Syntax.ConditionalExpression,\n                test: expr,\n                consequent: consequent,\n                alternate: parseAssignmentExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    // 11.13 Assignment Operators\n\n    function parseAssignmentExpression() {\n        var token, expr;\n\n        token = lookahead();\n        expr = parseConditionalExpression();\n\n        if (matchAssign()) {\n            // LeftHandSideExpression\n            if (!isLeftHandSide(expr)) {\n                throwError({}, Messages.InvalidLHSInAssignment);\n            }\n\n            // 11.13.1\n            if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {\n                throwErrorTolerant(token, Messages.StrictLHSAssignment);\n            }\n\n            expr = {\n                type: Syntax.AssignmentExpression,\n                operator: lex().value,\n                left: expr,\n                right: parseAssignmentExpression()\n            };\n        }\n\n        return expr;\n    }\n\n    // 11.14 Comma Operator\n\n    function parseExpression() {\n        var expr = parseAssignmentExpression();\n\n        if (match(',')) {\n            expr = {\n                type: Syntax.SequenceExpression,\n                expressions: [ expr ]\n            };\n\n            while (index < length) {\n                if (!match(',')) {\n                    break;\n                }\n                lex();\n                expr.expressions.push(parseAssignmentExpression());\n            }\n\n        }\n        return expr;\n    }\n\n    // 12.1 Block\n\n    function parseStatementList() {\n        var list = [],\n            statement;\n\n        while (index < length) {\n            if (match('}')) {\n                break;\n            }\n            statement = parseSourceElement();\n            if (typeof statement === 'undefined') {\n                break;\n            }\n            list.push(statement);\n        }\n\n        return list;\n    }\n\n    function parseBlock() {\n        var block;\n\n        expect('{');\n\n        block = parseStatementList();\n\n        expect('}');\n\n        return {\n            type: Syntax.BlockStatement,\n            body: block\n        };\n    }\n\n    // 12.2 Variable Statement\n\n    function parseVariableIdentifier() {\n        var token = lex();\n\n        if (token.type !== Token.Identifier) {\n            throwUnexpected(token);\n        }\n\n        return {\n            type: Syntax.Identifier,\n            name: token.value\n        };\n    }\n\n    function parseVariableDeclaration(kind) {\n        var id = parseVariableIdentifier(),\n            init = null;\n\n        // 12.2.1\n        if (strict && isRestrictedWord(id.name)) {\n            throwErrorTolerant({}, Messages.StrictVarName);\n        }\n\n        if (kind === 'const') {\n            expect('=');\n            init = parseAssignmentExpression();\n        } else if (match('=')) {\n            lex();\n            init = parseAssignmentExpression();\n        }\n\n        return {\n            type: Syntax.VariableDeclarator,\n            id: id,\n            init: init\n        };\n    }\n\n    function parseVariableDeclarationList(kind) {\n        var list = [];\n\n        while (index < length) {\n            list.push(parseVariableDeclaration(kind));\n            if (!match(',')) {\n                break;\n            }\n            lex();\n        }\n\n        return list;\n    }\n\n    function parseVariableStatement() {\n        var declarations;\n\n        expectKeyword('var');\n\n        declarations = parseVariableDeclarationList();\n\n        consumeSemicolon();\n\n        return {\n            type: Syntax.VariableDeclaration,\n            declarations: declarations,\n            kind: 'var'\n        };\n    }\n\n    // kind may be `const` or `let`\n    // Both are experimental and not in the specification yet.\n    // see http://wiki.ecmascript.org/doku.php?id=harmony:const\n    // and http://wiki.ecmascript.org/doku.php?id=harmony:let\n    function parseConstLetDeclaration(kind) {\n        var declarations;\n\n        expectKeyword(kind);\n\n        declarations = parseVariableDeclarationList(kind);\n\n        consumeSemicolon();\n\n        return {\n            type: Syntax.VariableDeclaration,\n            declarations: declarations,\n            kind: kind\n        };\n    }\n\n    // 12.3 Empty Statement\n\n    function parseEmptyStatement() {\n        expect(';');\n\n        return {\n            type: Syntax.EmptyStatement\n        };\n    }\n\n    // 12.4 Expression Statement\n\n    function parseExpressionStatement() {\n        var expr = parseExpression();\n\n        consumeSemicolon();\n\n        return {\n            type: Syntax.ExpressionStatement,\n            expression: expr\n        };\n    }\n\n    // 12.5 If statement\n\n    function parseIfStatement() {\n        var test, consequent, alternate;\n\n        expectKeyword('if');\n\n        expect('(');\n\n        test = parseExpression();\n\n        expect(')');\n\n        consequent = parseStatement();\n\n        if (matchKeyword('else')) {\n            lex();\n            alternate = parseStatement();\n        } else {\n            alternate = null;\n        }\n\n        return {\n            type: Syntax.IfStatement,\n            test: test,\n            consequent: consequent,\n            alternate: alternate\n        };\n    }\n\n    // 12.6 Iteration Statements\n\n    function parseDoWhileStatement() {\n        var body, test, oldInIteration;\n\n        expectKeyword('do');\n\n        oldInIteration = state.inIteration;\n        state.inIteration = true;\n\n        body = parseStatement();\n\n        state.inIteration = oldInIteration;\n\n        expectKeyword('while');\n\n        expect('(');\n\n        test = parseExpression();\n\n        expect(')');\n\n        if (match(';')) {\n            lex();\n        }\n\n        return {\n            type: Syntax.DoWhileStatement,\n            body: body,\n            test: test\n        };\n    }\n\n    function parseWhileStatement() {\n        var test, body, oldInIteration;\n\n        expectKeyword('while');\n\n        expect('(');\n\n        test = parseExpression();\n\n        expect(')');\n\n        oldInIteration = state.inIteration;\n        state.inIteration = true;\n\n        body = parseStatement();\n\n        state.inIteration = oldInIteration;\n\n        return {\n            type: Syntax.WhileStatement,\n            test: test,\n            body: body\n        };\n    }\n\n    function parseForVariableDeclaration() {\n        var token = lex();\n\n        return {\n            type: Syntax.VariableDeclaration,\n            declarations: parseVariableDeclarationList(),\n            kind: token.value\n        };\n    }\n\n    function parseForStatement() {\n        var init, test, update, left, right, body, oldInIteration;\n\n        init = test = update = null;\n\n        expectKeyword('for');\n\n        expect('(');\n\n        if (match(';')) {\n            lex();\n        } else {\n            if (matchKeyword('var') || matchKeyword('let')) {\n                state.allowIn = false;\n                init = parseForVariableDeclaration();\n                state.allowIn = true;\n\n                if (init.declarations.length === 1 && matchKeyword('in')) {\n                    lex();\n                    left = init;\n                    right = parseExpression();\n                    init = null;\n                }\n            } else {\n                state.allowIn = false;\n                init = parseExpression();\n                state.allowIn = true;\n\n                if (matchKeyword('in')) {\n                    // LeftHandSideExpression\n                    if (!isLeftHandSide(init)) {\n                        throwError({}, Messages.InvalidLHSInForIn);\n                    }\n\n                    lex();\n                    left = init;\n                    right = parseExpression();\n                    init = null;\n                }\n            }\n\n            if (typeof left === 'undefined') {\n                expect(';');\n            }\n        }\n\n        if (typeof left === 'undefined') {\n\n            if (!match(';')) {\n                test = parseExpression();\n            }\n            expect(';');\n\n            if (!match(')')) {\n                update = parseExpression();\n            }\n        }\n\n        expect(')');\n\n        oldInIteration = state.inIteration;\n        state.inIteration = true;\n\n        body = parseStatement();\n\n        state.inIteration = oldInIteration;\n\n        if (typeof left === 'undefined') {\n            return {\n                type: Syntax.ForStatement,\n                init: init,\n                test: test,\n                update: update,\n                body: body\n            };\n        }\n\n        return {\n            type: Syntax.ForInStatement,\n            left: left,\n            right: right,\n            body: body,\n            each: false\n        };\n    }\n\n    // 12.7 The continue statement\n\n    function parseContinueStatement() {\n        var token, label = null;\n\n        expectKeyword('continue');\n\n        // Optimize the most common form: 'continue;'.\n        if (source[index] === ';') {\n            lex();\n\n            if (!state.inIteration) {\n                throwError({}, Messages.IllegalContinue);\n            }\n\n            return {\n                type: Syntax.ContinueStatement,\n                label: null\n            };\n        }\n\n        if (peekLineTerminator()) {\n            if (!state.inIteration) {\n                throwError({}, Messages.IllegalContinue);\n            }\n\n            return {\n                type: Syntax.ContinueStatement,\n                label: null\n            };\n        }\n\n        token = lookahead();\n        if (token.type === Token.Identifier) {\n            label = parseVariableIdentifier();\n\n            if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {\n                throwError({}, Messages.UnknownLabel, label.name);\n            }\n        }\n\n        consumeSemicolon();\n\n        if (label === null && !state.inIteration) {\n            throwError({}, Messages.IllegalContinue);\n        }\n\n        return {\n            type: Syntax.ContinueStatement,\n            label: label\n        };\n    }\n\n    // 12.8 The break statement\n\n    function parseBreakStatement() {\n        var token, label = null;\n\n        expectKeyword('break');\n\n        // Optimize the most common form: 'break;'.\n        if (source[index] === ';') {\n            lex();\n\n            if (!(state.inIteration || state.inSwitch)) {\n                throwError({}, Messages.IllegalBreak);\n            }\n\n            return {\n                type: Syntax.BreakStatement,\n                label: null\n            };\n        }\n\n        if (peekLineTerminator()) {\n            if (!(state.inIteration || state.inSwitch)) {\n                throwError({}, Messages.IllegalBreak);\n            }\n\n            return {\n                type: Syntax.BreakStatement,\n                label: null\n            };\n        }\n\n        token = lookahead();\n        if (token.type === Token.Identifier) {\n            label = parseVariableIdentifier();\n\n            if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {\n                throwError({}, Messages.UnknownLabel, label.name);\n            }\n        }\n\n        consumeSemicolon();\n\n        if (label === null && !(state.inIteration || state.inSwitch)) {\n            throwError({}, Messages.IllegalBreak);\n        }\n\n        return {\n            type: Syntax.BreakStatement,\n            label: label\n        };\n    }\n\n    // 12.9 The return statement\n\n    function parseReturnStatement() {\n        var token, argument = null;\n\n        expectKeyword('return');\n\n        if (!state.inFunctionBody) {\n            throwErrorTolerant({}, Messages.IllegalReturn);\n        }\n\n        // 'return' followed by a space and an identifier is very common.\n        if (source[index] === ' ') {\n            if (isIdentifierStart(source[index + 1])) {\n                argument = parseExpression();\n                consumeSemicolon();\n                return {\n                    type: Syntax.ReturnStatement,\n                    argument: argument\n                };\n            }\n        }\n\n        if (peekLineTerminator()) {\n            return {\n                type: Syntax.ReturnStatement,\n                argument: null\n            };\n        }\n\n        if (!match(';')) {\n            token = lookahead();\n            if (!match('}') && token.type !== Token.EOF) {\n                argument = parseExpression();\n            }\n        }\n\n        consumeSemicolon();\n\n        return {\n            type: Syntax.ReturnStatement,\n            argument: argument\n        };\n    }\n\n    // 12.10 The with statement\n\n    function parseWithStatement() {\n        var object, body;\n\n        if (strict) {\n            throwErrorTolerant({}, Messages.StrictModeWith);\n        }\n\n        expectKeyword('with');\n\n        expect('(');\n\n        object = parseExpression();\n\n        expect(')');\n\n        body = parseStatement();\n\n        return {\n            type: Syntax.WithStatement,\n            object: object,\n            body: body\n        };\n    }\n\n    // 12.10 The swith statement\n\n    function parseSwitchCase() {\n        var test,\n            consequent = [],\n            statement;\n\n        if (matchKeyword('default')) {\n            lex();\n            test = null;\n        } else {\n            expectKeyword('case');\n            test = parseExpression();\n        }\n        expect(':');\n\n        while (index < length) {\n            if (match('}') || matchKeyword('default') || matchKeyword('case')) {\n                break;\n            }\n            statement = parseStatement();\n            if (typeof statement === 'undefined') {\n                break;\n            }\n            consequent.push(statement);\n        }\n\n        return {\n            type: Syntax.SwitchCase,\n            test: test,\n            consequent: consequent\n        };\n    }\n\n    function parseSwitchStatement() {\n        var discriminant, cases, clause, oldInSwitch, defaultFound;\n\n        expectKeyword('switch');\n\n        expect('(');\n\n        discriminant = parseExpression();\n\n        expect(')');\n\n        expect('{');\n\n        if (match('}')) {\n            lex();\n            return {\n                type: Syntax.SwitchStatement,\n                discriminant: discriminant\n            };\n        }\n\n        cases = [];\n\n        oldInSwitch = state.inSwitch;\n        state.inSwitch = true;\n        defaultFound = false;\n\n        while (index < length) {\n            if (match('}')) {\n                break;\n            }\n            clause = parseSwitchCase();\n            if (clause.test === null) {\n                if (defaultFound) {\n                    throwError({}, Messages.MultipleDefaultsInSwitch);\n                }\n                defaultFound = true;\n            }\n            cases.push(clause);\n        }\n\n        state.inSwitch = oldInSwitch;\n\n        expect('}');\n\n        return {\n            type: Syntax.SwitchStatement,\n            discriminant: discriminant,\n            cases: cases\n        };\n    }\n\n    // 12.13 The throw statement\n\n    function parseThrowStatement() {\n        var argument;\n\n        expectKeyword('throw');\n\n        if (peekLineTerminator()) {\n            throwError({}, Messages.NewlineAfterThrow);\n        }\n\n        argument = parseExpression();\n\n        consumeSemicolon();\n\n        return {\n            type: Syntax.ThrowStatement,\n            argument: argument\n        };\n    }\n\n    // 12.14 The try statement\n\n    function parseCatchClause() {\n        var param;\n\n        expectKeyword('catch');\n\n        expect('(');\n        if (!match(')')) {\n            param = parseExpression();\n            // 12.14.1\n            if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) {\n                throwErrorTolerant({}, Messages.StrictCatchVariable);\n            }\n        }\n        expect(')');\n\n        return {\n            type: Syntax.CatchClause,\n            param: param,\n            body: parseBlock()\n        };\n    }\n\n    function parseTryStatement() {\n        var block, handlers = [], finalizer = null;\n\n        expectKeyword('try');\n\n        block = parseBlock();\n\n        if (matchKeyword('catch')) {\n            handlers.push(parseCatchClause());\n        }\n\n        if (matchKeyword('finally')) {\n            lex();\n            finalizer = parseBlock();\n        }\n\n        if (handlers.length === 0 && !finalizer) {\n            throwError({}, Messages.NoCatchOrFinally);\n        }\n\n        return {\n            type: Syntax.TryStatement,\n            block: block,\n            guardedHandlers: [],\n            handlers: handlers,\n            finalizer: finalizer\n        };\n    }\n\n    // 12.15 The debugger statement\n\n    function parseDebuggerStatement() {\n        expectKeyword('debugger');\n\n        consumeSemicolon();\n\n        return {\n            type: Syntax.DebuggerStatement\n        };\n    }\n\n    // 12 Statements\n\n    function parseStatement() {\n        var token = lookahead(),\n            expr,\n            labeledBody;\n\n        if (token.type === Token.EOF) {\n            throwUnexpected(token);\n        }\n\n        if (token.type === Token.Punctuator) {\n            switch (token.value) {\n            case ';':\n                return parseEmptyStatement();\n            case '{':\n                return parseBlock();\n            case '(':\n                return parseExpressionStatement();\n            default:\n                break;\n            }\n        }\n\n        if (token.type === Token.Keyword) {\n            switch (token.value) {\n            case 'break':\n                return parseBreakStatement();\n            case 'continue':\n                return parseContinueStatement();\n            case 'debugger':\n                return parseDebuggerStatement();\n            case 'do':\n                return parseDoWhileStatement();\n            case 'for':\n                return parseForStatement();\n            case 'function':\n                return parseFunctionDeclaration();\n            case 'if':\n                return parseIfStatement();\n            case 'return':\n                return parseReturnStatement();\n            case 'switch':\n                return parseSwitchStatement();\n            case 'throw':\n                return parseThrowStatement();\n            case 'try':\n                return parseTryStatement();\n            case 'var':\n                return parseVariableStatement();\n            case 'while':\n                return parseWhileStatement();\n            case 'with':\n                return parseWithStatement();\n            default:\n                break;\n            }\n        }\n\n        expr = parseExpression();\n\n        // 12.12 Labelled Statements\n        if ((expr.type === Syntax.Identifier) && match(':')) {\n            lex();\n\n            if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) {\n                throwError({}, Messages.Redeclaration, 'Label', expr.name);\n            }\n\n            state.labelSet[expr.name] = true;\n            labeledBody = parseStatement();\n            delete state.labelSet[expr.name];\n\n            return {\n                type: Syntax.LabeledStatement,\n                label: expr,\n                body: labeledBody\n            };\n        }\n\n        consumeSemicolon();\n\n        return {\n            type: Syntax.ExpressionStatement,\n            expression: expr\n        };\n    }\n\n    // 13 Function Definition\n\n    function parseFunctionSourceElements() {\n        var sourceElement, sourceElements = [], token, directive, firstRestricted,\n            oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody;\n\n        expect('{');\n\n        while (index < length) {\n            token = lookahead();\n            if (token.type !== Token.StringLiteral) {\n                break;\n            }\n\n            sourceElement = parseSourceElement();\n            sourceElements.push(sourceElement);\n            if (sourceElement.expression.type !== Syntax.Literal) {\n                // this is not directive\n                break;\n            }\n            directive = sliceSource(token.range[0] + 1, token.range[1] - 1);\n            if (directive === 'use strict') {\n                strict = true;\n                if (firstRestricted) {\n                    throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);\n                }\n            } else {\n                if (!firstRestricted && token.octal) {\n                    firstRestricted = token;\n                }\n            }\n        }\n\n        oldLabelSet = state.labelSet;\n        oldInIteration = state.inIteration;\n        oldInSwitch = state.inSwitch;\n        oldInFunctionBody = state.inFunctionBody;\n\n        state.labelSet = {};\n        state.inIteration = false;\n        state.inSwitch = false;\n        state.inFunctionBody = true;\n\n        while (index < length) {\n            if (match('}')) {\n                break;\n            }\n            sourceElement = parseSourceElement();\n            if (typeof sourceElement === 'undefined') {\n                break;\n            }\n            sourceElements.push(sourceElement);\n        }\n\n        expect('}');\n\n        state.labelSet = oldLabelSet;\n        state.inIteration = oldInIteration;\n        state.inSwitch = oldInSwitch;\n        state.inFunctionBody = oldInFunctionBody;\n\n        return {\n            type: Syntax.BlockStatement,\n            body: sourceElements\n        };\n    }\n\n    function parseFunctionDeclaration() {\n        var id, param, params = [], body, token, stricted, firstRestricted, message, previousStrict, paramSet;\n\n        expectKeyword('function');\n        token = lookahead();\n        id = parseVariableIdentifier();\n        if (strict) {\n            if (isRestrictedWord(token.value)) {\n                throwErrorTolerant(token, Messages.StrictFunctionName);\n            }\n        } else {\n            if (isRestrictedWord(token.value)) {\n                firstRestricted = token;\n                message = Messages.StrictFunctionName;\n            } else if (isStrictModeReservedWord(token.value)) {\n                firstRestricted = token;\n                message = Messages.StrictReservedWord;\n            }\n        }\n\n        expect('(');\n\n        if (!match(')')) {\n            paramSet = {};\n            while (index < length) {\n                token = lookahead();\n                param = parseVariableIdentifier();\n                if (strict) {\n                    if (isRestrictedWord(token.value)) {\n                        stricted = token;\n                        message = Messages.StrictParamName;\n                    }\n                    if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {\n                        stricted = token;\n                        message = Messages.StrictParamDupe;\n                    }\n                } else if (!firstRestricted) {\n                    if (isRestrictedWord(token.value)) {\n                        firstRestricted = token;\n                        message = Messages.StrictParamName;\n                    } else if (isStrictModeReservedWord(token.value)) {\n                        firstRestricted = token;\n                        message = Messages.StrictReservedWord;\n                    } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {\n                        firstRestricted = token;\n                        message = Messages.StrictParamDupe;\n                    }\n                }\n                params.push(param);\n                paramSet[param.name] = true;\n                if (match(')')) {\n                    break;\n                }\n                expect(',');\n            }\n        }\n\n        expect(')');\n\n        previousStrict = strict;\n        body = parseFunctionSourceElements();\n        if (strict && firstRestricted) {\n            throwError(firstRestricted, message);\n        }\n        if (strict && stricted) {\n            throwErrorTolerant(stricted, message);\n        }\n        strict = previousStrict;\n\n        return {\n            type: Syntax.FunctionDeclaration,\n            id: id,\n            params: params,\n            defaults: [],\n            body: body,\n            rest: null,\n            generator: false,\n            expression: false\n        };\n    }\n\n    function parseFunctionExpression() {\n        var token, id = null, stricted, firstRestricted, message, param, params = [], body, previousStrict, paramSet;\n\n        expectKeyword('function');\n\n        if (!match('(')) {\n            token = lookahead();\n            id = parseVariableIdentifier();\n            if (strict) {\n                if (isRestrictedWord(token.value)) {\n                    throwErrorTolerant(token, Messages.StrictFunctionName);\n                }\n            } else {\n                if (isRestrictedWord(token.value)) {\n                    firstRestricted = token;\n                    message = Messages.StrictFunctionName;\n                } else if (isStrictModeReservedWord(token.value)) {\n                    firstRestricted = token;\n                    message = Messages.StrictReservedWord;\n                }\n            }\n        }\n\n        expect('(');\n\n        if (!match(')')) {\n            paramSet = {};\n            while (index < length) {\n                token = lookahead();\n                param = parseVariableIdentifier();\n                if (strict) {\n                    if (isRestrictedWord(token.value)) {\n                        stricted = token;\n                        message = Messages.StrictParamName;\n                    }\n                    if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {\n                        stricted = token;\n                        message = Messages.StrictParamDupe;\n                    }\n                } else if (!firstRestricted) {\n                    if (isRestrictedWord(token.value)) {\n                        firstRestricted = token;\n                        message = Messages.StrictParamName;\n                    } else if (isStrictModeReservedWord(token.value)) {\n                        firstRestricted = token;\n                        message = Messages.StrictReservedWord;\n                    } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {\n                        firstRestricted = token;\n                        message = Messages.StrictParamDupe;\n                    }\n                }\n                params.push(param);\n                paramSet[param.name] = true;\n                if (match(')')) {\n                    break;\n                }\n                expect(',');\n            }\n        }\n\n        expect(')');\n\n        previousStrict = strict;\n        body = parseFunctionSourceElements();\n        if (strict && firstRestricted) {\n            throwError(firstRestricted, message);\n        }\n        if (strict && stricted) {\n            throwErrorTolerant(stricted, message);\n        }\n        strict = previousStrict;\n\n        return {\n            type: Syntax.FunctionExpression,\n            id: id,\n            params: params,\n            defaults: [],\n            body: body,\n            rest: null,\n            generator: false,\n            expression: false\n        };\n    }\n\n    // 14 Program\n\n    function parseSourceElement() {\n        var token = lookahead();\n\n        if (token.type === Token.Keyword) {\n            switch (token.value) {\n            case 'const':\n            case 'let':\n                return parseConstLetDeclaration(token.value);\n            case 'function':\n                return parseFunctionDeclaration();\n            default:\n                return parseStatement();\n            }\n        }\n\n        if (token.type !== Token.EOF) {\n            return parseStatement();\n        }\n    }\n\n    function parseSourceElements() {\n        var sourceElement, sourceElements = [], token, directive, firstRestricted;\n\n        while (index < length) {\n            token = lookahead();\n            if (token.type !== Token.StringLiteral) {\n                break;\n            }\n\n            sourceElement = parseSourceElement();\n            sourceElements.push(sourceElement);\n            if (sourceElement.expression.type !== Syntax.Literal) {\n                // this is not directive\n                break;\n            }\n            directive = sliceSource(token.range[0] + 1, token.range[1] - 1);\n            if (directive === 'use strict') {\n                strict = true;\n                if (firstRestricted) {\n                    throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);\n                }\n            } else {\n                if (!firstRestricted && token.octal) {\n                    firstRestricted = token;\n                }\n            }\n        }\n\n        while (index < length) {\n            sourceElement = parseSourceElement();\n            if (typeof sourceElement === 'undefined') {\n                break;\n            }\n            sourceElements.push(sourceElement);\n        }\n        return sourceElements;\n    }\n\n    function parseProgram() {\n        var program;\n        strict = false;\n        program = {\n            type: Syntax.Program,\n            body: parseSourceElements()\n        };\n        return program;\n    }\n\n    // The following functions are needed only when the option to preserve\n    // the comments is active.\n\n    function addComment(type, value, start, end, loc) {\n        assert(typeof start === 'number', 'Comment must have valid position');\n\n        // Because the way the actual token is scanned, often the comments\n        // (if any) are skipped twice during the lexical analysis.\n        // Thus, we need to skip adding a comment if the comment array already\n        // handled it.\n        if (extra.comments.length > 0) {\n            if (extra.comments[extra.comments.length - 1].range[1] > start) {\n                return;\n            }\n        }\n\n        extra.comments.push({\n            type: type,\n            value: value,\n            range: [start, end],\n            loc: loc\n        });\n    }\n\n    function scanComment() {\n        var comment, ch, loc, start, blockComment, lineComment;\n\n        comment = '';\n        blockComment = false;\n        lineComment = false;\n\n        while (index < length) {\n            ch = source[index];\n\n            if (lineComment) {\n                ch = nextChar();\n                if (isLineTerminator(ch)) {\n                    loc.end = {\n                        line: lineNumber,\n                        column: index - lineStart - 1\n                    };\n                    lineComment = false;\n                    addComment('Line', comment, start, index - 1, loc);\n                    if (ch === '\\r' && source[index] === '\\n') {\n                        ++index;\n                    }\n                    ++lineNumber;\n                    lineStart = index;\n                    comment = '';\n                } else if (index >= length) {\n                    lineComment = false;\n                    comment += ch;\n                    loc.end = {\n                        line: lineNumber,\n                        column: length - lineStart\n                    };\n                    addComment('Line', comment, start, length, loc);\n                } else {\n                    comment += ch;\n                }\n            } else if (blockComment) {\n                if (isLineTerminator(ch)) {\n                    if (ch === '\\r' && source[index + 1] === '\\n') {\n                        ++index;\n                        comment += '\\r\\n';\n                    } else {\n                        comment += ch;\n                    }\n                    ++lineNumber;\n                    ++index;\n                    lineStart = index;\n                    if (index >= length) {\n                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                    }\n                } else {\n                    ch = nextChar();\n                    if (index >= length) {\n                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                    }\n                    comment += ch;\n                    if (ch === '*') {\n                        ch = source[index];\n                        if (ch === '/') {\n                            comment = comment.substr(0, comment.length - 1);\n                            blockComment = false;\n                            ++index;\n                            loc.end = {\n                                line: lineNumber,\n                                column: index - lineStart\n                            };\n                            addComment('Block', comment, start, index, loc);\n                            comment = '';\n                        }\n                    }\n                }\n            } else if (ch === '/') {\n                ch = source[index + 1];\n                if (ch === '/') {\n                    loc = {\n                        start: {\n                            line: lineNumber,\n                            column: index - lineStart\n                        }\n                    };\n                    start = index;\n                    index += 2;\n                    lineComment = true;\n                    if (index >= length) {\n                        loc.end = {\n                            line: lineNumber,\n                            column: index - lineStart\n                        };\n                        lineComment = false;\n                        addComment('Line', comment, start, index, loc);\n                    }\n                } else if (ch === '*') {\n                    start = index;\n                    index += 2;\n                    blockComment = true;\n                    loc = {\n                        start: {\n                            line: lineNumber,\n                            column: index - lineStart - 2\n                        }\n                    };\n                    if (index >= length) {\n                        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');\n                    }\n                } else {\n                    break;\n                }\n            } else if (isWhiteSpace(ch)) {\n                ++index;\n            } else if (isLineTerminator(ch)) {\n                ++index;\n                if (ch ===  '\\r' && source[index] === '\\n') {\n                    ++index;\n                }\n                ++lineNumber;\n                lineStart = index;\n            } else {\n                break;\n            }\n        }\n    }\n\n    function filterCommentLocation() {\n        var i, entry, comment, comments = [];\n\n        for (i = 0; i < extra.comments.length; ++i) {\n            entry = extra.comments[i];\n            comment = {\n                type: entry.type,\n                value: entry.value\n            };\n            if (extra.range) {\n                comment.range = entry.range;\n            }\n            if (extra.loc) {\n                comment.loc = entry.loc;\n            }\n            comments.push(comment);\n        }\n\n        extra.comments = comments;\n    }\n\n    function collectToken() {\n        var start, loc, token, range, value;\n\n        skipComment();\n        start = index;\n        loc = {\n            start: {\n                line: lineNumber,\n                column: index - lineStart\n            }\n        };\n\n        token = extra.advance();\n        loc.end = {\n            line: lineNumber,\n            column: index - lineStart\n        };\n\n        if (token.type !== Token.EOF) {\n            range = [token.range[0], token.range[1]];\n            value = sliceSource(token.range[0], token.range[1]);\n            extra.tokens.push({\n                type: TokenName[token.type],\n                value: value,\n                range: range,\n                loc: loc\n            });\n        }\n\n        return token;\n    }\n\n    function collectRegex() {\n        var pos, loc, regex, token;\n\n        skipComment();\n\n        pos = index;\n        loc = {\n            start: {\n                line: lineNumber,\n                column: index - lineStart\n            }\n        };\n\n        regex = extra.scanRegExp();\n        loc.end = {\n            line: lineNumber,\n            column: index - lineStart\n        };\n\n        // Pop the previous token, which is likely '/' or '/='\n        if (extra.tokens.length > 0) {\n            token = extra.tokens[extra.tokens.length - 1];\n            if (token.range[0] === pos && token.type === 'Punctuator') {\n                if (token.value === '/' || token.value === '/=') {\n                    extra.tokens.pop();\n                }\n            }\n        }\n\n        extra.tokens.push({\n            type: 'RegularExpression',\n            value: regex.literal,\n            range: [pos, index],\n            loc: loc\n        });\n\n        return regex;\n    }\n\n    function filterTokenLocation() {\n        var i, entry, token, tokens = [];\n\n        for (i = 0; i < extra.tokens.length; ++i) {\n            entry = extra.tokens[i];\n            token = {\n                type: entry.type,\n                value: entry.value\n            };\n            if (extra.range) {\n                token.range = entry.range;\n            }\n            if (extra.loc) {\n                token.loc = entry.loc;\n            }\n            tokens.push(token);\n        }\n\n        extra.tokens = tokens;\n    }\n\n    function createLiteral(token) {\n        return {\n            type: Syntax.Literal,\n            value: token.value\n        };\n    }\n\n    function createRawLiteral(token) {\n        return {\n            type: Syntax.Literal,\n            value: token.value,\n            raw: sliceSource(token.range[0], token.range[1])\n        };\n    }\n\n    function createLocationMarker() {\n        var marker = {};\n\n        marker.range = [index, index];\n        marker.loc = {\n            start: {\n                line: lineNumber,\n                column: index - lineStart\n            },\n            end: {\n                line: lineNumber,\n                column: index - lineStart\n            }\n        };\n\n        marker.end = function () {\n            this.range[1] = index;\n            this.loc.end.line = lineNumber;\n            this.loc.end.column = index - lineStart;\n        };\n\n        marker.apply = function (node) {\n            if (extra.range) {\n                node.range = [this.range[0], this.range[1]];\n            }\n            if (extra.loc) {\n                node.loc = {\n                    start: {\n                        line: this.loc.start.line,\n                        column: this.loc.start.column\n                    },\n                    end: {\n                        line: this.loc.end.line,\n                        column: this.loc.end.column\n                    }\n                };\n            }\n        };\n\n        return marker;\n    }\n\n    function trackLeftHandSideExpression() {\n        var marker, expr;\n\n        skipComment();\n        marker = createLocationMarker();\n\n        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();\n\n        while (match('.') || match('[')) {\n            if (match('[')) {\n                expr = {\n                    type: Syntax.MemberExpression,\n                    computed: true,\n                    object: expr,\n                    property: parseComputedMember()\n                };\n                marker.end();\n                marker.apply(expr);\n            } else {\n                expr = {\n                    type: Syntax.MemberExpression,\n                    computed: false,\n                    object: expr,\n                    property: parseNonComputedMember()\n                };\n                marker.end();\n                marker.apply(expr);\n            }\n        }\n\n        return expr;\n    }\n\n    function trackLeftHandSideExpressionAllowCall() {\n        var marker, expr;\n\n        skipComment();\n        marker = createLocationMarker();\n\n        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();\n\n        while (match('.') || match('[') || match('(')) {\n            if (match('(')) {\n                expr = {\n                    type: Syntax.CallExpression,\n                    callee: expr,\n                    'arguments': parseArguments()\n                };\n                marker.end();\n                marker.apply(expr);\n            } else if (match('[')) {\n                expr = {\n                    type: Syntax.MemberExpression,\n                    computed: true,\n                    object: expr,\n                    property: parseComputedMember()\n                };\n                marker.end();\n                marker.apply(expr);\n            } else {\n                expr = {\n                    type: Syntax.MemberExpression,\n                    computed: false,\n                    object: expr,\n                    property: parseNonComputedMember()\n                };\n                marker.end();\n                marker.apply(expr);\n            }\n        }\n\n        return expr;\n    }\n\n    function wrapTrackingFunction(range, loc) {\n\n        return function (parseFunction) {\n\n            function isBinary(node) {\n                return node.type === Syntax.LogicalExpression ||\n                    node.type === Syntax.BinaryExpression;\n            }\n\n            function visit(node) {\n                if (isBinary(node.left)) {\n                    visit(node.left);\n                }\n                if (isBinary(node.right)) {\n                    visit(node.right);\n                }\n\n                if (range && typeof node.range === 'undefined') {\n                    node.range = [node.left.range[0], node.right.range[1]];\n                }\n                if (loc && typeof node.loc === 'undefined') {\n                    node.loc = {\n                        start: node.left.loc.start,\n                        end: node.right.loc.end\n                    };\n                }\n            }\n\n            return function () {\n                var marker, node;\n\n                skipComment();\n\n                marker = createLocationMarker();\n                node = parseFunction.apply(null, arguments);\n                marker.end();\n\n                if (range && typeof node.range === 'undefined') {\n                    marker.apply(node);\n                }\n\n                if (loc && typeof node.loc === 'undefined') {\n                    marker.apply(node);\n                }\n\n                if (isBinary(node)) {\n                    visit(node);\n                }\n\n                return node;\n            };\n        };\n    }\n\n    function patch() {\n\n        var wrapTracking;\n\n        if (extra.comments) {\n            extra.skipComment = skipComment;\n            skipComment = scanComment;\n        }\n\n        if (extra.raw) {\n            extra.createLiteral = createLiteral;\n            createLiteral = createRawLiteral;\n        }\n\n        if (extra.range || extra.loc) {\n\n            extra.parseLeftHandSideExpression = parseLeftHandSideExpression;\n            extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;\n            parseLeftHandSideExpression = trackLeftHandSideExpression;\n            parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall;\n\n            wrapTracking = wrapTrackingFunction(extra.range, extra.loc);\n\n            extra.parseAdditiveExpression = parseAdditiveExpression;\n            extra.parseAssignmentExpression = parseAssignmentExpression;\n            extra.parseBitwiseANDExpression = parseBitwiseANDExpression;\n            extra.parseBitwiseORExpression = parseBitwiseORExpression;\n            extra.parseBitwiseXORExpression = parseBitwiseXORExpression;\n            extra.parseBlock = parseBlock;\n            extra.parseFunctionSourceElements = parseFunctionSourceElements;\n            extra.parseCatchClause = parseCatchClause;\n            extra.parseComputedMember = parseComputedMember;\n            extra.parseConditionalExpression = parseConditionalExpression;\n            extra.parseConstLetDeclaration = parseConstLetDeclaration;\n            extra.parseEqualityExpression = parseEqualityExpression;\n            extra.parseExpression = parseExpression;\n            extra.parseForVariableDeclaration = parseForVariableDeclaration;\n            extra.parseFunctionDeclaration = parseFunctionDeclaration;\n            extra.parseFunctionExpression = parseFunctionExpression;\n            extra.parseLeftHandSideExpression = parseLeftHandSideExpression;\n            extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall;\n            extra.parseLogicalANDExpression = parseLogicalANDExpression;\n            extra.parseLogicalORExpression = parseLogicalORExpression;\n            extra.parseMultiplicativeExpression = parseMultiplicativeExpression;\n            extra.parseNewExpression = parseNewExpression;\n            extra.parseNonComputedProperty = parseNonComputedProperty;\n            extra.parseObjectProperty = parseObjectProperty;\n            extra.parseObjectPropertyKey = parseObjectPropertyKey;\n            extra.parsePostfixExpression = parsePostfixExpression;\n            extra.parsePrimaryExpression = parsePrimaryExpression;\n            extra.parseProgram = parseProgram;\n            extra.parsePropertyFunction = parsePropertyFunction;\n            extra.parseRelationalExpression = parseRelationalExpression;\n            extra.parseStatement = parseStatement;\n            extra.parseShiftExpression = parseShiftExpression;\n            extra.parseSwitchCase = parseSwitchCase;\n            extra.parseUnaryExpression = parseUnaryExpression;\n            extra.parseVariableDeclaration = parseVariableDeclaration;\n            extra.parseVariableIdentifier = parseVariableIdentifier;\n\n            parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression);\n            parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);\n            parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression);\n            parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression);\n            parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression);\n            parseBlock = wrapTracking(extra.parseBlock);\n            parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);\n            parseCatchClause = wrapTracking(extra.parseCatchClause);\n            parseComputedMember = wrapTracking(extra.parseComputedMember);\n            parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);\n            parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);\n            parseEqualityExpression = wrapTracking(extra.parseEqualityExpression);\n            parseExpression = wrapTracking(extra.parseExpression);\n            parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);\n            parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);\n            parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);\n            parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression);\n            parseLeftHandSideExpressionAllowCall = wrapTracking(parseLeftHandSideExpressionAllowCall);\n            parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression);\n            parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression);\n            parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression);\n            parseNewExpression = wrapTracking(extra.parseNewExpression);\n            parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);\n            parseObjectProperty = wrapTracking(extra.parseObjectProperty);\n            parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);\n            parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);\n            parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);\n            parseProgram = wrapTracking(extra.parseProgram);\n            parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);\n            parseRelationalExpression = wrapTracking(extra.parseRelationalExpression);\n            parseStatement = wrapTracking(extra.parseStatement);\n            parseShiftExpression = wrapTracking(extra.parseShiftExpression);\n            parseSwitchCase = wrapTracking(extra.parseSwitchCase);\n            parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);\n            parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);\n            parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);\n        }\n\n        if (typeof extra.tokens !== 'undefined') {\n            extra.advance = advance;\n            extra.scanRegExp = scanRegExp;\n\n            advance = collectToken;\n            scanRegExp = collectRegex;\n        }\n    }\n\n    function unpatch() {\n        if (typeof extra.skipComment === 'function') {\n            skipComment = extra.skipComment;\n        }\n\n        if (extra.raw) {\n            createLiteral = extra.createLiteral;\n        }\n\n        if (extra.range || extra.loc) {\n            parseAdditiveExpression = extra.parseAdditiveExpression;\n            parseAssignmentExpression = extra.parseAssignmentExpression;\n            parseBitwiseANDExpression = extra.parseBitwiseANDExpression;\n            parseBitwiseORExpression = extra.parseBitwiseORExpression;\n            parseBitwiseXORExpression = extra.parseBitwiseXORExpression;\n            parseBlock = extra.parseBlock;\n            parseFunctionSourceElements = extra.parseFunctionSourceElements;\n            parseCatchClause = extra.parseCatchClause;\n            parseComputedMember = extra.parseComputedMember;\n            parseConditionalExpression = extra.parseConditionalExpression;\n            parseConstLetDeclaration = extra.parseConstLetDeclaration;\n            parseEqualityExpression = extra.parseEqualityExpression;\n            parseExpression = extra.parseExpression;\n            parseForVariableDeclaration = extra.parseForVariableDeclaration;\n            parseFunctionDeclaration = extra.parseFunctionDeclaration;\n            parseFunctionExpression = extra.parseFunctionExpression;\n            parseLeftHandSideExpression = extra.parseLeftHandSideExpression;\n            parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall;\n            parseLogicalANDExpression = extra.parseLogicalANDExpression;\n            parseLogicalORExpression = extra.parseLogicalORExpression;\n            parseMultiplicativeExpression = extra.parseMultiplicativeExpression;\n            parseNewExpression = extra.parseNewExpression;\n            parseNonComputedProperty = extra.parseNonComputedProperty;\n            parseObjectProperty = extra.parseObjectProperty;\n            parseObjectPropertyKey = extra.parseObjectPropertyKey;\n            parsePrimaryExpression = extra.parsePrimaryExpression;\n            parsePostfixExpression = extra.parsePostfixExpression;\n            parseProgram = extra.parseProgram;\n            parsePropertyFunction = extra.parsePropertyFunction;\n            parseRelationalExpression = extra.parseRelationalExpression;\n            parseStatement = extra.parseStatement;\n            parseShiftExpression = extra.parseShiftExpression;\n            parseSwitchCase = extra.parseSwitchCase;\n            parseUnaryExpression = extra.parseUnaryExpression;\n            parseVariableDeclaration = extra.parseVariableDeclaration;\n            parseVariableIdentifier = extra.parseVariableIdentifier;\n        }\n\n        if (typeof extra.scanRegExp === 'function') {\n            advance = extra.advance;\n            scanRegExp = extra.scanRegExp;\n        }\n    }\n\n    function stringToArray(str) {\n        var length = str.length,\n            result = [],\n            i;\n        for (i = 0; i < length; ++i) {\n            result[i] = str.charAt(i);\n        }\n        return result;\n    }\n\n    function parse(code, options) {\n        var program, toString;\n\n        toString = String;\n        if (typeof code !== 'string' && !(code instanceof String)) {\n            code = toString(code);\n        }\n\n        source = code;\n        index = 0;\n        lineNumber = (source.length > 0) ? 1 : 0;\n        lineStart = 0;\n        length = source.length;\n        buffer = null;\n        state = {\n            allowIn: true,\n            labelSet: {},\n            lastParenthesized: null,\n            inFunctionBody: false,\n            inIteration: false,\n            inSwitch: false\n        };\n\n        extra = {};\n        if (typeof options !== 'undefined') {\n            extra.range = (typeof options.range === 'boolean') && options.range;\n            extra.loc = (typeof options.loc === 'boolean') && options.loc;\n            extra.raw = (typeof options.raw === 'boolean') && options.raw;\n            if (typeof options.tokens === 'boolean' && options.tokens) {\n                extra.tokens = [];\n            }\n            if (typeof options.comment === 'boolean' && options.comment) {\n                extra.comments = [];\n            }\n            if (typeof options.tolerant === 'boolean' && options.tolerant) {\n                extra.errors = [];\n            }\n        }\n\n        if (length > 0) {\n            if (typeof source[0] === 'undefined') {\n                // Try first to convert to a string. This is good as fast path\n                // for old IE which understands string indexing for string\n                // literals only and not for string object.\n                if (code instanceof String) {\n                    source = code.valueOf();\n                }\n\n                // Force accessing the characters via an array.\n                if (typeof source[0] === 'undefined') {\n                    source = stringToArray(code);\n                }\n            }\n        }\n\n        patch();\n        try {\n            program = parseProgram();\n            if (typeof extra.comments !== 'undefined') {\n                filterCommentLocation();\n                program.comments = extra.comments;\n            }\n            if (typeof extra.tokens !== 'undefined') {\n                filterTokenLocation();\n                program.tokens = extra.tokens;\n            }\n            if (typeof extra.errors !== 'undefined') {\n                program.errors = extra.errors;\n            }\n        } catch (e) {\n            throw e;\n        } finally {\n            unpatch();\n            extra = {};\n        }\n\n        return program;\n    }\n\n    // Sync with package.json.\n    exports.version = '1.0.0-dev';\n\n    exports.parse = parse;\n\n    // Deep copy.\n    exports.Syntax = (function () {\n        var name, types = {};\n\n        if (typeof Object.create === 'function') {\n            types = Object.create(null);\n        }\n\n        for (name in Syntax) {\n            if (Syntax.hasOwnProperty(name)) {\n                types[name] = Syntax[name];\n            }\n        }\n\n        if (typeof Object.freeze === 'function') {\n            Object.freeze(types);\n        }\n\n        return types;\n    }());\n\n}));\n/* vim: set sw=4 ts=4 et tw=80 : */\n"
  },
  {
    "path": "togetherjs/libs/walkabout/lib/falafel.js",
    "content": "var _tmpModule = {exports: {}};\n(function (module) {\n\nvar parse = esprima.parse;\nvar objectKeys = Object.keys || function (obj) {\n    var keys = [];\n    for (var key in obj) keys.push(key);\n    return keys;\n};\nvar forEach = function (xs, fn) {\n    if (xs.forEach) return xs.forEach(fn);\n    for (var i = 0; i < xs.length; i++) {\n        fn.call(xs, xs[i], i, xs);\n    }\n};\n\nvar isArray = Array.isArray || function (xs) {\n    return Object.prototype.toString.call(xs) === '[object Array]';\n};\n\nmodule.exports = function (src, opts, fn) {\n    if (typeof opts === 'function') {\n        fn = opts;\n        opts = {};\n    }\n    if (typeof src === 'object') {\n        opts = src;\n        src = opts.source;\n        delete opts.source;\n    }\n    src = src || opts.source;\n    opts.range = true;\n    if (typeof src !== 'string') src = String(src);\n\n    var ast = parse(src, opts);\n\n    var result = {\n        chunks : src.split(''),\n        toString : function () { return result.chunks.join('') },\n        inspect : function () { return result.toString() }\n    };\n    var index = 0;\n\n    (function walk (node, parent) {\n        insertHelpers(node, parent, result.chunks);\n\n        forEach(objectKeys(node), function (key) {\n            if (key === 'parent') return;\n\n            var child = node[key];\n            if (isArray(child)) {\n                forEach(child, function (c) {\n                    if (c && typeof c.type === 'string') {\n                        walk(c, node);\n                    }\n                });\n            }\n            else if (child && typeof child.type === 'string') {\n                insertHelpers(child, node, result.chunks);\n                walk(child, node);\n            }\n        });\n        fn(node);\n    })(ast, undefined);\n\n    return result;\n};\n\nfunction insertHelpers (node, parent, chunks) {\n    if (!node.range) return;\n\n    node.parent = parent;\n\n    node.source = function () {\n        return chunks.slice(\n            node.range[0], node.range[1]\n        ).join('');\n    };\n\n    if (node.update && typeof node.update === 'object') {\n        var prev = node.update;\n        forEach(objectKeys(prev), function (key) {\n            update[key] = prev[key];\n        });\n        node.update = update;\n    }\n    else {\n        node.update = update;\n    }\n\n    function update (s) {\n        chunks[node.range[0]] = s;\n        for (var i = node.range[0] + 1; i < node.range[1]; i++) {\n            chunks[i] = '';\n        }\n    };\n}\n\n})(_tmpModule);\nvar falafel = _tmpModule.exports;\n"
  },
  {
    "path": "togetherjs/libs/walkabout/node-proxy.js",
    "content": "const dns = require(\"dns\");\nconst http = require(\"http\");\nconst fs = require(\"fs\");\nconst walkabout = require(\"./walkabout.js\");\nconst parseUrl = require(\"url\").parse;\n\nvar IPs = {\n  localhost: [\"127.0.0.1\"]\n};\n\nvar PortAliases = {};\n\nfunction loadEtcHosts(callback) {\n  fs.readFile(\"/etc/hosts\", \"UTF-8\", function (error, text) {\n    if (error) {\n      console.log(\"Error reading /etc/hosts:\", error);\n      return;\n    }\n    var lines = text.split(/\\n/g);\n    lines.forEach(function (l) {\n      l = l.replace(/^\\s*/, \"\");\n      if (! l) {\n        // empty line\n        return;\n      }\n      if (l.search(/^\\#/) != -1) {\n        // comment\n        return;\n      }\n      var parts = l.split(/\\s+/g);\n      if (parts[0] == \"255.255.255.255\" || parts[0].indexOf(\":\") != -1 ||\n          parts[0] == \"127.0.0.1\") {\n        return;\n      }\n      for (var i=1; i<parts.length; i++) {\n        if (! parts[i]) {\n          continue;\n        }\n        if (parts[i] in IPs) {\n          if (IPs[parts[i]].indexOf(parts[0]) == -1) {\n            IPs[parts[i]].push(parts[0]);\n          }\n        } else {\n          IPs[parts[i]] = [parts[0]];\n        }\n      }\n    });\n    if (callback) {\n      callback();\n    }\n  });\n}\n\nloadEtcHosts();\n\nvar server = http.createServer(function(request, response) {\n  var host = request.headers[\"host\"];\n  var port = 80;\n  if (parseUrl(request.url).pathname == \"/__walkabout__.js\") {\n    fs.readFile(__dirname + \"/walkabout.js\", function (error, code) {\n      if (error) {\n        write500(error, response);\n        return;\n      }\n      response.writeHead(200, {\"Content-Type\": \"text/javascript\"});\n      response.end(code);\n    });\n    return;\n  }\n  if (host.indexOf(\":\") != -1) {\n    port = host.substr(host.indexOf(\":\") + 1);\n    port = parseInt(port, 10);\n    host = host.replace(/\\:.*$/, \"\");\n  }\n  if (host in PortAliases) {\n    port = PortAliases[host];\n  }\n  if (! IPs[host]) {\n    request.pause();\n    dns.resolve4(host, function (error, addresses) {\n      console.log(\"Resolved host\", host, \"to\", addresses);\n      if (error) {\n        write500(error, response);\n        return;\n      }\n      IPs[host] = addresses;\n      request.resume();\n      forwardRequest(addresses, port, request, response);\n    });\n  } else {\n    forwardRequest(IPs[host], port, request, response);\n  }\n});\n\nvar preamble = (\n  '<script>_Walkabout_start_UI = true;_Walkabout_sitewide = true;</script>' +\n  '<script src=\"/__walkabout__.js\"></script>'\n);\n\nvar seenForwards = {};\n\nfunction forwardRequest(addresses, port, request, response) {\n  var address = addresses[Math.floor(Math.random() * addresses.length)];\n  if (! seenForwards[address]) {\n    seenForwards[address] = true;\n    console.log(\"Forwarding\", request.headers.host, \"to\", address + \":\" + port);\n  }\n  // Avoid gzipped responses:\n  delete request.headers[\"accept-encoding\"];\n  delete request.headers[\"if-modified-since\"];\n  delete request.headers[\"if-not-matches\"];\n  delete request.headers[\"connection\"];\n  request.headers[\"connection\"] = \"close\";\n  var origHost = request.headers.host;\n  request.headers.host = request.headers.host.replace(/:\\d+$/, \"\") + \":\" + port;\n  var clientRequest = http.request({\n    hostname: address,\n    port: port,\n    method: request.method,\n    path: request.url,\n    headers: request.headers\n  });\n  clientRequest.on(\"response\", function (clientResponse) {\n    var contentType = clientResponse.headers[\"content-type\"] || \"\";\n    var isHtml = contentType.indexOf(\"text/html\") != -1;\n    var isJavascript = contentType.indexOf(\"javascript\") != -1;\n    var location = clientResponse.headers[\"location\"];\n    if (location) {\n      clientResponse.location = location.replace(\n        request.headers.host.replace(/:80$/, \"\"), origHost.replace(/:80$/, \"\"));\n    }\n    if (isHtml) {\n      var contentLength = clientResponse.headers[\"content-length\"];\n      if (contentLength) {\n        contentLength = parseInt(contentLength, 10);\n        contentLength += preamble.length;\n        clientResponse.headers[\"content-length\"] = contentLength + \"\";\n      }\n    } else if (isJavascript) {\n      delete clientResponse.headers[\"content-length\"];\n    }\n    response.writeHead(clientResponse.statusCode, clientResponse.headers);\n    var s;\n    if ((! isHtml) && ! isJavascript) {\n      clientResponse.on(\"data\", function (chunk) {\n        response.write(chunk);\n      });\n    } else {\n      s = \"\";\n      clientResponse.on(\"data\", function (chunk) {\n        s += chunk;\n      });\n    }\n    clientResponse.on(\"end\", function () {\n      if (isHtml) {\n        if (s.search(/^</) == -1) {\n          // Doesn't really look like HTML\n          response.write(s);\n        } else {\n          response.write(translateHtml(s));\n        }\n      } else if (isJavascript) {\n        response.write(translateJavascript(s));\n      }\n      response.end();\n    });\n  });\n  clientRequest.on(\"error\", function (error) {\n    error.stage = \"clientRequest\";\n    error.headers = clientRequest._headers;\n    write500(error, response);\n  });\n  request.on(\"data\", function (chunk) {\n    clientRequest.write(chunk);\n  });\n  if (! request.ended) {\n    request.on(\"end\", function () {\n      clientRequest.end();\n    });\n  } else {\n    clientRequest.end();\n  }\n}\n\nfunction translateHtml(s) {\n  var pos = s.search(/<head>/i);\n  if (pos == -1) {\n    return preamble + s;\n  } else {\n    return s.substr(0, pos+6) + preamble + s.substr(pos+6);\n  }\n}\n\nfunction translateJavascript(s) {\n  return walkabout.rewriteListeners(s) + \"\";\n}\n\nfunction write500(error, response) {\n  console.warn(\"Error:\", error);\n  response.writeHead(500, {\"Content-Type\": \"text/plain\"});\n  if (typeof error != \"string\") {\n    error = \"\\n\" + JSON.stringify(error, null, \"  \");\n  }\n  response.end(\"Error: \" + error);\n}\n\nvar PORT = parseInt(process.env.PORT || 80, 10);\nvar BIND = process.env.BIND || \"127.0.0.1\";\n\nif (process.env.PORT_ALIASES) {\n  process.env.PORT_ALIASES.split(/;/g).forEach(function (part) {\n    part = part.split(/:/);\n    PortAliases[part[0]] = part[1];\n  });\n}\n\nconsole.log(\"Serving on\", \"http://\"+BIND+\":\"+PORT);\nserver.listen(PORT, BIND, function () {\n});\n"
  },
  {
    "path": "togetherjs/libs/walkabout/test_overlap.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Walkabout tests</title>\n    <script src=\"http://doctestjs.org/doctest.js\"></script>\n    <link rel=\"stylesheet\" href=\"http://doctestjs.org/doctest.css\"></script>\n    <!--<script src=\"doctestjs/doctest.js\"></script>-->\n    <script src=\"walkabout.js\"></script>\n  </head>\n  <body class=\"autodoctest\">\n\n    <div>\n      <pre class=\"commenttest\" href=\"test_overlap.js\"></pre>\n    </div>\n\n    <div id=\"fixture\">\n\n      <div id=\"modal\" style=\"background-color: #99f; opacity: 0.5;\">goes on top</div>\n\n      <div id=\"underlay\" style=\"background-color: #9f9;\">goes under</div>\n\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/libs/walkabout/test_overlap.js",
    "content": "var fixture = document.getElementById(\"fixture\");\nvar modal = document.getElementById(\"modal\");\nvar underlay = document.getElementById(\"underlay\");\n\nWalkabout.addEventListener(underlay, function (event) {\n  print(\"clicked\");\n}, false);\n\nfunction show(el) {\n  el.style.display = \"\";\n}\n\nfunction hide(el) {\n  el.style.display = \"none\";\n}\n\nprint(Walkabout.visible(modal));\nprint(Walkabout.visible(underlay));\nprint(Walkabout.clickable(underlay));\nhide(modal);\nprint(Walkabout.visible(modal));\nshow(modal);\n\n/* =>\ntrue\ntrue\ntrue\nfalse\n*/\n\nhide(underlay);\nprint(Walkabout.clickable(underlay));\nshow(underlay);\n\n// => false\n\nmodal.style.position = \"absolute\";\nmodal.style.width = \"100px\";\nmodal.style.height = \"100px\";\nmodal.style.top = \"0px\";\nmodal.style.right = \"0px\";\nmodal.style.zIndex = 10;\nunderlay.style.position = \"absolute\";\nunderlay.style.width = \"90px\";\nunderlay.style.height = \"90px\";\nunderlay.style.top = \"5px\";\nunderlay.style.right = \"5px\";\nunderlay.style.zIndex = 5;\n\nprint(getComputedStyle(modal).getPropertyValue(\"position\"));\n\n// => absolute\n\nvar rect = modal.getBoundingClientRect();\n\nprint(rect.bottom, rect.top, rect.height);\nprint(rect.left, rect.right, rect.width);\n\n/* =>\n100 0 100\n? ? 100\n*/\n\nprint(Walkabout.clickable(underlay));\n\n// => false\n\nunderlay.style.zIndex = 15;\nprint(Walkabout.clickable(underlay));\n\n// => true\n\nunderlay.style.zIndex = 5;\nunderlay.style.right = \"20px\";\nprint(Walkabout.clickable(underlay));\n\n// => true\n"
  },
  {
    "path": "togetherjs/libs/walkabout/test_walkabout.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Walkabout tests</title>\n    <script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js\"></script>\n    <script src=\"http://doctestjs.org/doctest.js\"></script>\n    <link rel=\"stylesheet\" href=\"http://doctestjs.org/doctest.css\"></script>\n    <!--<script src=\"doctestjs/doctest.js\"></script>-->\n    <script src=\"walkabout.js\"></script>\n  </head>\n  <body class=\"autodoctest\">\n\n    <div>\n      <pre class=\"commenttest\" href=\"test_walkabout.js\"></pre>\n    </div>\n\n    <div id=\"fixture\">\n      <button id=\"button\">A button</button>\n      <input type=\"text\" id=\"textinput\">\n      <a href=\"#1\" id=\"link\">link</a>\n      <ul>\n        <li class=\"item\">an item 1</li>\n        <li class=\"item\">an item 2</li>\n      </ul>\n      <pre id=\"log\"></pre>\n    </div>\n\n    <div id=\"textarea-fixture\">\n      <textarea id=\"textarea\" style=\"width: 50%; height: 3em\"\n                data-walkabout-edit-value=\"type paste delete move\"></textarea>\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/libs/walkabout/test_walkabout.js",
    "content": "jshint(\"walkabout.js\", {evil: true, scripturl: true});\n// => Script passed: .../walkabout.js\n\nfunction log(text) {\n  console.log(text);\n  if (window.print) {\n    print(text);\n  }\n  $(\"#log\").text($(\"#log\").text() + text + \"\\n\");\n}\n\nfunction logger(name) {\n  return function (text) {\n    log(name + \": \" + text);\n  };\n}\n\n$(\"#button\").click(function () {\n  log(\"button click\");\n});\n\n$(\"#textinput\").bindKey({which: 13}, function () {\n  log(\"Entered text: \" + $(\"#textinput\").val());\n  $(\"#textinput\").val(\"\");\n});\n\nlocation.hash = \"\";\n\n$(window).on(\"hashchange\", function () {\n  var hash = location.hash;\n  if (! hash) {\n    return;\n  }\n  log(\"Hash changed: \" + hash);\n  hash = parseInt(hash.substr(1), 10);\n  $(\"#link\").attr(\"href\", \"#\" + (hash + 1));\n});\n\n$(\"#fixture\").on(\"click\", \".item\", function () {\n  log(\"Clicked li: \" + $(this).text());\n});\n\n// =>\n\nvar actions = $(\"#fixture\").findActions();\nprint(actions);\n\n/* =>\n\n[\n  {element: <a href=\"#1\" id=\"link\">link</a>, options: {}, type: \"click\"},\n  {\n    element: <li class=\"item\">an item 1</li>,\n    handler: function ...,\n    jQuery: true,\n    options: {},\n    type: \"click\"\n  },\n  {\n    element: <li class=\"item\">an item 2</li>,\n    handler: function ...,\n    jQuery: true,\n    options: {},\n    type: \"click\"\n  },\n  {\n    element: <button id=\"button\">A button</button>,\n    handler: function ...,\n    jQuery: true,\n    options: {},\n    type: \"click\"\n  },\n  {\n    element: <input id=\"textinput\" type=\"text\" />,\n    handler: function ...,\n    jQuery: true,\n    options: {},\n    type: \"keypress\"\n  }\n]\n\n*/\n\nWalkabout.random.setSeed(100);\njQuery.fn.val.patch();\n\nactions.forEach(function (a) {\n  a.run();\n});\nwait();\n\n// I don't understand why \"Hash change: #1\" happens twice\n/* =>\n\nClicked li: an item 1\nClicked li: an item 2\nbutton click\nEntered text: zsmOG\nHash changed: #1...\n*/\n\n// Here we demonstrate that the random numbers are repeatable\n// (and hopefully portable):\nvar rand = Walkabout.RandomStream(1);\nfor (var i=0; i<10; i++) {\n  print(rand());\n}\n\n/* =>\n\n0.0225802504...\n0.8612917717...\n0.3039651696...\n0.8526061845...\n0.2648052292...\n0.5323929718...\n0.9003424612...\n0.0378481761...\n0.7294780843...\n0.4245760307...\n\n*/\n\n$(\"#textinput\").attr(\"data-walkabout-options\", \"['a', 'b']\");\nprint($(\"#textinput\").findActions());\n$(\"#textinput\").findActions()[0].run();\n$(\"#textinput\").findActions()[0].run();\n$(\"#textinput\").findActions()[0].run();\n\n/* =>\n\n[\n  {\n    element: <input data-walkabout-options=\"['a', 'b']\" id=\"textinput\" type=\"text\" />,\n    handler: function ...,\n    jQuery: true,\n    options: {},\n    type: \"keypress\"\n  }\n]\nEntered text: a\nEntered text: a\nEntered text: b\n\n*/\n\nlocation.hash = \"#2\";\nactions = $(\"#fixture\").findActions();\nvar last = actions[actions.length - 1];\nprint(last.constructor.name, location.hash);\n\n// => Back #2\n\nlast.run();\nprint(location.hash);\n\n// => #1\n\nactions = $(\"#textarea-fixture\").findActions();\nprint(actions);\n\n/* =>\n[\n  {\n    element: <textarea data-walkabout-edit-value=\"type paste delete move\".../>,\n    kind: \"type\"\n  },\n  {\n    element: <textarea data-walkabout-edit-value=\"type paste delete move\".../>,\n    kind: \"paste\"\n  }\n]\n\n*/\n\nactions[0].run();\nactions[0].run();\nvar t = $(\"#textarea\")[0];\nprint(repr($(\"#textarea\").val()));\n\n// => \"AKQk\"\n\nactions = $(\"#textarea-fixture\").findActions();\nactions.forEach(function (a) {print(a.description());});\n\n/* =>\nType into textarea#textarea\nPaste into textarea#textarea\nDelete from textarea#textarea\nMove cursor in textarea#textarea\n*/\n\nprint(t.selectionStart, t.selectionEnd);\nactions[3].run();\nprint(t.selectionStart, t.selectionEnd);\nactions[3].run();\nprint(t.selectionStart, t.selectionEnd);\n\n/* =>\n2 2\n0 0\n1 1\n*/\n\nprint(repr(t.value));\nactions[0].run(); // type\nprint(repr(t.value));\nactions[1].run(); // paste\nprint(repr(t.value));\nactions[2].run(); // delete\nprint(repr(t.value));\n\n/* =>\n\"\\nQ\"\n\"\\n7Q\"\n\"\\n7 N|`KX)vVSyQ\"\n\"\\n7 N|`KXQ\"\n*/\n"
  },
  {
    "path": "togetherjs/libs/walkabout/test_walkabout_nojquery.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Walkabout tests</title>\n    <link rel=\"stylesheet\" href=\"http://doctestjs.org/doctest.css\"></script>\n    <script src=\"http://doctestjs.org/doctest.js\"></script>\n    <!--<script src=\"doctestjs/doctest.js\"></script>-->\n    <script src=\"lib/esprima.js\"></script>\n    <script src=\"lib/falafel.js\"></script>\n    <script src=\"walkabout.js\"></script>\n  </head>\n  <body class=\"autodoctest\">\n\n    <div>\n      <pre class=\"commenttest\" href=\"test_walkabout_nojquery.js\"></pre>\n    </div>\n\n    <div id=\"fixture\">\n      <button id=\"button\">A button</button>\n      <input type=\"text\" id=\"textinput\" data-walkabout-keypress=\"{which: 13}\">\n      <a href=\"#1\" id=\"link\">link</a>\n      <ul>\n        <li class=\"item\">an item 1</li>\n        <li class=\"item\">an item 2</li>\n      </ul>\n      <pre id=\"log\"></pre>\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/libs/walkabout/test_walkabout_nojquery.js",
    "content": "jshint(\"walkabout.js\", {evil: true, scripturl: true});\n// => Script passed: .../walkabout.js\n\nfunction getElement(id) {\n  var el = document.getElementById(id);\n  if (! el) {\n    throw 'Element not found: #' + id;\n  }\n  return el;\n}\n\nfunction text(t) {\n  return document.createTextNode(t);\n}\n\nfunction log(t) {\n  console.log(t);\n  if (window.print) {\n    print(t);\n  }\n  getElement(\"log\").appendChild(text(t + \"\\n\"));\n}\n\nfunction logger(name) {\n  return function (text) {\n    log(name + \": \" + text);\n  };\n}\n\nvar clickAction = function () {\n  log(\"button click\");\n};\nWalkabout.addEventListener(getElement(\"button\"), \"click\", clickAction);\n\nWalkabout.addEventListener(getElement(\"textinput\"), \"keypress\", function (event) {\n  console.log(\"got keypress\", event.charCode, event.keyCode);\n  if (event.keyCode == 13) {\n    var value = Walkabout.value(getElement(\"textinput\"));\n    log(\"Entered text: \" + value);\n    getElement(\"textinput\").value = \"\";\n  }\n});\n\nlocation.hash = \"\";\n\nWalkabout.addEventListener(window, \"hashchange\", function () {\n  var hash = location.hash;\n  if (! hash) {\n    return;\n  }\n  log(\"Hash changed: \" + hash);\n  hash = parseInt(hash.substr(1), 10);\n  getElement(\"link\").href = \"#\" + (hash + 1);\n});\n\nWalkabout.addEventListener(getElement(\"fixture\"), \"click\", function (event) {\n  if (event.target.classList.contains(\"item\")) {\n    log(\"Clicked li: \" + event.target.textContent);\n  }\n}, false, {selector: \".item\"});\n\n// =>\n\nvar actions = Walkabout.findActions(document);\nprint(actions);\n\n// FIXME: sometimes there's a Back action, sometimes not\n/* =>\n\n[\n  {element: <a href=\"#1\" id=\"link\">link</a>, options: {}, type: \"click\"},\n  {\n    element: <li class=\"item\">an item 1</li>,\n    handler: function ...,\n    type: \"click\"\n  },\n  {\n    element: <li class=\"item\">an item 2</li>,\n    handler: function ...,\n    type: \"click\"\n  },\n  {\n    element: <button id=\"button\">A button</button>,\n    handler: function ...,\n    type: \"click\"\n  },\n  {\n    element: <input data-walkabout-keypress=\"{which: 13}\" id=\"textinput\" type=\"text\" />,\n    handler: function ...,\n    type: \"keypress\"\n  }...\n]\n\n*/\n\nWalkabout.random.setSeed(100);\n\nactions.forEach(function (a) {\n  a.run();\n});\nwait(100);\n\n// I don't understand why \"Hash change: #1\" happens twice\n/* =>\n\nClicked li: an item 1\nClicked li: an item 2\nbutton click\nEntered text: EzsmOGsiee\nHash changed: #1...\n*/\n\ngetElement(\"textinput\").setAttribute(\"data-walkabout-options\", \"['a', 'b']\");\nprint(Walkabout.findActions(getElement(\"textinput\"))[0]);\nWalkabout.findActions(getElement(\"textinput\"))[0].run();\nWalkabout.findActions(getElement(\"textinput\"))[0].run();\nWalkabout.findActions(getElement(\"textinput\"))[0].run();\nWalkabout.findActions(getElement(\"textinput\"))[0].run();\nWalkabout.findActions(getElement(\"textinput\"))[0].run();\nWalkabout.findActions(getElement(\"textinput\"))[0].run();\n\n// FIXME: for some reason this isn't the same as in the jquery example\n// it generates a different order\n/* =>\n\n{\n  element: <input data-walkabout-keypress=\"{which: 13}\" data-walkabout-options=\"['a', 'b']\" id=\"textinput\" type=\"text\" />,\n  handler: function ...,\n  type: \"keypress\"\n}\nEntered text: a\nEntered text: a\nEntered text: a\nEntered text: a\nEntered text: b\nEntered text: b\n\n*/\n\nprint(Walkabout.findActions().length);\n// => 6\n\nWalkabout.removeEventListener(getElement(\"button\"), \"click\", clickAction);\nprint(Walkabout.findActions().length);\n// => 5\n\n\nprint(Walkabout.rewriteListeners(\"function foobar() {el.addEventListener('click', function (foo) {}, false);}\"));\n// => function foobar() {Walkabout.addEventListener(el, 'click', function (foo) {}, false);}\n\nprint(Walkabout.rewriteListeners(\"$('#test')[0].addEventListener('click', function (foo) {}, false);\"));\n// => Walkabout.addEventListener($('#test')[0], 'click', function (foo) {}, false);\n\nprint(Walkabout.rewriteListeners(\"foo().bar.value\"));\n// => Walkabout.value(foo().bar)\n\nprint(Walkabout.rewriteListeners(\"obj.removeEventListener('click', function foo() {})\"));\n// => Walkabout.removeEventListener(obj, 'click', function foo() {})\n\nprint(Walkabout.rewriteListeners(\"Walkabout.removeEventListener(obj, 'click', function foo() {})\"));\n// => Walkabout.removeEventListener(obj, 'click', function foo() {})\n\nprint(Walkabout.rewriteListeners(\"obj.value = 'foo'\"));\n// => obj.value = 'foo'\n"
  },
  {
    "path": "togetherjs/libs/walkabout/traverse-rewrite.js",
    "content": "const fs = require(\"fs\");\nconst walkabout = require(__dirname + \"/walkabout.js\");\nconst path = require(\"path\");\n\nvar optionAliases = {\n  n: \"simulate\",\n  h: \"help\"\n};\n\nvar listOptions = {\n  exclude: true,\n  \"extra-js\": true,\n  \"copy-file\": true\n};\n\nfunction main() {\n  var args = [];\n  var options = [];\n  for (var i=2; i<process.argv.length; i++) {\n    var arg = process.argv[i];\n    if (arg.indexOf('-') === 0) {\n      var value, name;\n      arg = arg.substr(1);\n      if (arg.indexOf('-') === 0) {\n        arg = arg.substr(1);\n        if (arg.indexOf('=') != -1) {\n          value = arg.substr(arg.indexOf('=')+1);\n          name = arg.substr(0, arg.indexOf('='));\n        } else {\n          value = true;\n          name = arg;\n        }\n      } else {\n        value = arg.substr(1) || true;\n        name = arg.charAt(0);\n      }\n      name = optionAliases[name] || name;\n      if (listOptions[name]) {\n        if (name in options) {\n          options[name].push(value);\n        } else {\n          options[name] = [value];\n        }\n      } else {\n        options[name] = value;\n      }\n    } else {\n      if (! fs.existsSync(arg)) {\n        console.log(\"File does not exist:\", arg);\n        process.exit(1);\n      }\n      args.push(arg);\n    }\n  }\n  if (options.help) {\n    help();\n    return;\n  }\n  if (options.exclude) {\n    options.exclude = options.exclude.map(function (r) {return new RegExp(r);});\n  }\n  options[\"copy-file\"] = options[\"copy-file\"] || [];\n  options[\"copy-file\"] = options[\"copy-file\"].map(function (f) {\n    var pos = f.indexOf(\":\");\n    if (pos == -1) {\n      throw \"--copy-file=\" + f + \" has no :\";\n    }\n    var name = f.substr(0, pos);\n    var filename = f.substr(pos+1);\n    if (! fs.existsSync(filename)) {\n      throw \"--copy-file=\" + f + \" does not exist\";\n    }\n    return {name: name, filename: filename};\n  });\n  if (options.copy) {\n    options[\"copy-file\"].push({\n      name: \"walkabout.js\",\n      filename: path.join(__dirname, \"walkabout.js\")\n    });\n  }\n  if (options.simulate) {\n    console.log(\"Simulating (not writing)\");\n  }\n  if (! options['no-js']) {\n    if ((! options[\"script\"]) && (! options[\"copy\"])) {\n      console.log(\"You must provide --script=URL to rewrite Javascript\");\n      process.exit(1);\n    }\n    rewriteJavascript(options, args);\n  }\n  if (! options['no-html']) {\n    rewriteHtml(options, args);\n  }\n}\n\nfunction help() {\n  console.log(\n\"Usage: \" + process.argv[0] + \" \" + path.basename(process.argv[1]) + \" --script=URL [OPTIONS] DIRS\\n\" +\n\"  Rewrites .js and .html files for walkabout.js\\n\" +\n\"  Options:\\n\" +\n\"    DIRS: \\n\" +\n\"      directories to look for files in\\n\" +\n\"    -h --help:\\n\" +\n\"      this help\\n\" +\n\"    --script=URL\\n\" +\n\"      the URL of walkabout.js to inject into HTML files\\n\" +\n\"    -n --simulate\\n\" +\n\"      Don't actually write or change files\\n\" +\n\"    --copy\\n\" +\n\"      Copy walkabout.js into each directory with HTML files\\n\" +\n\"    --exclude=REGEX\\n\" +\n\"      Exclude any files whose FULL PATH matches the regular expression\\n\" +\n\"    --extra-js=CODE\\n\" +\n\"      Include extra code at the beginning of each file (after walkabout.js)\\n\" +\n\"    --copy-file=FILENAME:LOCATION\\n\" +\n\"      As well as walkabout.js, also copy the file in LOCATION to FILENAME\\n\"\n);\n}\n\nfunction rewriteJavascript(options, dirs) {\n  var files = findFiles(dirs, '.js', options.exclude, options[\"copy-file\"]);\n  files.forEach(function (f) {\n    var content = fs.readFileSync(f, \"UTF-8\");\n    try {\n      var newContent = walkabout.rewriteListeners(content);\n    } catch (e) {\n      console.warn(\"Error parsing:\", f);\n      throw e;\n    }\n    if (content === newContent) {\n      console.log(\"File not changed:\", f);\n      return;\n    }\n    console.log(\"Changing:\", f);\n    if (! options.simulate) {\n      fs.writeFileSync(f, newContent, \"UTF-8\");\n    }\n  });\n}\n\nfunction rewriteHtml(options, dirs) {\n  var extra = options[\"extra-js\"] && options[\"extra-js\"].join(\"\");\n  var files = findFiles(dirs, \".html\", options.exclude, options[\"copy-file\"]);\n  var script = options.script;\n  if (options.copy) {\n    script = \"walkabout.js\";\n  }\n  var writtenDirs = {};\n  files.forEach(function (f) {\n    var content = fs.readFileSync(f, \"UTF-8\");\n    var newContent = walkabout.rewriteHtml(content, script, extra);\n    if (content === newContent) {\n      console.log(\"File not changed:\", f);\n    } else {\n      console.log(\"Changing:\", f);\n      if (! options.simulate) {\n        fs.writeFileSync(f, newContent, \"UTF-8\");\n      }\n    }\n    var dir = path.dirname(f);\n    if (! writtenDirs[dir]) {\n      writtenDirs[dir] = true;\n      options[\"copy-file\"].forEach(function (c) {\n        var filePath = path.join(dir, c.name);\n        if (fs.existsSync(filePath)) {\n          console.log(\"File exists:\", filePath);\n        } else {\n          console.log(\"Linking\", c.filename, \"to\", filePath);\n          if (! options.simulate) {\n            fs.symlinkSync(path.resolve(c.filename), filePath);\n          }\n        }\n      });\n    }\n  });\n}\n\nfunction findFiles(dirs, ext, excludes, copied, files) {\n  files = files || [];\n  dirs.forEach(function (d) {\n    fs.readdirSync(d).forEach(function (f) {\n      if (f == \"walkabout.js\") {\n        return;\n      }\n      if (copied) {\n        var found = false;\n        copied.forEach(function (c) {\n          if (f == c.name) {\n            found = true;\n          }\n        });\n        if (found) {\n          return;\n        }\n      }\n      f = path.join(d, f);\n      if (fs.statSync(f).isDirectory()) {\n        findFiles([f], ext, excludes, copied, files);\n        return;\n      }\n      if (path.extname(f) != ext) {\n        return;\n      }\n      if (exclude(excludes, f)) {\n        return;\n      }\n      files.push(f);\n    });\n  });\n  return files;\n}\n\nfunction exclude(excludes, filename) {\n  if (! excludes) {\n    return false;\n  }\n  for (var i=0; i<excludes.length; i++) {\n    if (filename.search(excludes[i]) != -1) {\n      return true;\n    }\n  }\n  return false;\n}\n\nif (require.main == module) {\n  main();\n}\n"
  },
  {
    "path": "togetherjs/libs/walkabout/walkabout.js",
    "content": "(function () {function init(Walkabout) {\n\nWalkabout = Walkabout || {};\n\n// FIXME: this shouldn't be established so early, in case jquery\n// is loaded after walkabout.js\nWalkabout.jQueryAvailable = (typeof jQuery !== \"undefined\");\nWalkabout.$ = window.jQuery;\n\n// Actions must turn this on in order to patch .value/.val():\nWalkabout.inTesting = false;\n\n// These are events that we don't need to fire directly:\nWalkabout.ignoreEvents = {\n  hashchange: true\n};\n\nWalkabout.options = {\n  anyLocalLinks: false,\n  loadPersistent: false\n};\n\nWalkabout.setInTesting = function setInTesting(func, time) {\n  return function run() {\n    time = time || 0;\n    var id = setInTesting.count++;\n    Walkabout.inTesting = id;\n    var result;\n    try {\n      result = func.apply(this, arguments);\n    } catch (e) {\n      if (Walkabout.inTesting == id) {\n        Walkabout.inTesting = false;\n      }\n      throw e;\n    }\n    if (time == -1) {\n      if (Walkabout.inTesting == id) {\n        Walkabout.inTesting = false;\n      }\n    } else {\n      setTimeout(function () {\n        if (Walkabout.inTesting == id) {\n          Walkabout.inTesting = false;\n        }\n      }, time);\n    }\n    return result;\n  };\n};\n\nWalkabout.setInTesting.count = 1;\n\n/****************************************\n * Utility functions:\n */\n\nWalkabout._extend = function (obj, props) {\n  for (var a in props) {\n    if (! props.hasOwnProperty(a)) {\n      continue;\n    }\n    obj[a] = props[a];\n  }\n};\n\nWalkabout.Class = function Class(prototype) {\n  return function () {\n    var obj = Object.create(prototype);\n    prototype.constructor.apply(obj, arguments);\n    return obj;\n  };\n};\n\n/****************************************\n * Actions\n */\n\nWalkabout.actionFinders = [];\n\nWalkabout.findActions = function (el, actions) {\n  el = el || document;\n  actions = actions || new Walkabout.Actions();\n  if (! (Array.isArray(el) ||\n         (Walkabout.jQueryAvailable && el instanceof Walkabout.$))) {\n    el = [el];\n  }\n  for (var i=0; i<el.length; i++) {\n    for (var j=0; j<Walkabout.actionFinders.length; j++) {\n      var finder = Walkabout.actionFinders[j];\n      finder(el[i], actions);\n    }\n  }\n  return actions;\n};\n\nWalkabout.ignoreElement = function (el) {\n  // FIXME: should probably make this pluggable as well\n  // Also, I should unjQueryfy .is(\":visible\") and put it here\n  while (el) {\n    if (el.getAttribute && el.getAttribute(\"data-walkabout-disable\")) {\n      return true;\n    }\n    el = el.parentNode;\n  }\n  return false;\n};\n\nWalkabout.DEFAULT_TIMES = 100;\n\nWalkabout.runManyActions = function runManyActions(options) {\n  options = options || {};\n  var el = options.element || document;\n  var speed = options.speed || 100;\n  var whileTrue = options.whileTrue || null;\n  var ondone = options.ondone;\n  var onstatus = options.onstatus;\n  var cancelled = false;\n  var totalTimes = options.times;\n  var remaining;\n  function cancel() {\n    cancelled = true;\n  }\n  if ((! whileTrue) && ! totalTimes) {\n    totalTimes = Walkabout.DEFAULT_TIMES;\n  }\n  if (options.startAtRemaining) {\n    remaining = options.startAtRemaining;\n  } else {\n    remaining = totalTimes;\n  }\n  function runOnce() {\n    var doAgain = ! cancelled;\n    if (whileTrue && (! whileTrue())) {\n      doAgain = false;\n    }\n    if (totalTimes !== undefined && remaining <= 0) {\n      doAgain = false;\n    }\n    if (doAgain) {\n      setTimeout(runOnce, speed);\n    }\n    if (totalTimes !== undefined) {\n      remaining--;\n    }\n    var actions = Walkabout.findActions(el);\n    var action = actions.pick();\n    if (onstatus) {\n      onstatus({\n        actions: actions,\n        action: action,\n        times: totalTimes,\n        remaining: remaining\n      });\n    }\n    if ((! doAgain) && ondone) {\n      ondone();\n      return;\n    }\n    if (action) {\n      action.run();\n    }\n  }\n  setTimeout(runOnce, speed);\n  return cancel;\n};\n\nWalkabout.persistentData = function (value) {\n  var key = \"walkabout.runstate\";\n  if (value === undefined) {\n    value = localStorage.getItem(key);\n    if (value) {\n      value = JSON.parse(value);\n    } else {\n      value = {};\n    }\n    return value;\n  }\n  if (value === null) {\n    localStorage.removeItem(key);\n  } else {\n    localStorage.setItem(key, JSON.stringify(value));\n  }\n  return value;\n};\n\nWalkabout.actionFinders.push(function findAnchors(el, actions) {\n  var els = el.querySelectorAll(\"a\");\n  for (var i=-1; i<els.length; i++) {\n    var anchor = i == -1 ? el : els[i];\n    if (anchor.tagName != \"A\" ||\n        Walkabout.ignoreElement(anchor)) {\n      continue;\n    }\n    if (actions.matchingAction(\"click\", anchor)) {\n      continue;\n    }\n    if (! Walkabout.clickable(anchor)) {\n      continue;\n    }\n    var href;\n    if (Walkabout.options.anyLocalLinks) {\n      href = anchor.href;\n      var here = location.protocol + \"//\" + location.host;\n      if (typeof Walkabout.options.anyLocalLinks == \"string\") {\n        if (Walkabout.options.anyLocalLinks.indexOf(\"/\") !== 0) {\n          here += \"/\";\n        }\n        here += Walkabout.options.anyLocalLinks;\n      }\n      if (href.indexOf(here) !== 0) {\n        continue;\n      }\n    } else {\n      href = anchor.getAttribute(\"href\");\n      if ((! href) || href.indexOf(\"#\") !== 0) {\n        continue;\n      }\n    }\n    actions.push(Walkabout.LinkFollower({\n      element: anchor,\n      type: \"click\"\n    }));\n  }\n});\n\nWalkabout.actionFinders.push(function findEdits(el, actions) {\n  var children = el.getElementsByTagName(\"*\");\n  for (var i=-1; i<children.length; i++) {\n    var e = i == -1 ? el : children[i];\n    var attr = e.getAttribute && e.getAttribute(\"data-walkabout-edit-value\");\n    if (attr) {\n      var types = attr.split(/ /g);\n      for (var j=0; j<types.length; j++) {\n        var type = types[j];\n        if (type == \"type\") {\n          actions.push(Walkabout.Typer(e, \"type\"));\n        } else if (type == \"paste\") {\n          actions.push(Walkabout.Typer(e, \"paste\"));\n        } else if (type == \"delete\") {\n          if (e.value) {\n            actions.push(Walkabout.Deleter(e));\n          }\n        } else if (type == \"move\") {\n          if (e.value) {\n            actions.push(Walkabout.Mover(e));\n          }\n        //} else if (type == \"change\") {\n        //  actions.push(Walkabout.Changer(e));\n        } else if (type) {\n          console.warn('Unexpected data-walkabout-edit-value=\"' + type + '\"');\n        }\n      }\n    }\n  }\n});\n\nWalkabout.Typer = Walkabout.Class({\n  constructor: function Typer(element, kind) {\n    this.element = element;\n    this.kind = kind;\n  },\n\n  show: function () {\n    return Walkabout.Highlighter(this.element, \"type\");\n  },\n\n  description: function () {\n    return (this.kind == \"type\" ? \"Type\" : \"Paste\") +\n      \" into \" + Walkabout.elementDescription(this.element);\n  },\n\n  run: Walkabout.setInTesting(function () {\n    var e = this.element;\n    var value = e.value;\n    // First we save the location of the cursor:\n    e.focus();\n    var startPos = e.selectionStart;\n    var endPos = e.selectionEnd;\n    var r = Walkabout.random;\n    var length = 1;\n    if (this.kind == \"paste\") {\n      length = Math.floor(r() * 20);\n    }\n    var key = r.string(r.letters + r.numbers + r.punctuation + r.whitespace, length);\n    var start = value.substr(0, startPos);\n    var end = value.substr(endPos);\n    e.value = start + key + end;\n    // If we had a selection, we lost when typing:\n    e.selectionStart = e.selectionEnd = startPos + key.length;\n    // FIXME: should probably also do keydown, keypress, in sequence\n    // FIXME: should set the right keyCode/etc value\n    var keyup = Walkabout.EventAction({\n      element: e,\n      type: this.kind == \"type\" ? \"keyup\" : \"paste\",\n      handler: null, // FIXME: figure out if there's a handler?\n      jQuery: Walkabout.jQueryAvailable\n    });\n    keyup.run();\n  })\n\n});\n\nWalkabout.Deleter = Walkabout.Class({\n  constructor: function Deleter(element) {\n    this.element = element;\n  },\n\n  show: function () {\n    return Walkabout.Highlighter(this.element, \"delete from\");\n  },\n\n  description: function () {\n    return \"Delete from \" + Walkabout.elementDescription(this.element);\n  },\n\n  run: Walkabout.setInTesting(function () {\n    var length;\n    var e = this.element;\n    var value = e.value;\n    e.focus();\n    var startPos = e.selectionStart;\n    var endPos = e.selectionEnd;\n    if (startPos != endPos) {\n      // If there's a selection, delete that...\n      e.value = value.substr(0, startPos) + value.substr(endPos);\n      e.selectionStart = e.selectionEnd = startPos;\n    } else {\n      // We can delete after or before...\n      var canStart = startPos > 0;\n      // FIXME: I'm off by one here I think:\n      var canEnd = startPos < value.length;\n      if (canStart && canEnd && Walkabout.random() < 0.5) {\n        canStart = false;\n      }\n      if (canStart) {\n        length = Math.floor(Walkabout.random() * startPos);\n        e.value = value.substr(0, startPos - length) + value.substr(startPos);\n        e.selectionStart = e.selectionEnd = startPos - length;\n      } else {\n        length = Math.floor(Walkabout.random() * (value.length - startPos));\n        e.value = value.substr(0, startPos) + value.substr(startPos + length);\n        e.selectionStart = e.selectionEnd = startPos;\n      }\n    }\n    // FIXME: should set the right keyCode/etc value:\n    // FIXME: also keydown?  Or keypress?\n    var keyup = Walkabout.EventAction({\n      element: e,\n      type: \"keyup\",\n      handler: null, // FIXME: figure out if there's a handler?\n      jQuery: Walkabout.jQuerySupported\n    });\n    keyup.run();\n  })\n});\n\nWalkabout.Mover = Walkabout.Class({\n  constructor: function Mover(element) {\n    this.element = element;\n  },\n\n  show: function () {\n    return Walkabout.Highlighter(this.element, \"move cursor\");\n  },\n\n  description: function () {\n    return \"Move cursor in \" + Walkabout.elementDescription(this.element);\n  },\n\n  run: Walkabout.setInTesting(function () {\n    var e = this.element;\n    var value = e.value;\n    e.focus();\n    var pos = Math.floor(Walkabout.random() * value.length);\n    e.selectionStart = e.selectionEnd = pos;\n  })\n});\n\n\n/****************************************\n * jQuery support:\n */\n\nif (Walkabout.jQueryAvailable) {\n\n  Walkabout.$.fn.bindKey = function (matcher, arg1, arg2, arg3) {\n    var callback = arg3 || arg2 || arg1;\n    function handler(event) {\n      if (matcher.which) {\n        if (typeof matcher.which == \"number\" && event.which != matcher.which) {\n          return;\n        }\n        if (typeof matcher.which == \"object\" && typeof matcher.which.length == \"number\") {\n          if (matcher.which.indexOf(event.which) == -1) {\n            return;\n          }\n        }\n      }\n      // FIXME: I think this only makes sense for keypress\n      if ((matcher.shiftKey && ! event.shiftKey) ||\n          (matcher.ctrlKey && ! event.ctrlKey) ||\n          (matcher.altKey && ! event.altKey)) {\n        return;\n      }\n      callback.call(this, event);\n    }\n    matcher.type = matcher.type || \"keypress\";\n    handler.matcher = matcher;\n    handler.element = this;\n    handler.runEvent = function () {\n      var key = this.matcher.which;\n      if (typeof key == \"object\" && typeof key.length == \"number\") {\n        key = Walkabout.random.pick(key);\n      }\n      var event = Walkabout.$.Event(matcher.type);\n      event.which = key;\n      this.element.trigger(event);\n    };\n    var args = [matcher.type];\n    if (arg2) {\n      args.push(arg1);\n    }\n    if (arg3) {\n      args.push(arg2);\n    }\n    args.push(handler);\n    this.on.apply(this, args);\n  };\n\n  Walkabout.actionFinders.push(function jQueryHandlers(el, actions) {\n    var els = Walkabout.$(el).find(\"*\");\n    els.push(el);\n    els.each(function () {\n      if (Walkabout.ignoreElement(this)) {\n        return;\n      }\n      if (! Walkabout.clickable(this)) {\n        // FIXME: not sure if this is right for all kinds of events, or just click?\n        return;\n      }\n      var events;\n      if (Walkabout.$._data) {\n        // This is for jQuery 1.8+\n        events = Walkabout.$._data(this, \"events\");\n      } else {\n        // For older versions\n        events = Walkabout.$(this).data(\"events\");\n      }\n      if (! events) {\n        return;\n      }\n      for (var eventName in events) {\n        if ((! events.hasOwnProperty(eventName)) || Walkabout.ignoreEvents[eventName]) {\n          continue;\n        }\n        for (var i=0; i<events[eventName].length; i++) {\n          var event = events[eventName][i];\n          var els = [this];\n          if (event.selector) {\n            els = Walkabout.$(this).find(event.selector);\n          }\n          for (var j=0; j<els.length; j++) {\n            var action = Walkabout.EventAction({\n              element: els[j],\n              type: eventName,\n              handler: event.handler,\n              jQuery: true\n            });\n            // Prefer the jQuery form of the action\n            var existing = actions.matchingAction(eventName, els[j]);\n            if (existing) {\n              actions.replaceAction(existing, action);\n            } else {\n              actions.push(action);\n            }\n          }\n        }\n      }\n    });\n  });\n\n  Walkabout.$.fn.val.patch = function () {\n    Walkabout.$.fn.val = Walkabout.$.fn.val.mock;\n  };\n\n  Walkabout.$.fn.val.mock = function () {\n    if ((! Walkabout.inTesting) || this.attr(\"type\") == \"hidden\") {\n      return Walkabout.$.fn.val.mock.orig.apply(this, arguments);\n    }\n    var options = this.attr(\"data-walkabout-options\");\n    if (options) {\n      options = eval(\"(\" + options + \")\");\n    } else {\n      options = Walkabout.random.letters;\n    }\n    if (Array.isArray(options)) {\n      return Walkabout.random.pick(options);\n    } else if (typeof options == \"function\") {\n      return options(this);\n    } else if (typeof options == \"string\") {\n      var size = parseInt(this.attr(\"size\") || 10, 10);\n      size = Math.floor(Walkabout.random() * size);\n      return Walkabout.random.string(options, size);\n    } else {\n      // FIXME: what then?  E.g., if it's an object\n      return Walkabout.$.fn.val.mock.orig.apply(this, arguments);\n    }\n  };\n\n  Walkabout.$.fn.val.mock.patch = function () {\n    // Already patched\n  };\n\n  Walkabout.$.fn.val.mock.unpatch = function () {\n    Walkabout.$.fn.val = jQuery.fn.val.mock.orig;\n  };\n\n  Walkabout.$.fn.val.mock.orig = Walkabout.$.fn.val;\n  Walkabout.$.fn.val.mock.mock = Walkabout.$.fn.val.mock;\n\n  Walkabout.$.fn.findActions = function () {\n    return Walkabout.findActions(this);\n  };\n\n}\n\n\n/****************************************\n * Action implementations:\n */\n\nWalkabout.Highlighter = Walkabout.Class({\n  constructor: function (element, text) {\n    this.element = element;\n    this.text = text;\n    this.show();\n  },\n\n  OUTER: 8,\n\n  sizeOffsets: [-2, 0, 2],\n  sizeOffsetIndex: 0,\n\n  show: function () {\n    var box = this.element.getBoundingClientRect();\n    var middleX = Math.floor((box.left + box.right) / 2);\n    var middleY = Math.floor((box.top + box.bottom) / 2);\n    var h = document.createElement(\"div\");\n    // This is an attempt to make\n    outer = this.OUTER + this.sizeOffsets[this.sizeOffsetIndex];\n    var newSize = this.sizeOffsetIndex++;\n    if (newSize >= this.sizeOffsets.length) {\n      newSize = 0;\n    }\n    Walkabout.Highlighter.prototype.sizeOffsetIndex = newSize;\n    var outer = this.OUTER + Math.floor(Math.random() * 4);\n    h.style.position = \"absolute\";\n    h.style.zIndex = 1000;\n    h.style.border = \"2px dotted #f00\";\n    h.style.borderRadius = outer + \"px\";\n    h.style.left = middleX + \"px\";\n    h.style.top = middleY + \"px\";\n    h.style.marginTop = (-box.height/2 - (outer/2)) + \"px\";\n    h.style.marginLeft = (-box.width/2 - (outer/2)) + \"px\";\n    h.style.width = (box.width + outer) + \"px\";\n    h.style.height = (box.height + outer) + \"px\";\n    h.style.textAlign = \"center\";\n    //h.style.verticalAlign = \"center\";\n    h.setAttribute(\"data-walkabout-disable\", \"1\");\n    h.appendChild(document.createTextNode(this.text));\n    h.addEventListener(\"click\", this.remove.bind(this), false);\n    document.body.appendChild(h);\n    this.highlightElement = h;\n  },\n\n  remove: function () {\n    var h = this.highlightElement;\n    if (h) {\n      h.parentNode.removeChild(h);\n      this.highlightElement = null;\n    }\n  }\n\n});\n\nWalkabout.Notifier = Walkabout.Class({\n\n  constructor: function (message) {\n    this.message = message;\n    this.show();\n  },\n\n  container: function () {\n    var id = \"walkabout-notifier-container\";\n    var el = document.getElementById(id);\n    if (el) {\n      return el;\n    }\n    el = document.createElement(\"div\");\n    el.id = id;\n    el.setAttribute(\"style\", Walkabout.UI.prototype.styles.panel);\n    el.style.right = \"\";\n    el.style.left = \"10px\";\n    el.setAttribute(\"data-walkabout-disable\", \"1\");\n    document.body.append(el);\n    return el;\n  },\n\n  show: function () {\n    var c = this.container();\n    var el = document.createElement(\"div\");\n    el.appendChild(document.createTextNode(this.message));\n    el.addEventListener(\"click\", (function () {\n      this.remove();\n    }).bind(this));\n    c.appendChild(el);\n    this._element = el;\n  },\n\n  remove: function () {\n    var el = this._element;\n    if (! el) {\n      return;\n    }\n    var parent = el.parentNode;\n    parent.removeChild(el);\n    if (! parent.childNodes.length) {\n      parent.parentNode.removeChild(parent);\n    }\n  }\n\n});\n\nWalkabout.elementDescription = function (el, isJQuery) {\n  var name;\n  if (el.id) {\n    name = el.tagName.toLowerCase() + \"#\" + el.id;\n  } else {\n    name = el.tagName.toLowerCase();\n    var all = document.getElementsByTagName(name);\n    for (var i=0; i<all.length; i++) {\n      if (all[i] == el) {\n        name += \"[\" + i + \"]\";\n        break;\n      }\n    }\n    if (el.className) {\n      name += \".\" + el.className.replace(/\\s+/, \".\");\n    }\n  }\n  if (isJQuery) {\n    name = '$(\"' + name + '\")';\n  }\n  return name;\n};\n\nWalkabout.EventAction = Walkabout.Class({\n\n  constructor: function EventAction(event) {\n    this.element = event.element;\n    this.type = event.type;\n    this.handler = event.handler;\n    this.options = event.options || {};\n    this.jQuery = !! event.jQuery;\n  },\n\n  show: function () {\n    var name = this.type;\n    if (this.jQuery) {\n      name = '$.' + this.type + '()';\n    }\n    return Walkabout.Highlighter(this.element, name);\n  },\n\n  description: function () {\n    var s;\n    var elName = Walkabout.elementDescription(this.element, this.jQuery);\n    if (this.jQuery) {\n      s = elName + \".\" + this.type + \"()\";\n    } else {\n      s = \"Fire \" + this.type + \" on \" + elName;\n    }\n    return s;\n  },\n\n  run: Walkabout.setInTesting(function run() {\n    var event;\n    var props = this.eventProperties();\n    if (props.before == \"randomValue\") {\n      if (Walkabout.jQueryAvailable) {\n        Walkabout.$(this.element).val(Walkabout.value(this.element));\n      } else {\n        this.element.value = Walkabout.value(this.element);\n      }\n    }\n    if (this.handler && this.handler.runEvent) {\n      this.handler.runEvent();\n    } else if (Walkabout.jQueryAvailable) {\n      event = Walkabout.$.Event(this.type);\n      Walkabout._extend(event, props);\n      if ((this.type == \"keyup\" || this.type == \"keydown\" || this.type == \"keypress\") &&\n          (! event.which)) {\n        var normalKeys = [13, 9, 32];\n        if (Walkabout.random() > 0.4) {\n          event.which = Walkabout.random.pick(normalKeys);\n        } else {\n          event.which = Math.floor(Walkabout.random() * 256);\n        }\n        event.keyCode = event.which;\n      }\n      Walkabout.$(this.element).trigger(event);\n    } else {\n      var module = Walkabout._getEventModule(this.type);\n      event = document.createEvent(module);\n      if (module == \"UIEvents\") {\n        event.initUIEvent(\n          this.type,\n          props.get(\"canBubble\", true), // canBubble\n          props.get(\"cancelable\", true), // cancelable\n          window, // view\n          props.get(\"detail\", 0) // detail\n        );\n      } else if (module == \"MouseEvents\" || module == \"MouseEvent\") {\n        event.initMouseEvent(\n          this.type,\n          props.get(\"canBubble\", true), // canBubble\n          props.get(\"cancelable\", true), // cancelable\n          window, // view\n          props.get(\"detail\", 0), // detail\n          props.get(\"screenX\", 0), // screenX\n          props.get(\"screenY\", 0), // screenY\n          props.get(\"clientX\", 0), // clientX\n          props.get(\"clientY\", 0), // clientY\n          props.get(\"ctrlKey\", false), // ctrlKey\n          props.get(\"altKey\", false), // altKey\n          props.get(\"shiftKey\", false), // shiftKey\n          props.get(\"metaKey\", false), // metaKey\n          props.get(\"button\", 0), // button\n          props.get(\"relatedTarget\", null) // relatedTarget\n        );\n      } else if (module == \"HTMLEvents\") {\n        event.initEvent(\n          this.type,\n          props.get(\"canBubble\", false), // canBubble\n          props.get(\"cancelable\", false) // cancelable\n        );\n      } else if (module == \"KeyboardEvents\" || module == \"KeyboardEvent\") {\n        var keyCode = props.get(\"keyCode\", props.get(\"which\", props.get(\"charCode\", null)));\n        var charCode = null;\n        if (typeof keyCode == \"string\") {\n          charCode = keyCode;\n          keyCode = charCode.charCodeAt(0);\n        }\n        if (! keyCode) {\n          keyCode = Math.floor(Walkabout.random() * 256);\n        }\n        if (! charCode) {\n          charCode = String.fromCharCode(keyCode);\n        }\n        if (event.initKeyEvent) {\n          event.initKeyEvent(\n            this.type,\n            props.get(\"canBubble\", true), // canBubble\n            props.get(\"cancelable\", true), // cancelable\n            window, // window\n            props.get(\"ctrlKey\", false), // ctrlKey\n            props.get(\"altKey\", false), // altKey\n            props.get(\"shiftKey\", false), // shiftKey\n            props.get(\"metaKey\", false), // metaKey\n            keyCode, // keyCode/which\n            charCode // charCode\n          );\n        } else {\n          // initKeyboardEvent seems pretty broken\n          event = {\n            type: this.type,\n            target: this.element,\n            altKey: props.get(\"altKey\", false),\n            \"char\": charCode,\n            ctrlKey: props.get(\"ctrlKey\", false),\n            keyCode: keyCode,\n            locale: \"\",\n            location: props.get(\"location\", 0),\n            metaKey: props.get(\"metaKey\", false),\n            repeat: props.get(\"repeat\", false),\n            shiftKey: props.get(\"shiftKey\", false),\n            which: keyCode,\n            isDefaultPrevented: false,\n            preventDefault: function () {\n              this.isDefaultPrevented = true;\n            },\n            stopPropagation: function () {\n              // FIXME: not sure what to do here\n            }\n          };\n          this.handler(event);\n          // FIXME: pay attention to isDefaultPrevented?\n          // FIXME: do default?\n          return;\n          /*\n          FIXME: this is broken on Chrome:\n\n          var mods = [];\n          if (props.ctrlKey) {\n            mods.push(\"Control\");\n          }\n          if (props.altKey) {\n            mods.push(\"Alt\");\n          }\n          if (props.shiftKey) {\n            mods.push(\"Shift\");\n          }\n          if (props.metaKey) {\n            mods.push(\"Meta\");\n          }\n          mods = mods.join(\" \") || null;\n          event.initKeyboardEvent(\n            this.event.type,\n            props.get(\"canBubble\", true), // canBubble\n            props.get(\"cancelable\", true), // cancelable\n            window,\n            'Enter',\n            0, // location? http://msdn.microsoft.com/en-us/library/ie/ff974894(v=vs.85).aspx\n            mods, // modifer keys\n            props.get(\"repeat\", false), // repeat\n            null // locale\n          );\n          */\n        }\n      } else {\n        console.warn(\"Unknown method type/module:\", module, this.type);\n      }\n      Walkabout._extend(event, props);\n      this.element.dispatchEvent(event);\n    }\n  }),\n\n  eventProperties: function () {\n    var attrs = this.element.attributes;\n    var attrName = \"data-walkabout-\" + this.type;\n    var result = Object.create(this._eventPropsPrototype);\n    if (! attrs) {\n      return result;\n    }\n    for (var i=0; i<attrs.length; i++) {\n      if (attrs[i].name == attrName) {\n        var data;\n        try {\n          data = JSON.parse(attrs[i].value);\n        } catch (e) {\n        }\n        if (data === undefined) {\n          try {\n            data = eval(\"(\" + attrs[i].value + \")\");\n          } catch (e) {\n            console.warn(\"Bad attribute\", attrs[i].name, JSON.stringify(attrs[i].value));\n            continue;\n          }\n        }\n        Walkabout._extend(result, data);\n      }\n    }\n    return result;\n  },\n\n  _eventPropsPrototype: {\n    get: function (name, default_) {\n      if (this.hasOwnProperty(name)) {\n        return this[name];\n      } else {\n        return default_;\n      }\n    }\n  }\n\n});\n\nWalkabout._getEventModule = function (type) {\n  var modules = {\n    click: \"MouseEvent\",\n    dblclick: \"MouseEvent\",\n    mousedown: \"MouseEvent\",\n    mouseenter: \"MouseEvent\",\n    mouseleave: \"MouseEvent\",\n    mouseup: \"MouseEvent\",\n    mouseover: \"MouseEvent\",\n    mousemove: \"MouseEvent\",\n    mouseout: \"MouseEvent\",\n    load: \"HTMLEvents\",\n    unload: \"HTMLEvents\",\n    abort: \"HTMLEvents\",\n    error: \"HTMLEvents\",\n    select: \"HTMLEvents\",\n    change: \"HTMLEvents\",\n    submit: \"HTMLEvents\",\n    reset: \"HTMLEvents\",\n    focus: \"HTMLEvents\",\n    blur: \"HTMLEvents\",\n    resize: \"HTMLEvents\",\n    scroll: \"HTMLEvents\",\n    DOMFocusIn: \"UIEvents\",\n    DOMFocusOut: \"UIEvents\",\n    DOMActivate: \"UIEvents\",\n    keydown: \"KeyboardEvent\",\n    keyup: \"KeyboardEvent\",\n    keypress: \"KeyboardEvent\"\n  };\n  // Where should these go?\n  //   http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents\n  // This claims HTMLEvents should be UIEvents\n  //   http://www.w3.org/TR/DOM-Level-3-Events/#events-uievents\n  return modules[type] || \"UIEvents\";\n};\n\nWalkabout.LinkFollower = Walkabout.Class({\n  constructor: function LinkFollower(event) {\n    this.element = event.element;\n    this.type = event.type;\n    if (this.type != \"click\") {\n      throw \"Unexpected event type: \" + this.type;\n    }\n    this.options = event.options || {};\n  },\n\n  show: function () {\n    return Walkabout.Highlighter(this.element, \"follow\");\n  },\n\n  run: Walkabout.setInTesting(function () {\n    var event;\n    var cancelled;\n    if (Walkabout.jQueryAvailable) {\n      event = Walkabout.$.Event(\"click\");\n      Walkabout.$(this.element).trigger(event);\n      cancelled = event.isDefaultPrevented();\n    } else {\n      event = document.createEvent(\"MouseEvents\");\n      event.initMouseEvent(\n        \"click\", // type\n        true, // canBubble\n        true, // cancelable\n        window, // view\n        0, // detail\n        0, // screenX\n        0, // screenY\n        0, // clientX\n        0, // clientY\n        false, // ctrlKey\n        false, // altKey\n        false, // shiftKey\n        false, // metaKey\n        0, // button\n        null // relatedTarget\n      );\n      cancelled = this.element.dispatchEvent(event);\n    }\n    if ((! cancelled) && ! (event.defaultPrevented)) {\n      location.href = this.element.getAttribute(\"href\");\n    }\n  })\n});\n\nWalkabout.hidden = function (el) {\n  return (el.offsetWidth === 0 &&\n          el.offsetHeight === 0);\n  // FIXME: jQuery also uses a display: none test on some browsers,\n  // but this seems to be the only check for modern browsers?\n};\n\nWalkabout.visible = function (el) {\n  return ! Walkabout.hidden(el);\n};\n\nWalkabout.clickable = function (el) {\n  if (Walkabout.hidden(el)) {\n    return false;\n  }\n  if (Walkabout.anyOverlap(el)) {\n    return false;\n  }\n  return true;\n};\n\nWalkabout.anyOverlap = function (overElement) {\n  try {\n    var overStyle = getComputedStyle(overElement);\n  } catch (e) {\n    // FIXME: this is being called for the HTMLDocument element and other\n    // things that can't be used with getComputedStyle\n    return false;\n  }\n  if (! overStyle) {\n    return false;\n  }\n  var overZIndex = parseInt(overStyle.getPropertyValue(\"z-index\"), 10);\n  var overBox = overElement.getBoundingClientRect();\n  var overHeight = overElement.offsetHeight;\n  var overWidth = overElement.offsetWidth;\n  var els = document.getElementsByTagName(\"*\");\n  var len = els.length;\n  var result = [];\n  var parents = [];\n  var parent = overElement.parentNode;\n  while (parent) {\n    parents.push(parent);\n    parent = parent.parentNode;\n  }\n  for (var i=0; i<len; i++) {\n    var el = els[i];\n    if (el == overElement || parents.indexOf(el) != -1) {\n      continue;\n    }\n    var style = getComputedStyle(el);\n    var position = style.getPropertyValue(\"position\");\n    if (position != \"relative\" && position != \"fixed\" && position != \"absolute\") {\n      continue;\n    }\n    var zIndex = parseInt(style.getPropertyValue(\"z-index\"), 10);\n    if (zIndex <= overZIndex) {\n      continue;\n    }\n    var box = el.getBoundingClientRect();\n    if (box.left <= overBox.left &&\n        box.right >= overBox.right &&\n        box.top <= overBox.top &&\n        box.bottom >= overBox.bottom) {\n      return true;\n    }\n  }\n  return false;\n};\n\n/****************************************\n * Random numbers:\n */\n\n\n// Based on Python's whrandom\nWalkabout.RandomStream = function RandomStream(newSeed) {\n  var seed, x, y, z;\n  function setSeed(value) {\n    if (! value) {\n      value = Date.now();\n    }\n    if (typeof value != \"number\") {\n      if (value.getTime) {\n        value = value.getTime();\n      }\n      value = parseInt(value, 10);\n    }\n    if ((! value) || isNaN(value)) {\n      throw \"Bad seed: \" + value;\n    }\n    seed = value;\n    x = (seed % 30268) + 1;\n    seed = (seed - (seed % 30268)) / 30268;\n    y = (seed % 30306) + 1;\n    seed = (seed - (seed % 30306)) / 30306;\n    z = (seed % 30322) + 1;\n    seed = (seed - (seed % 30322)) / 30322;\n  }\n  setSeed(newSeed);\n  var result = function random() {\n    x = (171 * x) % 30269;\n    y = (172 * y) % 30307;\n    z = (170 * z) % 30323;\n    if (random.logState) {\n      console.log('x', x, 'y', y, 'z', z);\n    }\n    if (random.storeState) {\n      localStorage.setItem(random.storeState, JSON.stringify([x, y, z]));\n    }\n    return (x / 30269.0 + y / 30307.0 + z / 30323.0) % 1.0;\n  };\n  result.storeState = null;\n  result.setSeed = setSeed;\n  result.pick = function (array) {\n    var index = Math.floor(result() * array.length);\n    return array[index];\n  };\n  result.lowerLetters = \"abcdefghijklmnopqrstuvwxyz\";\n  result.upperLetters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n  result.letters = result.lowerLetters + result.upperLetters;\n  result.numbers = \"0123456789\";\n  result.simplePunctuation = \" _-+,./\";\n  result.extraPunctuation = \"!@#$%^&*()=`~[]{};:'\\\"\\\\|<>?\";\n  result.punctuation = result.simplePunctuation + result.extraPunctuation;\n  result.whitespace = \" \\n\";\n  result.string = function string(letters, length) {\n    letters = letters || result.letters;\n    length = length || 10;\n    var s = \"\";\n    for (var i=0; i<length; i++) {\n      s += result.pick(letters);\n    }\n    return s;\n  };\n  result.loadState = function (state) {\n    if (state === undefined && ! result.storeState) {\n      return;\n    }\n    if (state === undefined) {\n      state = localStorage.getItem(result.storeState);\n      if (state) {\n        state = JSON.parse(state);\n      } else {\n        return;\n      }\n    }\n    x = state[0];\n    y = state[1];\n    z = state[2];\n  };\n  result.clearState = function () {\n    if (! result.storeState) {\n      return;\n    }\n    localStorage.removeItem(result.storeState);\n  };\n  return result;\n};\n\nWalkabout.random = Walkabout.RandomStream();\n\n/****************************************\n * Action container:\n */\n\nWalkabout.Actions = function Actions() {\n};\n\nWalkabout.Actions.prototype = Object.create(Array.prototype);\n\nWalkabout.Actions.prototype.pick = function () {\n  return Walkabout.random.pick(this);\n};\n\nWalkabout.Actions.prototype.runAny = function () {\n  var item = this.pick();\n  item.run.apply(item, arguments);\n};\n\nWalkabout.Actions.prototype.matchingAction = function (eventName, element) {\n  for (var i=0; i<this.length; i++) {\n    var action = this[i];\n    if (action.type == eventName && action.element == element) {\n      return action;\n    }\n  }\n  return null;\n};\n\nWalkabout.Actions.prototype.replaceAction = function (action, newAction) {\n  var found = false;\n  for (var i=0; i<this.length; i++) {\n    if (this[i] === action) {\n      this[i] = newAction;\n      found = true;\n      break;\n    }\n  }\n  if (! found) {\n    throw \"Action not found: \" + action;\n  }\n};\n\nWalkabout.Actions.prototype.toSource = function () {\n  var items = [];\n  for (var i=0; i<this.length; i++) {\n    items.push(this[i].toSource().replace(/^\\(/, \"\").replace(/\\)$/, \"\"));\n  }\n  return \"new Walkabout.Actions(\" + items.join(\", \") + \")\";\n};\n\n\n/****************************************\n * Replacements for standard methods, to track or mock values:\n */\n\nWalkabout.addEventListener = function (obj, type, handler, bubbles, options) {\n  obj.addEventListener(type, handler, bubbles || false);\n  if (! obj._Walkabout_handlers) {\n    obj._Walkabout_handlers = {};\n  }\n  if (! obj._Walkabout_handlers[type]) {\n    obj._Walkabout_handlers[type] = [];\n  }\n  obj._Walkabout_handlers[type].push({\n    handler: handler,\n    bubbles: bubbles,\n    type: type,\n    options: options\n  });\n};\n\nWalkabout.removeEventListener = function (obj, type, handler, bubbles) {\n  obj.removeEventListener(type, handler, bubbles || false);\n  var handlers = obj._Walkabout_handlers;\n  if ((! handlers) || ! handlers[type]) {\n    return;\n  }\n  handlers = handlers[type];\n  for (var i=0; i<handlers.length; i++) {\n    if (handlers[i].handler === handler &&\n        handlers[i].type === type &&\n        handlers[i].bubbles === bubbles) {\n      handlers.splice(i, 1);\n      break;\n    }\n  }\n};\n\nWalkabout.actionFinders.push(function customEvents(el, actions) {\n  var els = el.getElementsByTagName(\"*\");\n  for (var i=-1; i<els.length; i++) {\n    var o = i == -1 ? el : els[i];\n    var handlers = o._Walkabout_handlers;\n    if (Walkabout.ignoreElement(o) || ! handlers) {\n      continue;\n    }\n    if (! Walkabout.clickable(o)) {\n      // FIXME: not sure if this is a good general rule\n      continue;\n    }\n    for (var eventName in handlers) {\n      if (! handlers.hasOwnProperty(eventName)) {\n        continue;\n      }\n      for (var j=0; j<handlers[eventName].length; j++) {\n        var handler = handlers[eventName][j];\n        var specific = [o];\n        if (handler.options && handler.options.selector) {\n          specific = o.querySelectorAll(handler.options.selector);\n        }\n        for (var k=0; k<specific.length; k++) {\n          actions.push(Walkabout.EventAction({\n            element: specific[k],\n            type: eventName,\n            handler: handler.handler,\n            options: handler.options\n          }));\n        }\n      }\n    }\n  }\n});\n\nWalkabout.value = function (obj) {\n  var curValue = obj.value;\n  if (! Walkabout.inTesting) {\n    return curValue;\n  }\n  if (! obj || (! obj.tagName)) {\n    return curValue;\n  }\n  if (obj.getAttribute && obj.getAttribute(\"data-walkabout-disable\")) {\n    return curValue;\n  }\n  if ((! obj.tagName) ||\n      (obj.tagName != \"INPUT\" && obj.tagName == \"TEXTAREA\" && obj.tagName == \"SELECT\")) {\n    return curValue;\n  }\n  if (obj.tagName == \"INPUT\" && Walkabout._getType(obj) == \"hidden\") {\n    return curValue;\n  }\n  var options = obj.getAttribute(\"data-walkabout-options\");\n  if (options) {\n    options = eval(\"(\" + options + \")\");\n  }\n  if ((! options) && obj.tagName == \"INPUT\" && Walkabout._getType(obj) == \"checkbox\") {\n    // FIXME: need to override .checked\n    return curValue;\n  }\n  if ((! options) && obj.tagName == \"SELECT\") {\n    var els = obj.querySelectorAll(\"option\");\n    options = [];\n    for (var i=0; i<els.length; i++) {\n      var option = els[i];\n      if (option.disabled) {\n        continue;\n      }\n      options.push(option.value);\n    }\n  }\n  // FIXME: Should check other types too\n  if (! options) {\n    options = Walkabout.random.letters;\n  }\n  if (Array.isArray(options)) {\n    return Walkabout.random.pick(options);\n  } else if (typeof options == \"function\") {\n    return options(obj);\n  } else if (typeof options == \"string\") {\n    var length = obj.getAttribute(\"size\") || 10;\n    length = parseInt(length, 10);\n    return Walkabout.random.string(options, length);\n  } else {\n    return curValue;\n  }\n};\n\nWalkabout._getType = function (obj) {\n  if ((! obj) || (! obj.getAttribute)) {\n    return null;\n  }\n  var value = obj.getAttribute(\"type\");\n  if (value) {\n    value = value.toLowerCase();\n  }\n  return value;\n};\n\nWalkabout.injectModules = function (modules) {\n  if (modules.esprima) {\n    esprima = modules.esprima;\n  }\n  if (modules.falafel) {\n    falafel = modules.falafel;\n  }\n};\n\nWalkabout.rewriteListeners = function (code) {\n  if (typeof esprima == \"undefined\") {\n    if (typeof require != \"undefined\") {\n      exprima = require(\"esprima\");\n    } else {\n      throw \"You must install or include esprima.js\";\n    }\n  }\n  if (typeof falafel == \"undefined\") {\n    if (typeof require != \"undefined\") {\n      falafel = require(\"falafel\");\n    } else {\n      throw \"You must install or include falafel.js\";\n    }\n  }\n  var result = falafel(code, function (node) {\n    if (node.type == \"CallExpression\" &&\n        node.callee && node.callee.property &&\n        (node.callee.property.name == \"addEventListener\" ||\n         node.callee.property.name == \"removeEventListener\")) {\n      if (node.callee.object.source() == \"Walkabout\") {\n        // Already fixed source\n        return;\n      }\n      var args = [];\n      node[\"arguments\"].forEach(function (n) {\n        args.push(n.source());\n      });\n      node.update(\n        \"Walkabout.\" + node.callee.property.name +\n        \"(\" + node.callee.object.source() +\n        \", \" + args.join(\", \") + \")\");\n    }\n    if (node.type == \"MemberExpression\" &&\n        (! node.computed) &&\n        node.property && node.property.name == \"value\" &&\n        node.parent && node.parent.type != \"AssignmentExpression\") {\n      if (node.object.source() == \"Walkabout\") {\n        // Already fixed\n        return;\n      }\n      node.update(\n        \"Walkabout.value(\" + node.object.source() + \")\");\n    }\n  });\n  return result.toString();\n};\n\nWalkabout.rewriteHtml = function (code, scriptLocation, extra) {\n  var start, rest;\n  extra = extra || \"\";\n  if (scriptLocation.search(/[<>\"]/) != -1) {\n    throw \"Bad scriptLocation: \" + scriptLocation;\n  }\n  var header = '<!--WALKABOUT--><scr' + 'ipt src=\"' + scriptLocation + '\"></scr' + 'ipt>' +\n    extra + '<!--/WALKABOUT-->';\n  var match = (/<!--WALKABOUT-->[^]*<!--\\/WALKABOUT-->/).exec(code);\n  if (match) {\n    start = code.substr(0, match.index);\n    rest = code.substr(match.index + match[0].length);\n    code = start + rest;\n  }\n  match = (/<head[^>]*>/i).exec(code);\n  if (! match) {\n    return code;\n  }\n  var endPos = match.index + match[0].length;\n  start = code.substr(0, endPos);\n  rest = code.substr(endPos);\n  return start + header + rest;\n};\n\n/****************************************\n * UI\n */\n\nWalkabout.UI = Walkabout.Class({\n\n  constructor: function UI() {\n    this.panel = this.make(\"div\", {\n      style: this.styles.panel,\n      \"data-walkabout-disable\": 1\n    }, [\n\n      this.closeButton = this.make(\n        \"span\",\n        {\n          style: this.styles.close\n        },\n        [\"\\xd7\"]\n      ),\n\n      this.make(\"div\", {style: this.styles.header}, [\"Walkabout\"]),\n\n      this.make(\n        \"div\",\n        {},\n        [\"Actions: \",\n         this.actionsField = this.make(\n           \"span\",\n           {style: this.styles.actions},\n           [\"?\"]),\n         \" Runs: \",\n         this.runField = this.make(\n           \"span\",\n           {style: this.styles.actions},\n           [\"- / -\"])\n        ]),\n\n      this.issues = this.make(\n        \"div\",\n        {style: this.styles.issues},\n        [\n          this.make(\"div\", {\"data-issues-header\": 1, style: this.styles.issuesHeader}, [\"Issues:\"])\n        ]),\n\n      this.startButton = this.make(\n        \"button\",\n        {style: this.styles.start}, [\"start\"]\n      ),\n\n      this.onceButton = this.make(\n        \"button\",\n        {style: this.styles.start}, [\"run once\"]\n      ),\n\n      this.showButton = this.make(\n        \"button\",\n        {style: this.styles.start}, [\"show\"]\n      )\n\n    ]);\n    document.body.appendChild(this.panel);\n    this.close = this.close.bind(this);\n    this.start = this.start.bind(this);\n    this.show = this.show.bind(this);\n    this.updateActions = this.updateActions.bind(this);\n    this.addIssue = this.addIssue.bind(this);\n    this.closeButton.addEventListener(\"click\", this.close, false);\n    this.startButton.addEventListener(\"click\", this.start, false);\n    this.startButton.disabled = false;\n    this.onceButton.addEventListener(\"click\", (function (event) {\n      this.start(event, 1);\n    }).bind(this), false);\n    this.showButton.addEventListener(\"click\", this.show, false);\n    this.onceButton.disabled = false;\n    this.updateActionsId = setInterval(this.updateActions, 5000);\n    this.updateActions();\n    this.catchIssues();\n    if (Walkabout.options.loadPersistent) {\n      var data = Walkabout.persistentData();\n      // Ignore data older than 30 minutes:\n      // FIXME: should probably still load up the console even if it's old\n      if (data.startAtRemaining) {\n        if ((Date.now() - data.savedAt) < 30*60*1000 ) {\n          this.start();\n        } else if (data.console) {\n          this.issueSerialization(data.console);\n          this.addIssue(\"Not continuing (out of date session)\");\n        }\n      } else if (data.console) {\n        this.issueSerialization(data.console);\n        this.addIssue(\"done.\");\n      }\n    }\n  },\n\n  styles: {\n    panel: \"color: #000; background-color: #ffc; border: 3px outset #aa9; border-radius: 4px; position: fixed; top: 0.3em; right: 0.3em; padding: 0.7em; width: 20%; z-index: 10000; font-family: sans-serif;\",\n    start: \"color: #000; background-color: #eee; border: 2px outset #999; border-radius: 2px; padding: 4px; margin-right: 2px;\",\n    close: \"cursor: pointer; float: right;\",\n    header: \"font-size: 110%; font-weight: bold; border-bottom: 1px solid #aa9; margin-bottom: 6px;\",\n    actions: \"border: 2px solid #000; padding: 0 0.5em 0 0.5em;\",\n    issues: \"max-height: 5em; overflow-y: auto; overflow: auto; border: 2px solid #000; margin: 4px 0 4px 0; font-size: 80%; padding-bottom: 8px;\",\n    issuesHeader: \"font-weight: bold\"\n  },\n\n  make: function (name, attrs, children) {\n    var el = document.createElement(name);\n    if (attrs) {\n      for (var a in attrs) {\n        if (attrs.hasOwnProperty(a)) {\n          el.setAttribute(a, attrs[a]);\n        }\n      }\n    }\n    if (children) {\n      for (var i=0; i<children.length; i++) {\n        var child = children[i];\n        if (typeof child == \"string\") {\n          child = document.createTextNode(child);\n        }\n        el.appendChild(child);\n      }\n    }\n    return el;\n  },\n\n  close: function () {\n    if (this.canceler) {\n      this.canceler();\n    }\n    clearTimeout(this.updateActionsId);\n    this.updateActionsId = null;\n    this.panel.parentNode.removeChild(this.panel);\n    if (Walkabout.options.loadPersistent) {\n      Walkabout.persistentData(null);\n    }\n  },\n\n  start: function (event, times) {\n    this.startButton.innerHTML = \"running\";\n    this.startButton.disabled = true;\n    if (Walkabout.jQueryAvailable) {\n      Walkabout.$.fn.val.patch();\n    }\n    this._lastCount = -1;\n    var startAtRemaining;\n    var persist = Walkabout.options.loadPersistent;\n    var seeded = false;\n    if (persist) {\n      var data = Walkabout.persistentData();\n      startAtRemaining = data.startAtRemaining;\n      if (data.console) {\n        this.issueSerialization(data.console);\n      }\n      if (data.seeded) {\n        seeded = true;\n      }\n      Walkabout.random.storeState = \"walkabout.randomstate\";\n    }\n    if ((! seeded) && times > 1) {\n      var seed = Date.now();\n      Walkabout.random.setSeed(seed);\n      this.addIssue(\"Starting run with seed: \" + seed);\n    }\n    this.canceler = Walkabout.runManyActions({\n      ondone: (function () {\n        this.startButton.innerHTML = \"start\";\n        this.startButton.disabled = false;\n        this.runField.innerHTML = \"- / -\";\n        if (Walkabout.jQueryAvailable) {\n          Walkabout.$.fn.val.unpatch();\n        }\n        if (persist) {\n          Walkabout.persistentData({\n            console: this.issueSerialization(),\n            savedAt: Date.now()\n          });\n        }\n      }).bind(this),\n      onstatus: (function (status) {\n        if (status.actions.length != this._lastCount) {\n          this._lastCount = status.actions.length;\n          this.updateActions(status.actions);\n        }\n        this.runField.textContent = (status.times - status.remaining) + \" / \" + status.times;\n        if (persist) {\n          var data = {\n            startAtRemaining: status.remaining,\n            console: this.issueSerialization(),\n            savedAt: Date.now(),\n            seeded: true\n          };\n          Walkabout.persistentData(data);\n        }\n      }).bind(this),\n      times: times,\n      startAtRemaining: startAtRemaining\n    });\n  },\n\n  show: function () {\n    if (this._showing) {\n      this.showButton.innerHTML = \"show\";\n      this._showing.forEach(function (item) {\n        if (item) {\n          item.remove();\n        }\n      });\n      this._showing = null;\n      return;\n    }\n    this.showButton.innerHTML = \"hide\";\n    var showing = this._showing = [];\n    var actions = Walkabout.findActions();\n    actions.forEach(function (a) {\n      showing.push(a.show());\n    });\n  },\n\n  updateActions: function (actions) {\n    actions = actions || Walkabout.findActions();\n    this.actionsField.innerHTML = \"\";\n    this.actionsField.appendChild(document.createTextNode(actions.length));\n  },\n\n  addIssue: function () {\n    var div = this.make(\"div\", {}, arguments);\n    this.issues.appendChild(div);\n    this.issues.childNodes[this.issues.childNodes.length - 1].scrollIntoView();\n  },\n\n  issueSerialization: function (value) {\n    var i;\n    if (value === undefined) {\n      var result = [];\n      for (i=0; i<this.issues.childNodes.length; i++) {\n        var child = this.issues.childNodes[i];\n        if (child.getAttribute(\"data-issues-header\")) {\n          continue;\n        }\n        result.push(this.issues.childNodes[i].textContent);\n      }\n      return result;\n    } else {\n      for (i=0; i<value.length; i++) {\n        if (value[i] == \"Issues:\") throw \"Issues in serialization :(\";\n        this.addIssue(value[i]);\n      }\n      return value;\n    }\n  },\n\n  catchIssues: function () {\n    var oldOnError = window.onerror;\n    window.onerror = (function (errorMessage, url, lineNumber) {\n      this.addIssue(errorMessage + \" in \" + url + \":\" + lineNumber);\n      if (oldOnError) {\n        return oldOnError(errorMessage, url, lineNumber);\n      }\n      return false;\n    }).bind(this);\n    function bind(context, obj, prop, message) {\n      var orig = obj[prop];\n      obj[prop] = function () {\n        var args = [message].concat(Array.prototype.slice.call(arguments, 0));\n        context.addIssue.apply(context, args);\n        orig.apply(obj, arguments);\n      };\n      obj[prop].orig = orig;\n    }\n    bind(this, console, \"warn\", \"WARN: \");\n    bind(this, console, \"error\", \"ERROR: \");\n  }\n\n});\n\nWalkabout.makeBookmarklet = function () {\n  var scripts = document.querySelectorAll(\"script\");\n  var walkaboutSrc;\n  for (var i=0; i<scripts.length; i++) {\n    var src = scripts[i].src;\n    if (src.indexOf(\"walkabout.js\") != -1) {\n      walkaboutSrc = src;\n      break;\n    }\n  }\n  if (! walkaboutSrc) {\n    return \"javascript:alert('Could not find script.')\";\n  }\n  // Cache bust on localhost\n  var cacheBust = walkaboutSrc.indexOf(\"localhost\") != -1;\n  var s = [\n    \"(function () {\",\n    \"var _s = document.getElementById('walkabout_script');\",\n    \"if (_s) _s.parentNode.removeChild(_s);\",\n    \"_s = document.createElement('script');\",\n    \"_s.src = '\" + walkaboutSrc + \"'\",\n    (cacheBust ? \" + '?cachebust=' + Date.now()\" : \"\"),\n    \";\",\n    \"_Walkabout_start_UI = true;\",\n    \"document.head.appendChild(_s);\",\n    \"})();void(0);\"\n  ];\n  s = s.join(\"\");\n  s = \"javascript:\" + encodeURIComponent(s);\n  return s;\n};\n\n/****************************************\n * History handling\n */\n\nif (typeof location != \"undefined\") {\n  Walkabout.hashHistory = [location.hash];\n}\n\nif (typeof window != \"undefined\") {\n  window.addEventListener(\"hashchange\", function () {\n    var hash = location.hash;\n    if (Walkabout.hashHistory.length > 1 &&\n        Walkabout.hashHistory[Walkabout.hashHistory.length - 2] == hash) {\n      // Someone just hit back (or at least that's what we'll pretend it is)\n      Walkabout.hashHistory.splice(Walkabout.hashHistory.length - 1, 1);\n    } else {\n      Walkabout.hashHistory.push(hash);\n    }\n  }, false);\n}\n\nWalkabout.actionFinders.push(function backFromHash(el, actions) {\n  if (el !== document && el !== window) {\n    return;\n  }\n  if (Walkabout.hashHistory.length > 1) {\n    // FIXME: there should be a way to suppress this from happening\n    actions.push(Walkabout.Back());\n  }\n});\n\nWalkabout.Back = Walkabout.Class({\n  constructor: function Back() {\n  },\n\n  show: function () {\n    return Walkabout.Notifier(\"Go back\");\n  },\n\n  description: function () {\n    return \"Go back\";\n  },\n\n  run: Walkabout.setInTesting(function () {\n    window.history.back();\n  })\n});\n\n/****************************************\n * Secret activation!\n */\n\nWalkabout.activationSequence = \"walkabout\";\n\nWalkabout.activationSequenceIndex = 0;\n\nif (typeof document != \"undefined\") {\n  document.addEventListener(\"keypress\", function (event) {\n    var index = Walkabout.activationSequenceIndex;\n    var seq = Walkabout.activationSequence;\n    var expected = seq.charCodeAt(index);\n    if (event.keyCode == expected) {\n      index++;\n    } else if (event.keyCode == seq.charCodeAt(0)) {\n      index = 1;\n    } else {\n      index = 0;\n    }\n    if (index >= seq.length) {\n      index = 0;\n      Walkabout.UI();\n    }\n    Walkabout.activationSequenceIndex = index;\n  }, false);\n}\n\n/****************************************\n * Mock APIs:\n */\n\nvar mockTelephony = {\n\n  muted: false,\n  speakerEnabled: true,\n  active: null,\n  calls: [],\n  conferenceGroup: null,\n  startTone: function (tone) {\n  },\n  stopTone: function () {\n  },\n  onincoming: null,\n  oncallschanged: null\n\n};\n\nvar mockCall = {\n  number: null, // string\n  // \"dialing\", \"alerting\", \"busy\", \"connecting\", \"connected\", \"disconnecting\",\n  // \"disconnected\", \"incoming\", \"holding\", \"held\", \"resuming\"\n  state: null,\n  group: null,\n  answer: function () {\n  },\n  hangUp: function () {\n  },\n  hold: function () {\n  },\n  resume: function () {\n  },\n  onstatechange: null,\n  onalerting: null,\n  onbusy: null,\n  onconnecting: null,\n  onconnected: null,\n  ondisconnecting: null,\n  ondisconnected: null,\n  onincoming: null,\n  onholding: null,\n  onheld: null,\n  onresuming: null,\n  ongroupchange: null\n};\n\nvar mockCallGroup = {\n  // Array of all calls that are currently in this group. The length\n  // of this array is never 1.\n  calls: [],\n\n  // Add a call to the callgroup. call2 must not be specified if the\n  // callgroup isn't empty.\n  // If the callgroup is empty both call and call2 must be specified,\n  // and one of them must be in 'held' state and the other in\n  // 'connected' state.\n  // Neither call or call2 can be in 'disconnected' state.\n  add: function (call, call2) {\n  },\n\n  // Removes a call from the callgroup. If this leaves the callgroup with\n  // just one call, then that last call is also removed from the callgroup.\n  remove: function (call) {\n  },\n\n  hold: function () {\n  },\n  // Resuming a group automatically holds any other groups/calls\n  resume: function () {\n  },\n\n  // When this changes, the state of all contained calls changes at the same time\n  state: null,\n\n  onstatechange: null,\n  onconnected: null,\n  onholding: null,\n  onheld: null,\n  onresuming: null,\n  // Fires when the array in the 'calls' property changes.\n  oncallschanged: null\n};\n\nif (typeof exports != \"undefined\") {\n  // Expect that we are in a node environment\n  Walkabout._extend(exports, Walkabout);\n}\n\nif (typeof _Walkabout_start_UI != \"undefined\") {\n  if (document.readyState == \"complete\") {\n    Walkabout.UI();\n  } else {\n    window.addEventListener(\"load\", Walkabout.UI, false);\n  }\n}\n\nif (typeof _Walkabout_sitewide != \"undefined\") {\n  Walkabout.options.anyLocalLinks = location.pathname.replace(/\\/[^\\/]*$/, \"/\");\n  Walkabout.options.loadPersistent = true;\n}\n\nreturn Walkabout;\n\n}\n\n// Wherein we support a variety of module systems:\n//   exports for CommonJS/Node\n//   define for RequireJS\n//   nothing to export Walkabout\nif (typeof exports != \"undefined\") {\n  init(exports);\n} else if (typeof define != \"undefined\") {\n  define(init);\n} else {\n  Walkabout = {};\n  init(Walkabout);\n}\n\n})();\n"
  },
  {
    "path": "togetherjs/libs/whrandom/README.md",
    "content": "whrandom / random.js\n====================\n\nThis is a port of Python's [whrandom](http://docs.python.org/release/2.4/lib/module-whrandom.html) module, which is a [pseudorandom number generator](http://en.wikipedia.org/wiki/Pseudorandom_number_generator).\n\nThat means it creates \"random\" numbers with a <em>seed</em>, and if you provide the same seed it will create the same set of numbers.  This is a common feature in many languages, but not offered by Javascript's `Math.random()`.\n\nThis isn't the best random number generator, but the algorithm is very simple.  \n\n\nMersenne Twister / mersenne.js\n==============================\n\nPython now prefers the [Marsenne Twister](http://en.wikipedia.org/wiki/Mersenne_twister).  It has some nice features over whrandom (you can read that page to see them).\n\nI've taken a [piece of code](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/JAVASCRIPT/java-script.html) written by Y. Okada and library-ized it some.  It matches the interface of whrandom.\n\nUsing it\n--------\n\nIf you include `random.js` it will expose one variable: `WHRandomStream` (`mersenne.js` exposes `MersenneRandomStream`).  You can also require the module using [requirejs](http://requirejs.org/) or import it in Node (though I haven't provided a pacakge.json), and in both cases the exported object is `RandomStream` itself (e.g., `var RandomStream = require(\"./random.js\");`, ditto `mersenne.js`)\n\nTo create a stream, call `RandomStream(seed)`; if no `seed` is provided then `Date.now()` is used.  To get new random numbers from a stream, simply call the function.  All random numbers are *between* 0 and 1 (but never actually 1), just like `Math.random()`.\n\n`MersenneRandomStream` instances also have the methods:\n\n`.int31()`: generates a random number on [0,0x7fffffff]-interval\n\n`.real1()`: generates a random number on [0,1]-real-interval\n\n`.real2()`: generates a random number on [0,1)-real-interval (the default)\n\n`.real3()`: generates a random number on (0,1)-real-interval\n\n`.res53()`: generates a random number on [0,1) with 53-bit resolution (basically higher resolution version of the default)\n"
  },
  {
    "path": "togetherjs/libs/whrandom/mersenne.js",
    "content": "// this program is a JavaScript version of Mersenne Twister,\n// a straight conversion from the original program, mt19937ar.c,\n// translated by y. okada on july 17, 2006.\n// and modified a little at july 20, 2006, but there are not any substantial differences.\n// modularized by Ian Bicking, March 25, 2013 (found original version at http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/JAVASCRIPT/java-script.html)\n// in this program, procedure descriptions and comments of original source code were not removed.\n// lines commented with //c// were originally descriptions of c procedure. and a few following lines are appropriate JavaScript descriptions.\n// lines commented with /* and */ are original comments.\n// lines commented with // are additional comments in this JavaScript version.\n/*\n   A C-program for MT19937, with initialization improved 2002/1/26.\n   Coded by Takuji Nishimura and Makoto Matsumoto.\n\n   Before using, initialize the state by using init_genrand(seed)\n   or init_by_array(init_key, key_length).\n\n   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions\n   are met:\n\n     1. Redistributions of source code must retain the above copyright\n        notice, this list of conditions and the following disclaimer.\n\n     2. Redistributions in binary form must reproduce the above copyright\n        notice, this list of conditions and the following disclaimer in the\n        documentation and/or other materials provided with the distribution.\n\n     3. The names of its contributors may not be used to endorse or promote\n        products derived from this software without specific prior written\n        permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n   Any feedback is very welcome.\n   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html\n   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)\n*/\n\n(function () {\n\nfunction RandomStream(seed) {\n\n  /*jshint bitwise:false */\n  /* Period parameters */\n  //c//#define N 624\n  //c//#define M 397\n  //c//#define MATRIX_A 0x9908b0dfUL   /* constant vector a */\n  //c//#define UPPER_MASK 0x80000000UL /* most significant w-r bits */\n  //c//#define LOWER_MASK 0x7fffffffUL /* least significant r bits */\n  var N = 624;\n  var M = 397;\n  var MATRIX_A = 0x9908b0df;   /* constant vector a */\n  var UPPER_MASK = 0x80000000; /* most significant w-r bits */\n  var LOWER_MASK = 0x7fffffff; /* least significant r bits */\n  //c//static unsigned long mt[N]; /* the array for the state vector  */\n  //c//static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */\n  var mt = new Array(N);   /* the array for the state vector  */\n  var mti = N+1;           /* mti==N+1 means mt[N] is not initialized */\n\n  function unsigned32 (n1) // returns a 32-bits unsiged integer from an operand to which applied a bit operator.\n  {\n    return n1 < 0 ? (n1 ^ UPPER_MASK) + UPPER_MASK : n1;\n  }\n\n  function subtraction32 (n1, n2) // emulates lowerflow of a c 32-bits unsiged integer variable, instead of the operator -. these both arguments must be non-negative integers expressible using unsigned 32 bits.\n  {\n    return n1 < n2 ? unsigned32((0x100000000 - (n2 - n1)) & 0xffffffff) : n1 - n2;\n  }\n\n  function addition32 (n1, n2) // emulates overflow of a c 32-bits unsiged integer variable, instead of the operator +. these both arguments must be non-negative integers expressible using unsigned 32 bits.\n  {\n    return unsigned32((n1 + n2) & 0xffffffff);\n  }\n\n  function multiplication32 (n1, n2) // emulates overflow of a c 32-bits unsiged integer variable, instead of the operator *. these both arguments must be non-negative integers expressible using unsigned 32 bits.\n  {\n    var sum = 0;\n    for (var i = 0; i < 32; ++i){\n      if ((n1 >>> i) & 0x1){\n        sum = addition32(sum, unsigned32(n2 << i));\n      }\n    }\n    return sum;\n  }\n\n  /* initializes mt[N] with a seed */\n  //c//void init_genrand(unsigned long s)\n  function init_genrand(s) {\n    //c//mt[0]= s & 0xffffffff;\n    mt[0]= unsigned32(s & 0xffffffff);\n    for (mti=1; mti<N; mti++) {\n      mt[mti] =\n      //c//(1812433253 * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);\n      addition32(multiplication32(1812433253, unsigned32(mt[mti-1] ^ (mt[mti-1] >>> 30))), mti);\n      /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */\n      /* In the previous versions, MSBs of the seed affect   */\n      /* only MSBs of the array mt[].                        */\n      /* 2002/01/09 modified by Makoto Matsumoto             */\n      //c//mt[mti] &= 0xffffffff;\n      mt[mti] = unsigned32(mt[mti] & 0xffffffff);\n      /* for >32 bit machines */\n    }\n  }\n\n  /* initialize by an array with array-length */\n  /* init_key is the array for initializing keys */\n  /* key_length is its length */\n  /* slight change for C++, 2004/2/26 */\n  //c//void init_by_array(unsigned long init_key[], int key_length)\n  function init_by_array(init_key, key_length) {\n    //c//int i, j, k;\n    var i, j, k;\n    init_genrand(19650218);\n    i=1; j=0;\n    k = (N>key_length ? N : key_length);\n    for (; k; k--) {\n      //c//mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525))\n      //c// + init_key[j] + j; /* non linear */\n      mt[i] = addition32(addition32(unsigned32(mt[i] ^ multiplication32(unsigned32(mt[i-1] ^ (mt[i-1] >>> 30)), 1664525)), init_key[j]), j);\n      mt[i] =\n      //c//mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */\n      unsigned32(mt[i] & 0xffffffff);\n      i++; j++;\n      if (i>=N) { mt[0] = mt[N-1]; i=1; }\n      if (j>=key_length) {\n        j=0;\n      }\n    }\n    for (k=N-1; k; k--) {\n      //c//mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941))\n      //c//- i; /* non linear */\n      mt[i] = subtraction32(unsigned32((mt[i]) ^ multiplication32(unsigned32(mt[i-1] ^ (mt[i-1] >>> 30)), 1566083941)), i);\n      //c//mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */\n      mt[i] = unsigned32(mt[i] & 0xffffffff);\n      i++;\n      if (i>=N) { mt[0] = mt[N-1]; i=1; }\n    }\n    mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */\n  }\n\n  /* generates a random number on [0,0xffffffff]-interval */\n  //c//unsigned long genrand_int32(void)\n  function genrand_int32() {\n    //c//unsigned long y;\n    //c//static unsigned long mag01[2]={0x0UL, MATRIX_A};\n    var y;\n    var mag01 = [0x0, MATRIX_A];\n    /* mag01[x] = x * MATRIX_A  for x=0,1 */\n\n    if (mti >= N) { /* generate N words at one time */\n      //c//int kk;\n      var kk;\n\n      if (mti == N+1) {   /* if init_genrand() has not been called, */\n        init_genrand(Date.now()); /* a default initial seed is used */\n      }\n\n      for (kk=0;kk<N-M;kk++) {\n        //c//y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);\n        //c//mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];\n        y = unsigned32((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK));\n        mt[kk] = unsigned32(mt[kk+M] ^ (y >>> 1) ^ mag01[y & 0x1]);\n      }\n      for (;kk<N-1;kk++) {\n        //c//y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);\n        //c//mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];\n        y = unsigned32((mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK));\n        mt[kk] = unsigned32(mt[kk+(M-N)] ^ (y >>> 1) ^ mag01[y & 0x1]);\n      }\n      //c//y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);\n      //c//mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];\n      y = unsigned32((mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK));\n      mt[N-1] = unsigned32(mt[M-1] ^ (y >>> 1) ^ mag01[y & 0x1]);\n      mti = 0;\n    }\n\n    y = mt[mti++];\n\n    /* Tempering */\n    //c//y ^= (y >> 11);\n    //c//y ^= (y << 7) & 0x9d2c5680;\n    //c//y ^= (y << 15) & 0xefc60000;\n    //c//y ^= (y >> 18);\n    y = unsigned32(y ^ (y >>> 11));\n    y = unsigned32(y ^ ((y << 7) & 0x9d2c5680));\n    y = unsigned32(y ^ ((y << 15) & 0xefc60000));\n    y = unsigned32(y ^ (y >>> 18));\n\n    return y;\n  }\n\n  /* generates a random number on [0,0x7fffffff]-interval */\n  //c//long genrand_int31(void)\n  function genrand_int31() {\n    //c//return (genrand_int32()>>1);\n    return (genrand_int32()>>>1);\n  }\n\n  /* generates a random number on [0,1]-real-interval */\n  //c//double genrand_real1(void)\n  function genrand_real1() {\n    return genrand_int32()*(1.0/4294967295.0);\n    /* divided by 2^32-1 */\n  }\n\n  /* generates a random number on [0,1)-real-interval */\n  //c//double genrand_real2(void)\n  function genrand_real2() {\n    return genrand_int32()*(1.0/4294967296.0);\n    /* divided by 2^32 */\n  }\n\n  /* generates a random number on (0,1)-real-interval */\n  //c//double genrand_real3(void)\n  function genrand_real3() {\n    return ((genrand_int32()) + 0.5)*(1.0/4294967296.0);\n    /* divided by 2^32 */\n  }\n\n  /* generates a random number on [0,1) with 53-bit resolution*/\n  //c//double genrand_res53(void)\n  function genrand_res53() {\n    //c//unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;\n    var a=genrand_int32()>>>5, b=genrand_int32()>>>6;\n    return (a*67108864.0+b)*(1.0/9007199254740992.0);\n  }\n  /* These real versions are due to Isaku Wada, 2002/01/09 added */\n\n  var random = genrand_real2;\n\n  random.seed = function (seed) {\n    if (! seed) {\n      seed = Date.now();\n    }\n    if (typeof seed != \"number\") {\n      seed = parseInt(seed, 10);\n    }\n    if ((seed !== 0 && ! seed) || isNaN(seed)) {\n      throw \"Bad seed\";\n    }\n    init_genrand(seed);\n  };\n\n  random.seed(seed);\n\n  random.int31 = genrand_int31;\n  random.real1 = genrand_real1;\n  random.real2 = genrand_real2;\n  random.real3 = genrand_real3;\n  random.res53 = genrand_res53;\n\n  return random;\n\n}\n\n// Support for AMD/requirejs, CommonJS/Node, and no module system:\nif (typeof define != \"undefined\") {\n  define([], function () {return RandomStream;});\n} else if (typeof module != \"undefined\") {\n  module.exports = RandomStream;\n} else {\n  window.MersenneRandomStream = RandomStream;\n}\n\n})();\n"
  },
  {
    "path": "togetherjs/libs/whrandom/random.js",
    "content": "(function () {\n\nfunction RandomStream(seed) {\n  if (! seed) {\n    seed = Date.now();\n  }\n  if (typeof seed != \"number\") {\n    seed = parseInt(seed, 10);\n  }\n  if ((! seed) || isNaN(seed)) {\n    throw \"Bad seed\";\n  }\n  var x = (seed % 30268) + 1;\n  seed = (seed - (seed % 30268)) / 30268;\n  var y = (seed % 30306) + 1;\n  seed = (seed - (seed % 30306)) / 30306;\n  var z = (seed % 30322) + 1;\n  seed = (seed - (seed % 30322)) / 30322;\n  return function random() {\n    x = (171 * x) % 30269;\n    y = (172 * y) % 30307;\n    z = (170 * z) % 30323;\n    if (random.logState) {\n      console.log('x', x, 'y', y, 'z', z);\n    }\n    return (x / 30269.0 + y / 30307.0 + z / 30323.0) % 1.0;\n  };\n}\n\n// Support for AMD/requirejs, CommonJS/Node, and no module system:\nif (typeof define != \"undefined\") {\n  define([], function () {return RandomStream;});\n} else if (typeof module != \"undefined\") {\n  module.exports = RandomStream;\n} else {\n  window.WHRandomStream = RandomStream;\n}\n\n})();\n"
  },
  {
    "path": "togetherjs/libs/whrandom/test_random.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Test RandomStream</title>\n    <meta charset=\"UTF-8\">\n    <script src=\"random.js\"></script>\n    <script src=\"mersenne.js\"></script>\n    <script src=\"http://doctestjs.org/doctest.js\"></script>\n    <link rel=\"stylesheet\" href=\"http://doctestjs.org/doctest.css\">\n  </head>\n  <body class=\"autodoctest\">\n\n    <p>Tests will run automatically:</p>\n\n    <pre class=\"commenttest\" href=\"test_random.js\">\n    </pre>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/libs/whrandom/test_random.js",
    "content": "//==SECTION WHRandom\n\njshint(\"random.js\");\n// => Script passed: ...\n\nvar random = WHRandomStream(1);\nrandom.logState = true;\n\nprint(random());\n\n// => 0.02258025041320865\n\nrandom = WHRandomStream(61731 + (24903<<32) + (614<<64) + (42143<<96));\nfor (var i=0; i<1990; i++) {\n  // Throw away the first 1990 results\n  random();\n}\nfor (var i=0; i<10; i++) {\n  print(random());\n}\n\n/* =>\n0.509619534765086\n0.46840731249967416\n0.6477464858997404\n0.7262869907208884\n0.26678101301184265\n0.8506177950611828\n0.807989512174746\n0.34070112203493075\n0.3237063277558945\n0.9579732082997315\n*/\n\nrandom = WHRandomStream(61731 + (24903<<32) + (614<<64) + (42143<<96));\nfor (var i=0; i<1990; i++) {\n  // Throw away the first 1990 results\n  random();\n}\nfor (var i=0; i<10; i++) {\n  print(random());\n}\n\n/* =>\n0.509619534765086\n0.46840731249967416\n0.6477464858997404\n0.7262869907208884\n0.26678101301184265\n0.8506177950611828\n0.807989512174746\n0.34070112203493075\n0.3237063277558945\n0.9579732082997315\n*/\n\nvar random1 = WHRandomStream();\nwait(10);\n// =>\nvar random2 = WHRandomStream();\nprint(random1() == random2());\n\n// => false\n\n//==SECTION Mersenne Twister\n\nrandom = MersenneRandomStream(61731 + (24903<<32) + (614<<64) + (42143<<96));\nfor (var i=0; i<1990; i++) {\n  // Throw away the first 1990 results\n  random();\n}\nfor (var i=0; i<10; i++) {\n  print(random());\n}\n\n/* =>\n0.36614991538226604\n0.7007313468493521\n0.053458782844245434\n0.7753883530385792\n0.27555248513817787\n0.16756457393057644\n0.8208331714849919\n0.014290706953033805\n0.8880474304314703\n0.9676008424721658\n*/\n\nvar random1 = MersenneRandomStream();\nwait(10);\n// =>\nvar random2 = MersenneRandomStream();\nprint(random1() == random2());\n\n// => false\n"
  },
  {
    "path": "togetherjs/linkify.js",
    "content": "define([], function () {\n  // FIXME: this could be moved to a different module, it's pretty stand-alone\n  /* Finds any links in the text of an element (or its children) and turns them\n     into anchors (with target=_blank) */\n  function linkify(el) {\n    if (el.jquery) {\n      el = el[0];\n    }\n    el.normalize();\n    function linkifyNode(node) {\n      var _len = node.childNodes.length;\n      for (var i=0; i<_len; i++) {\n        if (node.childNodes[i].nodeType == document.ELEMENT_NODE) {\n          linkifyNode(node.childNodes[i]);\n        }\n      }\n      var texts = [];\n      for (i=0; i<_len; i++) {\n        if (node.childNodes[i].nodeType == document.TEXT_NODE) {\n          texts.push(node.childNodes[i]);\n        }\n      }\n      texts.forEach(function (item) {\n        if (item.nodeType == document.ELEMENT_NODE) {\n          linkifyNode(item);\n        } else if (item.nodeType == document.TEXT_NODE) {\n          while (true) {\n            var text = item.nodeValue;\n            var regex = /\\bhttps?:\\/\\/[a-z0-9\\.\\-_](:\\d+)?[^ \\n\\t<>()\\[\\]]*/i;\n            var match = regex.exec(text);\n            if (! match) {\n              break;\n            }\n            var leadingNode = document.createTextNode(text.substr(0, match.index));\n            node.replaceChild(leadingNode, item);\n            var anchor = document.createElement(\"a\");\n            anchor.setAttribute(\"target\", \"_blank\");\n            anchor.href = match[0];\n            anchor.appendChild(document.createTextNode(match[0]));\n            node.insertBefore(anchor, leadingNode.nextSibling);\n            var trailing = document.createTextNode(text.substr(match.index + match[0].length));\n            node.insertBefore(trailing, anchor.nextSibling);\n            item = trailing;\n          }\n        }\n      });\n    }\n    linkifyNode(el);\n    return el;\n  }\n\n  return linkify;\n});\n"
  },
  {
    "path": "togetherjs/locale/de-DE.json",
    "content": "{\n  \"Activate your <strong>browser microphone</strong> near your URL bar above.\": \"Das <strong>browser Mikrofon</strong> neben der Adresszeile oben aktivieren.\",\n  \"Add a friend\": \"Freund hinzufügen\",\n  \"Alright, you're ready to use TOOL_NAME. Now start collaborating on SITE_NAME!\": \"TOOL_NAME ist einsatzbereit. Jetzt auf SITE_NAME zusammenarbeiten!\",\n  \"anyone\": \"jemand\",\n  \"Are you sure you'd like to end your TOOL_NAME session?\": \"Soll die TOOL_NAME Sitzung wirklich beendet werden?\",\n  \"Audio chat requires you to use a <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>newer browser</a>!\": \"Für die Audiokonferenz wird ein <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>neuerer browser</a> benötigt!\",\n  \"Audio Chat\": \"Audiokonferenz\",\n  \"Cancel\": \"Abbrechen\",\n  \"Change avatar\": \"Avatar ändern\",\n  \"Change your avatar, name and user color using the Profile button.\": \"Avatar, Name und Profilfarbe über die Profil Taste ändern.\",\n  \"Chat\": \"Nachrichten\",\n  \"Close\": \"Schließen\",\n  \"Copy and paste this link into IM or email to invite friends.\": \"Diese Adresse an Freunde senden, um sie einzuladen.\",\n  \"Copy and paste this link over IM or email:\": \"Diese Adresse an Freunde senden:\",\n  \"Currently at:\": \"Momentan auf:\",\n  \"declined to join the session.\": \"hat die Einladung abgelehnt.\",\n  \"Don't show again.\": \"Nicht erneut anzeigen.\",\n  \"End session\": \"Sitzung beenden\",\n  \"End session?\": \"Sitzung beenden?\",\n  \"End TOOL_NAME\": \"TOOL_NAME beenden\",\n  \"End\": \"Beende\",\n  \"Enter your name\": \"Namen eingeben\",\n  \"Feedback\": \"Rückmeldung\",\n  \"Follow this participant:\": \"Diesem Teilnehmer folgen:\",\n  \"Follow:\": \"Folgen:\",\n  \"Following to new URL...\": \"Zur neuen Adresse folgen ...\",\n  \"Following\": \"Folgt\",\n  \"Friends who join your TOOL_NAME session will appear here.  You can click their avatars to see more.\": \"Freunde, die an der TOOL_NAME Sitzung teilnehmen, erscheinen hier.  Auf die Avatare klicken, um mehr zu sehen.\",\n  \"has gone to:\": \"ging auf:\",\n  \"has invited\": \"hat eingeladen\",\n  \"Help\": \"Hilfe\",\n  \"here\": \"Audiokonferenz lesen\",\n  \"I'm ready!\": \"Bereit!\",\n  \"If your browser supports it, click the microphone icon to begin an audio chat. Learn more about this experimental feature <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">here</a>.\": \"Mikrofon klicken, um eine Audiokonferenz zu beginnen, falls vom browser unterstützt. Info zur <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">experimentellen Funktion</a>.\",\n  \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">is currently not supported</a>.  If you do want to try out TogetherJS, we'd suggest using Firefox or Chrome.\": \"<a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">Internet Explorer</a> wird momentan nicht unterstütztis currently not supported.  Um TogetherJS auszuprobieren empfehlen wir Firefox oder Chrome.\",\n  \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> is not supported</a> and won't be supported in the near term, please use Firefox or Chrome.\": \"<a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'>Internet Explorer</a> wird nicht unterstützt. Auch in nächster Zukunft nicht. Bitte Firefox oder Chrome nutzen.\",\n  \"Invite a friend\": \"Einen Freund einladen\",\n  \"Invite anyone\": \"Jemanden einladen\",\n  \"is on the same page as you.\": \"ist auf der selben Seite.\",\n  \"Join them\": \"Teilnehmen\",\n  \"Join TOOL_NAME session?\": \"TOOL_NAME Sitzungsteilnahme?\",\n  \"joined the session.\": \"nimmt an der Sitzung teil.\",\n  \"left the session.\": \"hat die Sitzung verlassen.\",\n  \"Live audio chat requires a newer (or different) browser than you're using.\": \"Die Echtzeitaudiokonferenz benötigt einen neueren (oder anderen) browser.\",\n  \"Loading form...\": \"Formular lädt ...\",\n  \"Move the dock\": \"Konsole verschieben\",\n  \"names\": \"Freundlicher Fuchs, Brillianter Biber, Äugende Eule, Gesellige Giraffe, Wilder Wolf, Stiller Seehund, Wahnsinniger Wal, Curious Katze, Intelligent Leguan\",\n  \"No one else is here.\": \"Es ist sonst niemand hier.\",\n  \"No, don't join\": \"Nein, ablehnen\",\n  \"Nudge them\": \"Anstupsen\",\n  \"OK\": \"OK\",\n  \"or\": \"oder\",\n  \"Participants\": \"Teilnehmer\",\n  \"Pick profile color\": \"Profilfarbe ändern\",\n  \"Read more about Audio Chat\": \"Mehr über\",\n  \"refresh users\": \"Nutzer aktualisieren\",\n  \"Role:\": \"Rolle:\",\n  \"Save\": \"Speichern\",\n  \"Saved!\": \"Gespeichert!\",\n  \"See <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>this page</a>for more information and a list of supported browsers.\": \"<a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>Liste ünterstützter browser und mehr Information</a>.\",\n  \"Send the above link to a friend so they can join your session!  You can find this invite link on the TOOL_NAME dock as well.\": \"Die obige Adresse an Freunde schicken, um diese zur Sitzung einzuladen!  Diese findet sich auch in der TOOL_NAME Konsole.\",\n  \"Set up your avatar, name and user color above.  If you'd like to update it later, you can click your Profile button.\": \"Avatar, Name und Profilfarbe oben anlegen.  Um diese später zu ändern, die Profiltaste klicken.\",\n  \"Settings and Profile\": \"Einstellungen und Profil\",\n  \"Sorry\": \"Entschuldigung\",\n  \"Status:\": \"Status:\",\n  \"Talking on your microphone through your web browser is an experimental feature.\": \"Das Mikrofon über den browser zu nutzen, ist eine experimentelle Funktion.\",\n  \"This is you\": \"Persönliche Einstellungen\",\n  \"to\": \"nach\",\n  \"TOOL_NAME is a service for your website that makes it easy to collaborate in real-time on SITE_NAME\": \"TOOL_NAME ist ein einfacher Dienst zur Zusammenarbeit in Echtzeit auf SITE_NAME\",\n  \"Try TOOL_NAME Anyway\": \"TOOL_NAME trotzdem ausprobieren\",\n  \"Turn on microphone\": \"Mikrofon einschalten\",\n  \"Type your message here\": \"Nachricht hier eingeben\",\n  \"Unsupported Browser\": \"Nicht unterstützter Browser\",\n  \"Update avatar\": \"Avatar ändern\",\n  \"Update Name\": \"Name ändern\",\n  \"Update your name\": \"Name ändern\",\n  \"We're sorry, TOOL_NAME doesn't work with this browser.  Please <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>upgrade to a supported browser</a> to try TOOL_NAME.\": \"Entschuldigung, TOOL_NAME läuft nicht mit diesem browser.  Bitte auf einen <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>unterstützten browser</a> aktualisieren, um TOOL_NAME auszuprobieren.\",\n  \"We need your help fixing TogetherJS on Internet Explorer!  Here are a list of IE <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">GitHub issues</a> we need fixed that you can work on.\": \"Um TogetherJS auf Internet Explorer zu bringen wird Hilfe benötigt!  Diese <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">Liste an IE GitHub Themen</a> muss behoben werden, um IE einzusetzen.\",\n  \"When your friends join you in your TOOL_NAME session, you can chat with them here!\": \"Wenn Freunde an der TOOL_NAME Sitzung teilnehmen, können hier Nachrichten versandt werden!\",\n  \"Would you like to join their session?\": \"An deren Sitzung teilnehmen?\",\n  \"Yes, join session\": \"Ja, teilnehmen\",\n  \"You can continue to try to use TOOL_NAME, but you are likely to hit lots of bugs.  So be warned.\": \"Warnung.  TOOL_NAME kann weiterhin eingesetzt werden, allerdings werden wahrscheinlich einige Fehler auftreten.\",\n  \"You can invite more friends to the session by sending the invite link in the TOOL_NAME dock.\": \"Weitere Freunde können über Versendung des Einladungsverweis in der TOOL_NAME Konsole eingeladen werden.\",\n  \"You\": \"You\",\n  \"you\": \"you\",\n  \"You're using TOOL_NAME!\": \"TOOL_NAME wird genutzt!\",\n  \"Your friend has asked you to join their TOOL_SITE_LINK browser session to collaborate in real-time!\": \"Ein Freund hat zur TOOL_SITE_LINK browser Sitzung zur Echtzeitzusammenarbeit eingeladen!\"\n}\n"
  },
  {
    "path": "togetherjs/locale/en-US.json",
    "content": "{\n  \"Activate your <strong>browser microphone</strong> near your URL bar above.\": \"Activate your <strong>browser microphone</strong> near your URL bar above.\",\n  \"Add a friend\": \"Add a friend\",\n  \"Alright, you're ready to use TOOL_NAME. Now start collaborating on SITE_NAME!\": \"Alright, you're ready to use TOOL_NAME. Now start collaborating on SITE_NAME!\",\n  \"anyone\": \"anyone\",\n  \"Are you sure you'd like to end your TOOL_NAME session?\": \"Are you sure you'd like to end your TOOL_NAME session?\",\n  \"Audio chat requires you to use a <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>newer browser</a>!\": \"Audio chat requires you to use a <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>newer browser</a>!\",\n  \"Audio Chat\": \"Audio Chat\",\n  \"Cancel\": \"Cancel\",\n  \"Change avatar\": \"Change avatar\",\n  \"Change your avatar, name and user color using the Profile button.\": \"Change your avatar, name and user color using the Profile button.\",\n  \"Chat\": \"Chat\",\n  \"Close\": \"Close\",\n  \"Copy and paste this link into IM or email to invite friends.\": \"Copy and paste this link into IM or email to invite friends.\",\n  \"Copy and paste this link over IM or email:\": \"Copy and paste this link over IM or email:\",\n  \"Currently at:\": \"Currently at:\",\n  \"declined to join the session.\": \"declined to join the session.\",\n  \"Don't show again.\": \"Don't show again.\",\n  \"End session\": \"End session\",\n  \"End session?\": \"End session?\",\n  \"End TOOL_NAME\": \"End TOOL_NAME\",\n  \"End\": \"End\",\n  \"Enter your name\": \"Enter your name\",\n  \"Feedback\": \"Feedback\",\n  \"Follow this participant:\": \"Follow this participant:\",\n  \"Follow:\": \"Follow:\",\n  \"Following to new URL...\": \"Following to new URL...\",\n  \"Following\": \"Following\",\n  \"Friends who join your TOOL_NAME session will appear here.  You can click their avatars to see more.\": \"Friends who join your TOOL_NAME session will appear here.  You can click their avatars to see more.\",\n  \"has gone to:\": \"has gone to:\",\n  \"has invited\": \"has invited\",\n  \"Help\": \"Help\",\n  \"here\": \"here\",\n  \"I'm ready!\": \"I'm ready!\",\n  \"If your browser supports it, click the microphone icon to begin an audio chat. Learn more about this experimental feature <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">here</a>.\": \"If your browser supports it, click the microphone icon to begin an audio chat. Learn more about this experimental feature <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">here</a>.\",\n  \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">is currently not supported</a>.  If you do want to try out TogetherJS, we'd suggest using Firefox or Chrome.\": \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">is currently not supported</a>.  If you do want to try out TogetherJS, we'd suggest using Firefox or Chrome.\",\n  \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> is not supported</a> and won't be supported in the near term, please use Firefox or Chrome.\": \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> is not supported</a> and won't be supported in the near term, please use Firefox or Chrome.\",\n  \"Invite a friend\": \"Invite a friend\",\n  \"Invite anyone\": \"Invite anyone\",\n  \"is on the same page as you.\": \"is on the same page as you.\",\n  \"Join them\": \"Join them\",\n  \"Join TOOL_NAME session?\": \"Join TOOL_NAME session?\",\n  \"joined the session.\": \"joined the session.\",\n  \"left the session.\": \"left the session.\",\n  \"Live audio chat requires a newer (or different) browser than you're using.\": \"Live audio chat requires a newer (or different) browser than you're using.\",\n  \"Loading form...\": \"Loading form...\",\n  \"Move the dock\": \"Move the dock\",\n  \"names\": \"Friendly Fox, Brilliant Beaver, Observant Owl, Gregarious Giraffe, Wild Wolf, Silent Seal, Wacky Whale, Curious Cat, Intelligent Iguana\",\n  \"No one else is here.\": \"No one else is here.\",\n  \"No, don't join\": \"No, don't join\",\n  \"Nudge them\": \"Nudge them\",\n  \"OK\": \"OK\",\n  \"or\": \"or\",\n  \"Participants\": \"Participants\",\n  \"Pick profile color\": \"Pick profile color\",\n  \"Read more about Audio Chat\": \"Read more about Audio Chat\",\n  \"refresh users\": \"refresh users\",\n  \"Role:\": \"Role:\",\n  \"Save\": \"Save\",\n  \"Saved!\": \"Saved!\",\n  \"See <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>this page</a>for more information and a list of supported browsers.\": \"See <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>this page</a>for more information and a list of supported browsers.\",\n  \"Send the above link to a friend so they can join your session!  You can find this invite link on the TOOL_NAME dock as well.\": \"Send the above link to a friend so they can join your session!  You can find this invite link on the TOOL_NAME dock as well.\",\n  \"Set up your avatar, name and user color above.  If you'd like to update it later, you can click your Profile button.\": \"Set up your avatar, name and user color above.  If you'd like to update it later, you can click your Profile button.\",\n  \"Settings and Profile\": \"Settings and Profile\",\n  \"Sorry\": \"Sorry\",\n  \"Status:\": \"Status:\",\n  \"Talking on your microphone through your web browser is an experimental feature.\": \"Talking on your microphone through your web browser is an experimental feature.\",\n  \"This is you\": \"This is you\",\n  \"to\": \"to\",\n  \"TOOL_NAME is a service for your website that makes it easy to collaborate in real-time on SITE_NAME\": \"TOOL_NAME is a service for your website that makes it easy to collaborate in real-time on SITE_NAME\",\n  \"Try TOOL_NAME Anyway\": \"Try TOOL_NAME Anyway\",\n  \"Turn on microphone\": \"Turn on microphone\",\n  \"Type your message here\": \"Type your message here\",\n  \"Unsupported Browser\": \"Unsupported Browser\",\n  \"Update avatar\": \"Update avatar\",\n  \"Update Name\": \"Update Name\",\n  \"Update your name\": \"Update your name\",\n  \"We're sorry, TOOL_NAME doesn't work with this browser.  Please <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>upgrade to a supported browser</a> to try TOOL_NAME.\": \"We're sorry, TOOL_NAME doesn't work with this browser.  Please <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>upgrade to a supported browser</a> to try TOOL_NAME.\",\n  \"We need your help fixing TogetherJS on Internet Explorer!  Here are a list of IE <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">GitHub issues</a> we need fixed that you can work on.\": \"We need your help fixing TogetherJS on Internet Explorer!  Here are a list of IE <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">GitHub issues</a> we need fixed that you can work on.\",\n  \"When your friends join you in your TOOL_NAME session, you can chat with them here!\": \"When your friends join you in your TOOL_NAME session, you can chat with them here!\",\n  \"Would you like to join their session?\": \"Would you like to join their session?\",\n  \"Yes, join session\": \"Yes, join session\",\n  \"You can continue to try to use TOOL_NAME, but you are likely to hit lots of bugs.  So be warned.\": \"You can continue to try to use TOOL_NAME, but you are likely to hit lots of bugs.  So be warned.\",\n  \"You can invite more friends to the session by sending the invite link in the TOOL_NAME dock.\": \"You can invite more friends to the session by sending the invite link in the TOOL_NAME dock.\",\n  \"You\": \"You\",\n  \"you\": \"you\",\n  \"You're using TOOL_NAME!\": \"You're using TOOL_NAME!\",\n  \"Your friend has asked you to join their TOOL_SITE_LINK browser session to collaborate in real-time!\": \"Your friend has asked you to join their TOOL_SITE_LINK browser session to collaborate in real-time!\"\n}\n"
  },
  {
    "path": "togetherjs/locale/es-BO.json",
    "content": "{\n  \"Activate your <strong>browser microphone</strong> near your URL bar above.\": \"Activa tu <strong>microfono del navegador</strong> cerca de la barra de direcciones en la parte superior.\",\n  \"Add a friend\": \"Agrega un amigo\",\n  \"Alright, you're ready to use TOOL_NAME. Now start collaborating on SITE_NAME!\": \"Bien, estás listo para usar TOOL_NAME. Ahora empieza a colaborar en SITE_NAME!\",\n  \"anyone\": \"cualquiera\",\n  \"Are you sure you'd like to end your TOOL_NAME session?\": \"Estás seguro de terminar tu sesión en TOOL_NAME?\",\n  \"Audio chat requires you to use a <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>newer browser</a>!\": \"Audio chat requiere que uses un <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>navegador moderno!</a>!\",\n  \"Audio Chat\": \"Audio Chat\",\n  \"Cancel\": \"Cancelar\",\n  \"Change avatar\": \"Cambiar avatar\",\n  \"Change your avatar, name and user color using the Profile button.\": \"Cambia tu avatar, nombre y color de usuario usando el boton de Perfil.\",\n  \"Chat\": \"Chat\",\n  \"Close\": \"Cerrar\",\n  \"Copy and paste this link into IM or email to invite friends.\": \"Copia y pega este link en tu mensajería o email para invitar amigos.\",\n  \"Copy and paste this link over IM or email:\": \"Copia y pega este link en tu mensajería o email:\",\n  \"Currently at:\": \"Actualmente en:\",\n  \"declined to join the session.\": \"rechazo unirse a la sesión.\",\n  \"Don't show again.\": \"No volver a mostrar.\",\n  \"End session\": \"Terminar sesión\",\n  \"End session?\": \"Terminar sesión?\",\n  \"End TOOL_NAME\": \"Terminar TOOL_NAME\",\n  \"End\": \"Fin\",\n  \"Enter your name\": \"Ingresa tu nombre\",\n  \"Feedback\": \"Retroalimentación\",\n  \"Follow this participant:\": \"Sigue este participante:\",\n  \"Follow:\": \"Sigue:\",\n  \"Following to new URL...\": \"Siguiendo a new URL...\",\n  \"Following\": \"Siguiendo\",\n  \"Friends who join your TOOL_NAME session will appear here. You can click their avatars to see more.\": \"Los amigos que se unan a tu sesión de TOOL_NAME aparecerán aquí. Puedes hacer click en su avatar para ver más.\",\n  \"has gone to:\": \"se fue a:\",\n  \"has invited\": \"ha invitado\",\n  \"Help\": \"Ayuda\",\n  \"here\": \"aqui\",\n  \"I'm ready!\": \"Estoy listo!\",\n  \"If your browser supports it, click the microphone icon to begin an audio chat. Learn more about this experimental feature <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">here</a>.\": \"Si tu navegador soporta, haz click en el ícono de microfono para iniciar audio chat. Aprende más sobre esta característica experimental <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">aquí</a>.\",\n  \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">is currently not supported</a>. If you do want to try out TogetherJS, we'd suggest using Firefox or Chrome.\": \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">no cuenta con soporte actualmente</a>. Si deseas probar TogetherJS, sugerimos que uses Firefox o Chrome.\",\n  \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> is not supported</a> and won't be supported in the near term, please use Firefox or Chrome.\": \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> no tiene soporte</a> y no lo tendra en un tiempo cercano, por favor usa Firefox o Chrome.\",\n  \"Invite a friend\": \"Invita a un amigo\",\n  \"Invite anyone\": \"Invita a cualquiera\",\n  \"is on the same page as you.\": \"esta en la misma página que tú.\",\n  \"Join them\": \"Únete a ellos\",\n  \"Join TOOL_NAME session?\": \"Unirse a la sesión TOOL_NAME?\",\n  \"joined the session.\": \"se unió a la sesión.\",\n  \"left the session.\": \"dejo la sesión.\",\n  \"Live audio chat requires a newer (or different) browser than you're using.\": \"Audio chat en vivo necesita un nuevo (o diferente) navegador del que estás usando.\",\n  \"Loading form...\": \"cargando desde...\",\n  \"Move the dock\": \"Mover el panel\",\n  \"names\": \"Zorro Amigable, Castor Brillante, Buho Observador, Girafa Sociable, Lobo Salvaje, Foca Silenciosa, Ballena Graciosa, Gato Curioso, Iguana Inteligente\",\n  \"No one else is here.\": \"Nadie más está aquí.\",\n  \"No, don't join\": \"No, no unirse\",\n  \"Nudge them\": \"Zúmbalos\",\n  \"OK\": \"OK\",\n  \"or\": \"o\",\n  \"Participants\": \"Participantes\",\n  \"Pick profile color\": \"Escoge un color de perfil\",\n  \"Read more about Audio Chat\": \"Lee más sobre Audio Chat\",\n  \"refresh users\": \"refrescar usuarios\",\n  \"Role:\": \"Rol:\",\n  \"Save\": \"Guardar\",\n  \"Saved!\": \"Guardado!\",\n  \"See <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>this page</a>for more information and a list of supported browsers.\": \"Visita <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>esta página</a> para más información y una lista de los navegadores soportados.\",\n  \"Send the above link to a friend so they can join your session! You can find this invite link on the TOOL_NAME dock as well.\": \"Envia el link superior a un amigo para que puedan unirse a tu sesión! También puedes encontrar el link de invitación en el panel de TOOL_NAME.\",\n  \"Set up your avatar, name and user color above. If you'd like to update it later, you can click your Profile button.\": \"Configura tu avatar, nombre y color de usuario en la parte superior. Si deseas actualizarlo luego, puedes hacer click en el boton de perfil.\",\n  \"Settings and Profile\": \"Configuraciones y Perfil\",\n  \"Sorry\": \"Lo siento\",\n  \"Status:\": \"Estado:\",\n  \"Talking on your microphone through your web browser is an experimental feature.\": \"Hablar con tu microfono sobre un navegador es una tecnología experimental.\",\n  \"This is you\": \"Este eres tú\",\n  \"to\": \"para\",\n  \"TOOL_NAME is a service for your website that makes it easy to collaborate in real-time on SITE_NAME\": \"TOOL_NAME es un servicio para tu sitio web que hace fácil colaborar en tiempo real en SITE_NAME\",\n  \"Try TOOL_NAME Anyway\": \"Prueba TOOL_NAME de todas formas\",\n  \"Turn on microphone\": \"Enciende tu microfono\",\n  \"Type your message here\": \"Escribe tu mensaje aquí\",\n  \"Unsupported Browser\": \"Navegador sin soporte\",\n  \"Update avatar\": \"Actualizar avatar\",\n  \"Update Name\": \"Actualizar nombre\",\n  \"Update your name\": \"Actualiza tu nombre\",\n  \"We're sorry, TOOL_NAME doesn't work with this browser. Please <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>upgrade to a supported browser</a> to try TOOL_NAME.\": \"Lo sentimos, TOOL_NAME no funciona en este navegador. Por favor <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>actualiza a un  navegador con soporte</a> para probar TOOL_NAME.\",\n  \"We need your help fixing TogetherJS on Internet Explorer! Here are a list of IE <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">GitHub issues</a> we need fixed that you can work on.\": \"Necesitamos ayuda para corregir TogetherJS en Internet Explorer! Aquí hay una lista de <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">problemas</a> en IE que necesitamos corregir y tú puedes trabajar en ellos.\",\n  \"When your friends join you in your TOOL_NAME session, you can chat with them here!\": \"When your friends join you in your TOOL_NAME session, you can chat with them here!\",\n  \"Would you like to join their session?\": \"Deseas unirte a su sesión?\",\n  \"Yes, join session\": \"Sí, unirse a la sesión\",\n  \"You can continue to try to use TOOL_NAME, but you are likely to hit lots of bugs. So be warned.\": \"You can continue to try to use TOOL_NAME, but you are likely to hit lots of bugs. So be warned.\",\n  \"You can invite more friends to the session by sending the invite link in the TOOL_NAME dock.\": \"Puedes invitar más amigos a la sesión enviándoles el link de invitación en el panel de TOOL_NAME.\",\n  \"You\": \"Ustedes\",\n  \"you\": \"tú\",\n  \"You're using TOOL_NAME!\": \"Estas usando TOOL_NAME!\",\n  \"Your friend has asked you to join their TOOL_SITE_LINK browser session to collaborate in real-time!\": \"Tu amigo a solicitado que lo unas en su TOOL_SITE_LINK sesión de navegador para colaborar en tiempo real!\"\n}\n"
  },
  {
    "path": "togetherjs/locale/pl-PL.json",
    "content": "{\n  \"Activate your <strong>browser microphone</strong> near your URL bar above.\": \"Aktywuj swój <strong>mikrofon przeglądarki</strong> w pobliżu paska adresu, powyżej.\",\n  \"Add a friend\": \"Dodaj znajomego\",\n  \"Alright, you're ready to use TOOL_NAME. Now start collaborating on SITE_NAME!\": \"W porządku, możesz już używać TOOL_NAME. Zacznij współpracować nad SITE_NAME!\",\n  \"anyone\": \"kogokolwiek\",\n  \"Are you sure you'd like to end your TOOL_NAME session?\": \"Czy na pewno chcesz zakończyć swoją sesję w TOOL_NAME?\",\n  \"Audio chat requires you to use a <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>newer browser</a>!\": \"Aby użyć rozmowy głosowej, potrzebujesz <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>nowszej przeglądarki</a>!\",\n  \"Audio Chat\": \"Rozmowa głosowa\",\n  \"Cancel\": \"Anuluj\",\n  \"Change avatar\": \"Zmień zdjęcie\",\n  \"Change your avatar, name and user color using the Profile button.\": \"Zmień swoje zdjęcie, imię i kolor, używając przycisku 'Profil'.\",\n  \"Chat\": \"Czat\",\n  \"Close\": \"Zamknij\",\n  \"Copy and paste this link into IM or email to invite friends.\": \"Skopiuj ten adres i wklej w komunikatorze lub wiadomości email, aby zaprosić znajomych.\",\n  \"Copy and paste this link over IM or email:\": \"Skopiuj ten adres i wklej w komunikatorze lub wiadomości email:\",\n  \"Currently at:\": \"Obecnie na:\",\n  \"declined to join the session.\": \"odrzucił zaproszenie.\",\n  \"Don't show again.\": \"Nie pokazuj ponownie.\",\n  \"End session\": \"Zakończ sesję\",\n  \"End session?\": \"Zakończ sesję?\",\n  \"End TOOL_NAME\": \"Zakończ TOOL_NAME\",\n  \"End\": \"Zakończ\",\n  \"Enter your name\": \"Podaj swoje imię\",\n  \"Feedback\": \"Uwagi\",\n  \"Follow this participant:\": \"Podążaj za tą osobą:\",\n  \"Follow:\": \"Podążaj:\",\n  \"Following to new URL...\": \"Podążam do nowej strony...\",\n  \"Following\": \"Podążam\",\n  \"Friends who join your TOOL_NAME session will appear here.  You can click their avatars to see more.\": \"Twoi znajomi, którzy dołączą do Twojej sesji TOOL_NAME będą widoczni tutaj.  Możesz kliknąć ich zdjęcia aby zobaczyć więcej na ich temat.\",\n  \"has gone to:\": \"przeszedł do:\",\n  \"has invited\": \"zaprosił\",\n  \"Help\": \"Pomoc\",\n  \"here\": \"tutaj\",\n  \"I'm ready!\": \"Jestem gotowy!\",\n  \"If your browser supports it, click the microphone icon to begin an audio chat. Learn more about this experimental feature <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">here</a>.\": \"Jeśli Twoja przeglądarka wspiera tą technologię, kliknij ikonę mikrofonu, aby zacząć rozmowę głosową. Dowiedz się więcej na temat tej eksperymentalnej technologii <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">tutaj</a>.\",\n  \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">is currently not supported</a>.  If you do want to try out TogetherJS, we'd suggest using Firefox or Chrome.\": \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">obecnie nie jest wspierany</a>.  Jeśli mimo to chcesz wypróbować TogetherJS, polecamy przeglądarkę Firefox lub Chrome.\",\n  \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> is not supported</a> and won't be supported in the near term, please use Firefox or Chrome.\": \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> nie jest wspierany</a> i nie będzie w najbliższej przyszłości - użyj proszę przeglądarki Firefox lub Chrome.\",\n  \"Invite a friend\": \"Zaproś znajomego\",\n  \"Invite anyone\": \"Zaproś kogokolwiek\",\n  \"is on the same page as you.\": \"na tej samej stronie co Ty.\",\n  \"Join them\": \"Dołącz\",\n  \"Join TOOL_NAME session?\": \"Dołączyć do sesji TOOL_NAME?\",\n  \"joined the session.\": \"dołączył do sesji.\",\n  \"left the session.\": \"left the session.\",\n  \"Live audio chat requires a newer (or different) browser than you're using.\": \"Rozmowa głosowa wymaga nowszej (lub innej) przeglądarki, niż ta, której używasz.\",\n  \"Loading form...\": \"Ładowanie formularza...\",\n  \"Move the dock\": \"Przesuń pasek\",\n  \"names\": \"Przyjazny Pingwin, Czujna Czajka, Ryży Ryś, Przebiegła Pantera, Błogi Bóbr, Puchaty Puchacz, Bohaterski Borsuk, Mądra Mysz, Łasa Łasica\",\n  \"No one else is here.\": \"Nie ma tu nikogo innego.\",\n  \"No, don't join\": \"Nie dołączaj\",\n  \"Nudge them\": \"Zaczep ich\",\n  \"OK\": \"OK\",\n  \"or\": \"lub\",\n  \"Participants\": \"Uczestnicy\",\n  \"Pick profile color\": \"Wybierz kolor profilu\",\n  \"Read more about Audio Chat\": \"Dowiedz wię więcej o rozmowie głosowej\",\n  \"refresh users\": \"odśwież listę uczestników\",\n  \"Role:\": \"Rola:\",\n  \"Save\": \"Zapisz\",\n  \"Saved!\": \"Zapisano!\",\n  \"See <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>this page</a>for more information and a list of supported browsers.\": \"Przeczytaj <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>tą stronę</a> Aby dowiedzieć się więcej i poznać listę wspieranych przeglądarek.\",\n  \"Send the above link to a friend so they can join your session!  You can find this invite link on the TOOL_NAME dock as well.\": \"Prześlij powyższy link znajomemu, żeby mógł dołączyć do Twojej sesji! Możesz znaleźć link zapraszający również na pasku TOOL_NAME.\",\n  \"Set up your avatar, name and user color above.  If you'd like to update it later, you can click your Profile button.\": \"Powyżej możesz ustawić swoje zdjęcie, imię i kolor. Możesz zrobić to też później, klikając przycisk swojego profilu.\",\n  \"Settings and Profile\": \"Ustawienia i Profil\",\n  \"Sorry\": \"Przykro nam\",\n  \"Status:\": \"Stan:\",\n  \"Talking on your microphone through your web browser is an experimental feature.\": \"Rozmowa głosowa przez przeglądarkę jest eksperymentalną funkjconalnością.\",\n  \"This is you\": \"to Ty\",\n  \"to\": \"do\",\n  \"TOOL_NAME is a service for your website that makes it easy to collaborate in real-time on SITE_NAME\": \"TOOL_NAME jest usługą dla Twojej strony, która umożliwia łatwą współpracę w czasie rzeczywistym na stronie SITE_NAME\",\n  \"Try TOOL_NAME Anyway\": \"Mimo to, wybróbuj TOOL_NAME\",\n  \"Turn on microphone\": \"Włącz mikrofon\",\n  \"Type your message here\": \"Wpisz tutaj swoją wiadomość\",\n  \"Unsupported Browser\": \"Niewspierana przeglądarka\",\n  \"Update avatar\": \"Zmień zdjęcie\",\n  \"Update Name\": \"Zmień imię\",\n  \"Update your name\": \"Zmień swoje imię\",\n  \"We're sorry, TOOL_NAME doesn't work with this browser.  Please <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>upgrade to a supported browser</a> to try TOOL_NAME.\": \"Przykto nam, TOOL_NAME nie działa w tej przeglądarce. <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>Zaktualizuj do wspieranej przeglądarki</a> żeby móc użyć TOOL_NAME.\",\n  \"We need your help fixing TogetherJS on Internet Explorer!  Here are a list of IE <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">GitHub issues</a> we need fixed that you can work on.\": \"Potrzebujemy Twojej pomocy w przygotowaniu TogetherJS pod Internet Explorera!  Tutaj znajdziesz listę <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">zgłoszeń GitHub</a> związanych z IE, które muszą być naprawione zanim będzie można używać narzędzia pod tą przeglądarką.\",\n  \"When your friends join you in your TOOL_NAME session, you can chat with them here!\": \"Kiedy Twoi znajomi dołączą do Ciebie w Twojej sesji TOOL_NAME, w tym miejscu będziesz mógł z nimi rozmawiać!\",\n  \"Would you like to join their session?\": \"Czy chcesz dołączyć do jego sesji?\",\n  \"Yes, join session\": \"Tak, dołącz do sesji\",\n  \"You can continue to try to use TOOL_NAME, but you are likely to hit lots of bugs.  So be warned.\": \"Możesz używać TOOL_NAME, ale uwaga: najprawdopodobniej natrafisz na wiele problemów z działaniem.\",\n  \"You can invite more friends to the session by sending the invite link in the TOOL_NAME dock.\": \"Możesz zaprosić więcej znajomych do sesji, wysyłając im link poprzez pasek TOOL_NAME.\",\n  \"You\": \"Ty\",\n  \"you\": \"Cię\",\n  \"You're using TOOL_NAME!\": \"Używasz TOOL_NAME!\",\n  \"Your friend has asked you to join their TOOL_SITE_LINK browser session to collaborate in real-time!\": \"Twój znajomy zaprosił Cię do współpracy w czasie rzeczywistym na stronie TOOL_SITE_LINK!\"\n}\n"
  },
  {
    "path": "togetherjs/locale/ru.json",
    "content": "{\n    \"Follow:\": \"Последовать:\",\n    \"declined to join the session.\": \"отказался присоединиться к сеансу.\",\n    \"Yes, join session\": \"Да, присоединиться к сеансу\",\n    \"left the session.\": \"покинул сеанс.\",\n    \"Live audio chat requires a newer (or different) browser than you're using.\": \"Для живого аудио-чата требуется более новый (или другой) браузер, чем тот, который Вы используете.\",\n    \"Saved!\": \"Сохранено!\",\n    \"Role:\": \"Роль:\",\n    \"Would you like to join their session?\": \"Хотели бы Вы присоединиться к его сеансу?\",\n    \"I'm ready!\": \"Я готов!\",\n    \"Loading form...\": \"Загружаю форму ...\",\n    \"End TOOL_NAME\": \"Закончить TOOL_NAME\",\n    \"to\": \"на\",\n    \"You're using TOOL_NAME!\": \"Вы используете TOOL_NAME!\",\n    \"Activate your <strong>browser microphone</strong> near your URL bar above.\": \"Включите <strong>микрофон браузера</strong> возле адресной строки вверху.\",\n    \"Invite anyone\": \"Пригласить кого-нибудь\",\n    \"Currently at:\": \"Сейчас на:\",\n    \"you\": \"Вас\",\n    \"OK\": \"Хорошо\",\n    \"Help\": \"Помощь\",\n    \"No one else is here.\": \"Здесь больше никого нет.\",\n    \"Set up your avatar, name and user color above.  If you'd like to update it later, you can click your Profile button.\": \"Задайте свои аватар, имя и пользовательский цвет вверху. При желании изменить их позднее, щёлкните по кнопке Профиль.\",\n    \"Update Name\": \"Обновить имя\",\n    \"Unsupported Browser\": \"Браузер не поддерживается\",\n    \"Settings and Profile\": \"Установки и профиль\",\n    \"End\": \"Закончить\",\n    \"When your friends join you in your TOOL_NAME session, you can chat with them here!\": \"Когда Ваши друзья присоединятся к Вашему сеансу TOOL_NAME, Вы сможете общаться с ними здесь!\",\n    \"Join TOOL_NAME session?\": \"Присоединиться к сеансу TOOL_NAME?\",\n    \"Add a friend\": \"Добавить друга\",\n    \"We need your help fixing TogetherJS on Internet Explorer!  Here are a list of IE <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">GitHub issues</a> we need fixed that you can work on.\": \"Нам нужна Ваша помощь в починке TogetherJS на Internet Explorer!  Вот список <a href=\\\"https://github.com/mozilla/togetherjs/issues?labels=IE&milestone=&page=1&state=open\\\" target=\\\"_blank\\\">ошибок на GitHub</a>, которые нам нужно починить, и над которыми Вы можете поработать.\",\n    \"Save\": \"Сохранить\",\n    \"is on the same page as you.\": \"с Вами на одной странице.\",\n    \"Join them\": \"Присоединиться к нему\",\n    \"Friends who join your TOOL_NAME session will appear here.  You can click their avatars to see more.\": \"Друзья, которые присоединятся к Вашему сеансу TOOL_NAME, появятся здесь. Вы можете щёлкнуть по аватару друга, чтобы увидеть больше информации.\",\n    \"See <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>this page</a>for more information and a list of supported browsers.\": \"Посмотрите на <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>'этой странице'</a> дополнительную информацию и список поддерживаемых браузеров.\",\n    \"Alright, you're ready to use TOOL_NAME. Now start collaborating on SITE_NAME!\": \"Ну вот Вы и готовы использовать TOOL_NAME. Теперь начинайте сотрудничать на сайте SITE_NAME!\",\n    \"Read more about Audio Chat\": \"Почитайте больше об аудио-чате\",\n    \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\">is currently not supported</a>.  If you do want to try out TogetherJS, we'd suggest using Firefox or Chrome.\": \"Internet Explorer <a href=\\\"https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer\\\"> в настоящее время не поддерживается</a>.  Если Вы действительно хотите испытать TogetherJS, советуем Вам использовать Firefox или Chrome.\",\n    \"here\": \"здесь\",\n    \"Status:\": \"Статус:\",\n    \"Your friend has asked you to join their TOOL_SITE_LINK browser session to collaborate in real-time!\": \"Ваш друг просит Вас присоединиться к его TOOL_SITE_LINK браузер-сеансу, чтобы сотрудничать с Вами в реальном времени!\",\n    \"Copy and paste this link into IM or email to invite friends.\": \"Скопируйте и приклейте эту ссылку в IM или в имейл, чтобы пригласить друзей.<br>\",\n    \"Chat\": \"Чат\",\n    \"You can continue to try to use TOOL_NAME, but you are likely to hit lots of bugs.  So be warned.\": \"Вы можете продолжать пробовать использовать TOOL_NAME, но скорее всего Вы получите массу ошибок. Мы Вас предупредили.\",\n    \"Copy and paste this link over IM or email:\": \"Скопируйте эту ссылку и приклейте её в IM или в имейл:\",\n    \"or\": \"или\",\n    \"This is you\": \"Это Вы\",\n    \"Pick profile color\": \"Выбрать цвет профиля\",\n    \"If your browser supports it, click the microphone icon to begin an audio chat. Learn more about this experimental feature <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">here</a>.\": \"Если Ваш браузер поддерживает аудио-чат, Вы можете запустить его нажатием на иконку микрофона. Узнайте побольше об этой экспериментальной функции <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">здесь</a>.\",\n    \"Move the dock\": \"Передвинуть панель\",\n    \"Participants\": \"Участники\",\n    \"names\": \"Лысый Лис, Большой Бобёр, Умная Сова, Жирный Жираф, Серый Волк, Толстый Тюлень, Рыба-кит, Кисьян Котяра, Известная Игуана\",\n    \"Change avatar\": \"Изменить аватар\",\n    \"Sorry\": \"Извините\",\n    \"has invited\": \"пригласил\",\n    \"anyone\": \"кого-либо\",\n    \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> is not supported</a> and won't be supported in the near term, please use Firefox or Chrome.\": \"Internet Explorer <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#internet-explorer'> не поддерживается</a> и не будет поддерживаем в ближайшем будущем, просьба использовать Firefox или Chrome.\",\n    \"You can invite more friends to the session by sending the invite link in the TOOL_NAME dock.\": \"Вы можете пригласить ещё друзей на Ваш сеанс, послав им ссылку с приглашением на панели TOOL_NAME.\",\n    \"refresh users\": \"освежить пользователей\",\n    \"has gone to:\": \"отправился на:\",\n    \"Turn on microphone\": \"Включить микрофон\",\n    \"Try TOOL_NAME Anyway\": \"Всё равно попробовать TOOL_NAME\",\n    \"Following\": \"Следую\",\n    \"Don't show again.\": \"Больше не показывать.\",\n    \"We're sorry, TOOL_NAME doesn't work with this browser.  Please <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>upgrade to a supported browser</a> to try TOOL_NAME.\": \"Извините, TOOL_NAME не работает на этом браузере. Просьба <a href='https://github.com/mozilla/togetherjs/wiki/Supported-Browsers#supported-browsers'>обновиться до поддерживаемого браузера</a>, чтобы попробовать TOOL_NAME.\",\n    \"Feedback\": \"Отзывы и предложения\",\n    \"No, don't join\": \"Нет, не присоединяться\",\n    \"Type your message here\": \"Напечатайте своё сообщение здесь\",\n    \"Nudge them\": \"Толкнуть друга\",\n    \"Cancel\": \"Отмена\",\n    \"Close\": \"Закрыть\",\n    \"End session?\": \"Закончить сеанс?\",\n    \"joined the session.\": \"присоединился к сеансу.\",\n    \"Update avatar\": \"Обновить аватар\",\n    \"End session\": \"Закончить сеанс\",\n    \"Invite a friend\": \"Пригласить друга\",\n    \"You\": \"Вы\",\n    \"Enter your name\": \"Введите своё имя\",\n    \"Audio Chat\": \"Аудио-чат\",\n    \"Audio chat requires you to use a <a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>newer browser</a>!\": \"Аудио-чат требует, чтобы Вы использовали<a href='https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC' target='_blank'>браузер поновее</a>!\",\n    \"Update your name\": \"Обновить своё имя\",\n    \"Send the above link to a friend so they can join your session!  You can find this invite link on the TOOL_NAME dock as well.\": \"Пошлите другу ссылку вверху, чтобы он мог присоединиться к Вашему сеансу! Вы также можете найти эту ссылку с приглашением на панели TOOL_NAME.\",\n    \"Change your avatar, name and user color using the Profile button.\": \"Вы можете изменить свои аватар, имя и пользовательский цвет, используя кнопку Профиль.\",\n    \"Are you sure you'd like to end your TOOL_NAME session?\": \"Вы уверены, что хотите завершить свой сеанс TOOL_NAME?\",\n    \"Follow this participant:\": \"Следовать за этим участником:\",\n    \"Following to new URL...\": \"Следую на новый URL...\",\n    \"TOOL_NAME is a service for your website that makes it easy to collaborate in real-time on SITE_NAME\": \"TOOL_NAME - это служба для Вашего сайта, которая помогает Вам сотрудничать с другими в реальном времени на сайте SITE_NAME\",\n    \"Talking on your microphone through your web browser is an experimental feature.\": \"Разговор по микрофону через веб-браузер - экспериментальное свойство.\"\n}"
  },
  {
    "path": "togetherjs/mobile.less",
    "content": "/*TogetherJS dock*/\n#togetherjs-dock {\n  &.togetherjs-dock-right {\n    top: 0px;\n    width: auto;\n    height: 40px !important;\n    right: 0px;\n    margin: 10px;\n    bottom: 0px;\n  }\n  \n  #togetherjs-dock-anchor {\n    width: 40px;\n    height: 40px;\n    float: right;\n    user-select: all;\n    cursor: default;\n    display: inline;\n  }\n  \n  #togetherjs-buttons {\n    display: inline;\n  }\n  \n  .togetherjs-button {\n    float: right;\n    border-right: 1px solid rgba(0,0,0,0.2);\n    border-top: none;\n    width: 40px;\n    height: 40px;\n    background-size: 30px 30px;\n  }\n  \n  #togetherjs-profile-arrow {\n    display: none;\n  }\n  \n  #togetherjs-dock-anchor-horizontal img {\n    width: 24px;\n    height: 24px;\n    padding: 8px;\n  }\n  \n}\n\n\n.togetherjs-only-mobile {\n  display: block;\n  text-align: center;\n  \n/*  a.togetherjs-share-link {\n    padding: 6px 111px 6px;\n  }*/\n  \n  \n}\n\n\n.togetherjs-not-mobile {\n  display: none;\n}\n\n.togetherjs {\n  \n  .togetherjs-menu-item {\n    cursor: pointer;\n    margin: 0px -14px 0px;\n    padding: 9px;\n    border-bottom: 1px solid rgba(0,0,0,0.2);\n  }\n  \n  #togetherjs-menu-feedback-button, #togetherjs-menu-update-color-button, #togetherjs-menu-help-button {\n    display: none;\n  }\n  \n  .togetherjs-menu-item img {\n    display: none;\n  }\n  \n  .togetherjs-menu-item:first-child {\n    display: none;\n  }\n  \n  .togetherjs-button .togetherjs-person {\n    margin: 0 0 0 5px;\n  }\n  \n  .togetherjs-person {\n    background-size: 30px 30px;\n    height: 26px;\n    width: 26px;\n  }\n  \n  .togetherjs-person-avatar-swatch {\n    margin-left: 12px;\n  }\n\n  .togetherjs-window {\n    width: 100%;\n    margin-left: 0;\n    height: 82%;\n    margin-top: 0%;\n    z-index: @z-index+3 !important;\n    top: 20%;\n    left: -2px;\n    \n    #togetherjs-chat-messages {\n     width: 105%; \n    }\n    \n    .togetherjs-close {\n     display: none;\n    }\n    \n    #togetherjs-chat-messages {\n      height: 62%;\n      top: -37px;\n    }\n    \n  }\n  \n  .togetherjs-subtitle {\n    width: 98%;\n    margin: 22px 7px;\n  }\n  \n  #togetherjs-chat-input-box {\n    width: 100%;\n    bottom: 0px;\n    position: fixed;\n  }\n  \n  #togetherjs-chat-input {\n    width: 95%;\n  }\n  \n  .togetherjs-timestamp {\n   padding: 8px 45px 0px 10px;\n  }\n  \n  #togetherjs-rtc-not-supported section.togetherjs-buttons {\n    display: none;\n  }\n  \n  #togetherjs-menu-window section.togetherjs-buttons {\n    display: none;\n  }\n\n  .togetherjs-modal {\n    width: 94%;\n    margin-left: 1%;\n    height: 94%;\n    margin-top: 1%;\n    top: 0;\n    left: 0;\n  }\n  \n  .togetherjs-window > header {\n    margin: -7px;\n    padding: 10px;\n  }\n}\n\n#togetherjs-dock-participants {\n  display: none;\n}\n\n#togetherjs-confirm-end section.togetherjs-buttons {\n  position: fixed;\n  bottom: 0;\n  width: 92%;\n}\n\n#togetherjs-edit-name-window section.togetherjs-buttons {\n  position: fixed;\n  bottom: 0;\n  width: 96%;\n}\n\ninput.togetherjs-self-name {\n  padding: 10px;\n  width: 92%;\n  margin-top: 10px;\n}\n\n#togetherjs-avatar-edit section.togetherjs-buttons {\n  position: fixed;\n  bottom: 0;\n  width: 92%;\n}\n\n#togetherjs-avatar-edit .togetherjs-person {\n  margin: 30px auto;\n  float: none;\n}\n\n#togetherjs-avatar-edit #togetherjs-avatar-buttons {\n  float: none;\n  margin: 0 auto;\n}\n\n#togetherjs-window-pointer-right, #togetherjs-window-pointer-left {\n  position: fixed;\n  width: 10px;\n  height: 10px;\n  margin-right: -5px;\n  margin-top: -5px;\n  background: #fff;\n  border-right: 1px solid rgba(0,0,0,0.2);\n  border-bottom: 1px solid rgba(0,0,0,0.2);\n  z-index: @z-index + 2;\n  box-shadow: 1px 1px 1px rgba(0,0,0,0.1);\n}\n#togetherjs-window-pointer-right {\n  -moz-transform: rotate(-45deg);\n  -webkit-transform: rotate(-45deg);\n}\n#togetherjs-window-pointer-left {\n  -moz-transform: rotate(135deg);\n  -webkit-transform: rotate(135deg);\n}\n\n\n\n/*TogetherJS walkthrough*/\n\n.togetherjs .togetherjs-modal section {\nmargin: 0px 7px;\n}\n\n\n#togetherjs-walkthrough-progress {\n  width: 93%;\n  text-align:center;\n  position: static;\n}\n\n.togetherjs-modal-wide section.togetherjs-buttons {\n  width: 93.9%;\n  text-align: center !important;\n  position: absolute;\n  bottom: -17px;\n}\n\n.togetherjs-walkthrough-slide p {\n  margin:13px auto;\n  width: 100%;\n  font-size: 11px;\n}\n\n.togetherjs .togetherjs-walkthrough-main-image {\n  width: auto;\n  height: auto;\n  background: rgba(216, 216, 216, 0.1);\n  border-radius: 4px;\n  border: 1px solid \n  rgba(151, 151, 151, 0.1);\n  padding: 10px;\n}\n\n.togetherjs .togetherjs-walkthrough-main-image img {\n  width: 50%;\n  height: auto;\n}\n\n.togetherjs #togetherjs-walkthrough-next {\n  cursor: pointer;\n  width: 19px;\n  height: 36px;\n  background-repeat: no-repeat;\n  background-size: 60% 60%;\n  margin-right: 0px;\n  margin-top: 28%;\n  background-image: url('./images/icn-walkthrough-arrow-r.png');\n  float: right;\n}\n\n.togetherjs #togetherjs-walkthrough-previous {\n  cursor: pointer;\n  width: 19px;\n  height: 36px;\n  background-repeat: no-repeat;\n  background-size: 60% 60%;\n  margin-top: 28%;\n  background-image: url('./images/icn-walkthrough-arrow-l.png');\n  float: left;\n  margin-left: 0px;\n}\n\n.togetherjs .togetherjs-modal .togetherjs-share-link {\n  width: 80%;\n  font-size: 14px;\n  padding: 14px;\n  border-radius: 4px;\n  border: 1px solid \n  #cccccc;\n  box-shadow: inset 0 2px 2px rgba(0, 0, 0, 0.1);\n  font-family: Monaco;\n  margin: 7px 0px;\n}\n\n.togetherjs-walkthrough-sendlink {\n  top: 44%;\n  position: relative;\n  padding: 15px;\n}\n\n.togetherjs section.togetherjs-walkthrough-slide input.togetherjs-self-name {\n  position: absolute;\n  top: 50%;\n  left: 29%;\n  font-size: 14px;\n  padding: 6px 6px 6px;\n  border-radius: 4px 4px 4px 4px;\n  border: 1px solid \n  #cccccc;\n  box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.1) inset;\n  font-family: openSansRegular;\n  margin: -20px 11px;\n  width: 60%;\n}\n\n.togetherjs section.togetherjs-walkthrough-slide .togetherjs-walkthrough-main-image .togetherjs-walkthrough-avatar-section {\n  margin-top: 15px;\n}\n\n.togetherjs .togetherjs-avatar-preview {\n  margin: 0 auto;\n  float: none;\n}\n\n.togetherjs .togetherjs-avatar-upload-input {\n  margin: 10px auto;\n  float: none;\n}\n\n.togetherjs .togetherjs-avatar-upload-input input {\n  width: 60%;\n}\n\ninput.togetherjs-upload-avatar {\n  line-height: 0px;\n  width: 174px;\n  margin-left: 0px;\n}\n\n.togetherjs section.togetherjs-walkthrough-slide input.togetherjs-self-name {\n  float: left;\n  font-size: 14px;\n  padding: 6px 6px 6px;\n  border-radius: 4px 4px 4px 4px;\n  border: 1px solid \n  #cccccc;\n  box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.1) inset;\n  font-family: openSansRegular;\n  width: 66%;\n  position: static;\n  margin: 10px 10px;\n}\n\n.togetherjs section.togetherjs-walkthrough-slide .togetherjs-swatch {\n  width: 32px;\n  height: 32px;\n  background: none repeat scroll 0% 0% \n  #000000;\n  position: relative;\n  float: right;\n  right: 10px;\n  border-radius: 4px 4px 4px 4px;\n  border: 1px solid #cccccc;\n  top: 10px;\n}\n\n.togetherjs .togetherjs-save-settings {\n  margin-top: 20px;\n  margin-bottom: 0px;\n}\n\n// for larger devices\n\n@media (min-width: 480px) {\n  \n  .togetherjs-mobile-browser input.togetherjs-self-name {\n    width: 95%;\n    margin-top: 10px;\n  }\n  \n  .togetherjs .togetherjs-window {\n    width: 100%;\n    left: -2px !important;\n    top: 50%;\n  }\n  \n  .togetherjs-mobile-browser #togetherjs-edit-name-window section.togetherjs-buttons {\n    width: 99%;\n  }\n  \n/*  #togetherjs-dock.togetherjs-dock-right {\n    width: 27% !important; \n  }*/\n \n  #togetherjs-confirm-end section.togetherjs-buttons {\n   width: 96.6%;\n   position: absolute;\n   bottom: 0;\n  }\n\n  #togetherjs-edit-name-window section.togetherjs-buttons {\n   width: 99%;\n  }\n\n  input.togetherjs-self-name {\n   width: 94%;\n   margin-top: 10px;\n  }\n\n  #togetherjs-avatar-edit section.togetherjs-buttons {\n   width: 95.3%;\n   bottom: 0;\n   background: #F2F2F2;\n   padding: 10px;\n   text-align: right;\n   border-bottom-right-radius: 4px;\n   border-bottom-left-radius: 4px;\n   border-top: 1px solid #E1E1E1;\n   position: absolute;\n  }\n  \n  .togetherjs-modal {\n    width: 74% !important;\n    height: 50% !important;\n    margin: 20% 12% !important;\n  }\n  \n  .togetherjs-mobile-browser .togetherjs .togetherjs-modal {\n    width: 76% !important;\n    margin-left: 1%;\n    height: 94%;\n    margin-top: 1%;\n    top: 0;\n    left: 0;\n    height: 41%;\n    margin: 20% 11%;\n}\n  \n  .togetherjs-modal-wide section.togetherjs-buttons {\n    width: 97.4% !important;\n  }\n  \n}\n\n//for smaller devices\n@media (max-width: 480px) {\n  .togetherjs .togetherjs-window {\n    width: 96%;\n    margin-left: 0;\n    height: 82%;\n    margin-top: 0%;\n    z-index: @z-index+3 !important;\n    top: 20%;\n    left: -2px;\n\n    #togetherjs-chat-messages {\n     width: 105%; \n    }\n\n    .togetherjs-close {\n     display: none;\n    }\n\n    #togetherjs-chat-messages {\n      height: 62%;\n      top: -37px;\n    }\n  }\n  \n  #togetherjs-chat-input-box {\n    width: 94% !important;\n    bottom: 0px;\n    position: fixed;\n  }\n  \n  .togetherjs-timestamp {\n   padding: 8px 15px 0px 10px !important;\n  }\n  \n  input[type='text'],input[type='number'],textarea {font-size:16px !important;}\n  \n}\n"
  },
  {
    "path": "togetherjs/module-descriptions.json",
    "content": "{\n  \"analytics\": \"A small bit of code for handling Google Analytics\",\n  \"channels\": \"An abstraction over WebSockets and other communication channels (like `postMessage`).\",\n  \"chat\": \"Handles the chat messages (except actual display, which is in `ui.js`).\",\n  \"console\": \"An console replacement that collects messages and allows TogetherJS-specific log levels\",\n  \"cursor\": \"Handles the shared cursors, display and capturing the events.  Also handles clicks and scrolls.  Includes UI.\",\n  \"elementFinder\": \"Generates something like a CSS selector for an element, and finds said elements based on selectors.  A portable description of an element.\",\n  \"eventMaker\": \"Creates artificial events, like a fake click event.\",\n  \"forms\": \"Handles synchronization of forms, including CodeMirror, ACE, CKEditor and tinyMCE Editor support.  Implements a portion of OT.\",\n  \"jqueryPlugins\": \"Some plugins for jQuery; doesn't export anything, just patches `$`.\",\n  \"linkify\": \"Detects and adds links to plain text.\",\n  \"ot\": \"Operational transformation support: what keeps big chunks of text in sync when multiple people are simultaneously editing those fields.\",\n  \"peers\": \"Handles the objects representing the peers and oneself.\",\n  \"playback\": \"Handles the magic `/playback` command that plays recordings.\",\n  \"randomutil\": \"Some functions/methods for random numbers, really just for testing support.\",\n  \"recorder\": \"Used by `recorder.html`, which is a kind of alternate mini-client used to record sessions when you put `/record` in the chat box.\",\n  \"session\": \"The most important and most core module in the system.  This sets up the channels, routes messages, tracks peers, and is used for inter-module communication using events.\",\n  \"startup\": \"Handles the logic of what to display when TogetherJS is first started up (including warning messages, introductory stuff, the share link, confirmation of joining the session).\",\n  \"storage\": \"An abstraction (over `localStorage`) of per-tab and client storage.\",\n  \"templates\": \"This is generated from `interface.html` and other sources, including the content as inline strings.\",\n  \"templating\": \"Handles creating new nodes based on DOM templates.  Does some substitution based on specific class names.\",\n  \"togetherjs\": \"This is the bootstrap code.  It is included on all pages, defines the `TogetherJS` variable, and handles configuration and initial loading.\",\n  \"ui\": \"This has most of the UI, meaning everything involving HTML, and reacting to that interface.\",\n  \"util\": \"Lots of support code in here.  It doesn't depend on other things, and has fairly abstract general-purpose code.  It includes a pattern for creating classes, assertions, events.\",\n  \"videos.js\": \"Support for the video sync feature\",\n  \"visibilityApi\": \"Handles cross-browser tab visibility events\",\n  \"walkthrough\": \"Implements the walkthrough interface (content is in `walkthrough.html`).\",\n  \"webrtc\": \"Handles live audio chat.\",\n  \"who\": \"Lets clients peek into rooms and invite people from those rooms without joining the room\",\n  \"windowing\": \"Handles the creation of different windows, notifications, and modal windows.\",\n  \"youtubeVideos\": \"Support for the YouTube video sync feature\"\n}\n"
  },
  {
    "path": "togetherjs/ot.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"util\"], function (util) {\n\n  var ot = util.Module(\"ot\");\n  var assert = util.assert;\n\n  var StringSet = util.Class({\n    /* Set that only supports string items */\n    constructor: function () {\n      this._items = {};\n      this._count = 0;\n    },\n    contains: function (k) {\n      assert(typeof k == \"string\");\n      return this._items.hasOwnProperty(k);\n    },\n    add: function (k) {\n      assert(typeof k == \"string\");\n      if (this.contains(k)) {\n        return;\n      }\n      this._items[k] = null;\n      this._count++;\n    },\n    remove: function (k) {\n      assert(typeof k == \"string\");\n      if (! this.contains(k)) {\n        return;\n      }\n      delete this._items[k];\n      this._count++;\n    },\n    isEmpty: function () {\n      return ! this._count;\n    }\n  });\n\n  var Queue = util.Class({\n\n    constructor: function (size) {\n      this._q = [];\n      this._size = size;\n      this._deleted = 0;\n    },\n\n    _trim: function () {\n      if (this._size) {\n        if (this._q.length > this._size) {\n          this._q.splice(0, this._q.length - this._size);\n          this._deleted += this._q.length - this._size;\n        }\n      }\n    },\n\n    push: function (item) {\n      this._q.push(item);\n      this._trim();\n    },\n\n    last: function () {\n      return this._q[this._q.length-1];\n    },\n\n    walkBack: function (callback, context) {\n      var result = true;\n      for (var i=this._q.length-1; i >= 0; i--) {\n        var item = this._q[i];\n        result = callback.call(context, item, i + this._deleted);\n        if (result === false) {\n          return result;\n        } else if (! result) {\n          result = true;\n        }\n      }\n      return result;\n    },\n\n    walkForward: function (index, callback, context) {\n      var result = true;\n      for (var i=index; i<this._q.length; i++) {\n        var item = this._q[i-this._deleted];\n        result = callback.call(context, item, i);\n        if (result === false) {\n          return result;\n        } else if (! result) {\n          result = true;\n        }\n      }\n      return result;\n    },\n\n    insert: function (index, item) {\n      this._q.splice(index-this._deleted, 0, item);\n    }\n\n  });\n\n  var Change = util.Class({\n\n    constructor: function (version, clientId, delta, known, outOfOrder) {\n      this.version = version;\n      this.clientId = clientId;\n      this.delta = delta;\n      this.known = known;\n      this.outOfOrder = !! outOfOrder;\n      assert(typeof version == \"number\" && typeof clientId == \"string\",\n             \"Bad Change():\", version, clientId);\n    },\n\n    toString: function () {\n      var s = \"[Change \" + this.version + \".\" + this.clientId + \": \";\n      s += this.delta + \" \";\n      if (this.outOfOrder) {\n        s += \"(out of order) \";\n      }\n      var cids = [];\n      for (var a in this.known) {\n        if (this.known.hasOwnProperty(a)) {\n          cids.push(a);\n        }\n      }\n      cids.sort();\n      s += \"{\";\n      if (! cids.length) {\n        s += \"nothing known\";\n      } else {\n        cids.forEach(function (a, index) {\n          if (index) {\n            s += \";\";\n          }\n          s += a + \":\" + this.known[a];\n        }, this);\n      }\n      return s + \"}]\";\n    },\n\n    clone: function () {\n      return Change(this.version, this.clientId, this.delta.clone(), util.extend(this.known), this.outOfOrder);\n    },\n\n    isBefore: function (otherChange) {\n      assert(otherChange !== this, \"Tried to compare a change to itself\", this);\n      return otherChange.version > this.version ||\n          (otherChange.version == this.version && otherChange.clientId > this.clientId);\n    },\n\n    knowsAboutAll: function (versions) {\n      for (var clientId in versions) {\n        if (! versions.hasOwnProperty(clientId)) {\n          continue;\n        }\n        if (! versions[clientId]) {\n          continue;\n        }\n        if ((! this.known[clientId]) || this.known[clientId] < versions[clientId]) {\n          return false;\n        }\n      }\n      return true;\n    },\n\n    knowsAboutChange: function (change) {\n      return change.clientId == this.clientId ||\n          (this.known[change.clientId] && this.known[change.clientId] >= change.version);\n    },\n\n    knowsAboutVersion: function (version, clientId) {\n      if ((! version) || clientId == this.clientId) {\n        return true;\n      }\n      return this.known[clientId] && this.known[clientId] >= version;\n    },\n\n    maybeMissingChanges: function (mostRecentVersion, clientId) {\n      if (! mostRecentVersion) {\n        // No actual changes for clientId exist\n        return false;\n      }\n      if (! this.known[clientId]) {\n        // We don't even know about clientId, so we are definitely missing something\n        return true;\n      }\n      if (this.known[clientId] >= mostRecentVersion) {\n        // We know about all versions through mostRecentVersion\n        return false;\n      }\n      if ((clientId > this.clientId && this.known[clientId] >= this.version-1) ||\n          (clientId < this.clientId && this.known[clientId] == this.version)) {\n        // We know about all versions from clientId that could exist before this\n        // version\n        return false;\n      }\n      // We may or may not be missing something\n      return true;\n    }\n  });\n\n  /* SimpleHistory synchronizes peers by relying on the server to serialize\n   * the order of all updates.  Each client maintains a queue of patches\n   * which have not yet been 'committed' (by being echoed back from the\n   * server).  The client is responsible for transposing its own queue\n   * if 'earlier' patches are heard from the server.\n   *\n   * Let's say that A's edit \"1\" and B's edit \"2\" occur and get put in\n   * their respective SimpleHistory queues.  The server happens to\n   * handle 1 first, then 2, so those are the order that all peers\n   * (both A and B) see the messages.\n   *\n   * A sees 1, and has 1 on its queue, so everything's fine. It\n   * updates the 'committed' text to match its current text and drops\n   * the patch from its queue. It then sees 2, but the basis number\n   * for 2 no longer matches the committed basis, so it throws it\n   * away.\n   *\n   * B sees 1, and has 2 on its queue. It does the OT transpose thing,\n   * updating the committed text to include 1 and the 'current' text\n   * to include 1+2. It updates its queue with the newly transposed\n   * version of 2 (call it 2prime) and updates 2prime's basis\n   * number. It them resends 2prime to the server. It then receives 2\n   * (the original) but the basis number no longer matches the\n   * committed basis, so it throws it away.\n   *\n   * Now the server sees 2prime and rebroadcasts it to both A and B.\n   *\n   * A is seeing it for the first time, and the basis number matches,\n   * so it applies it to the current and committed text.\n   *\n   * B sees that 2prime matches what's on the start of its queue,\n   * shifts it off, and updates the committed text to match the\n   * current text.\n   *\n   * Note that no one tries to keep an entire history of changes,\n   * which is the main difference with ot.History.  Everyone applies\n   * the same patches in the same order.\n   */\n  ot.SimpleHistory = util.Class({\n\n    constructor: function(clientId, initState, initBasis) {\n      this.clientId = clientId;\n      this.committed = initState;\n      this.current = initState;\n      this.basis = initBasis;\n      this.queue = [];\n      this.deltaId = 1;\n      this.selection = null;\n    },\n\n    // Use a fake change to represent the selection.\n    // (This is the only bit that hard codes ot.TextReplace as the delta\n    // representation; override this in a subclass (or don't set the\n    // selection) if you are using a different delta representation.\n    setSelection: function(selection) {\n      if (selection) {\n        this.selection = ot.TextReplace(selection[0],\n                                        selection[1] - selection[0], '@');\n      } else {\n        this.selection = null;\n      }\n    },\n\n    // Decode the fake change to reconstruct the updated selection.\n    getSelection: function() {\n      if (! this.selection) {\n        return null;\n      }\n      return [this.selection.start, this.selection.start + this.selection.del];\n    },\n\n    // Add this delta to this client's queue.\n    add: function(delta) {\n      var change = {\n        id: this.clientId + '.' + (this.deltaId++),\n        delta: delta\n      };\n      if (! this.queue.length) {\n        change.basis = this.basis;\n      }\n      this.queue.push(change);\n      this.current = delta.apply(this.current);\n      return !!change.basis;\n    },\n\n    // Apply a delta received from the server.\n    // Return true iff the current text changed as a result.\n    commit: function(change) {\n\n      // ignore it if the basis doesn't match (this patch doesn't apply)\n      // if so, this delta is out of order; we expect the original client\n      // to retransmit an updated delta.\n      if (change.basis !== this.basis) {\n        return false; // 'current' text did not change\n      }\n\n      // is this the first thing on the queue?\n      if (this.queue.length && this.queue[0].id === change.id) {\n        assert(change.basis === this.queue[0].basis);\n        // good, apply this to commit state & remove it from queue\n        this.committed = this.queue.shift().delta.apply(this.committed);\n        this.basis++;\n        if (this.queue.length) {\n          this.queue[0].basis = this.basis;\n        }\n        return false; // 'current' text did not change\n      }\n\n      // Transpose all bits on the queue to put this patch first.\n      var inserted = change.delta;\n      this.queue = this.queue.map(function(qchange) {\n        var tt = qchange.delta.transpose(inserted);\n        inserted = tt[1];\n        return {\n          id: qchange.id,\n          delta: tt[0]\n        };\n      });\n      if (this.selection) {\n        // update the selection!\n        this.selection = this.selection.transpose(inserted)[0];\n      }\n      this.committed = change.delta.apply(this.committed);\n      this.basis++;\n      if (this.queue.length) {\n        this.queue[0].basis = this.basis;\n      }\n      // Update current by replaying queued changes starting from 'committed'\n      this.current = this.committed;\n      this.queue.forEach(function(qchange) {\n        this.current = qchange.delta.apply(this.current);\n      }.bind(this));\n      return true; // The 'current' text changed.\n    },\n\n    // Return the next change to transmit to the server, or null if there\n    // isn't one.\n    getNextToSend: function() {\n      var qchange = this.queue[0];\n      if (! qchange) {\n        /* nothing to send */\n        return null;\n      }\n      if (qchange.sent) {\n        /* already sent */\n        return null;\n      }\n      assert(qchange.basis);\n      qchange.sent = true;\n      return qchange;\n    }\n  });\n\n  ot.History = util.Class({\n\n    constructor: function (clientId, initState) {\n      this._history = Queue();\n      this._history.push({\n        clientId: \"init\", state: initState\n      });\n      this.clientId = clientId;\n      this.known = {};\n      this.mostRecentLocalChange = null;\n    },\n\n    add: function (change) {\n      // Simplest cast, it is our change:\n      if (change.clientId == this.clientId) {\n        this._history.push(change);\n        this.mostRecentLocalChange = change.version;\n        return change.delta;\n      }\n      assert((! this.known[change.clientId]) || this.known[change.clientId] < change.version,\n            \"Got a change\", change, \"that appears older (or same as) a known change\", this.known[change.clientId]);\n      // Second simplest case, we get a change that we can add to our\n      // history without modification:\n      var last = this._history.last();\n      if ((last.clientId == \"init\" || last.isBefore(change)) &&\n          change.knowsAboutAll(this.known) &&\n          change.knowsAboutVersion(this.mostRecentLocalChange, this.clientId)) {\n        this._history.push(change);\n        this.known[change.clientId] = change.version;\n        return change.delta;\n      }\n      // We must do work!\n\n      this.logHistory(\"//\");\n\n      // First we check if we need to modify this change because we\n      // know about changes that it should know about (changes that\n      // preceed it that are in our local history).\n      var clientsToCheck = StringSet();\n      for (var clientId in this.known) {\n        if (! this.known.hasOwnProperty(clientId)) {\n          continue;\n        }\n        if (change.maybeMissingChanges(this.known[clientId], clientId)) {\n          clientsToCheck.add(clientId);\n        }\n      }\n      if (change.maybeMissingChanges(this.mostRecentLocalChange, this.clientId)) {\n        clientsToCheck.add(this.clientId);\n      }\n      if (! clientsToCheck.isEmpty()) {\n        var indexToCheckFrom = null;\n        this._history.walkBack(function (c, index) {\n          indexToCheckFrom = index;\n          if (c.clientId == \"init\") {\n            return false;\n          }\n          if (clientsToCheck.contains(c.clientId) &&\n              ! change.maybeMissingChanges(c.version, c.clientId)) {\n            clientsToCheck.remove(c.clientId);\n            if (clientsToCheck.isEmpty()) {\n              return false;\n            }\n          }\n          return true;\n        }, this);\n        this._history.walkForward(indexToCheckFrom, function (c, index) {\n          if (c.clientId == \"init\") {\n            return true;\n          }\n          if (change.isBefore(c)) {\n            return false;\n          }\n          if (! change.knowsAboutChange(c)) {\n            var presentDelta = this.promoteDelta(c.delta, index, change);\n            if (! presentDelta.equals(c.delta)) {\n              //console.log(\"->rebase delta rewrite\", presentDelta+\"\");\n            }\n            this.logChange(\"->rebase\", change, function () {\n              var result = change.delta.transpose(presentDelta);\n              change.delta = result[0];\n              change.known[c.clientId] = c.version;\n            }, \"with:\", c);\n          }\n          return true;\n        }, this);\n      }\n\n      // Next we insert the change into its proper location\n      var indexToInsert = null;\n      this._history.walkBack(function (c, index) {\n        if (c.clientId == \"init\" || c.isBefore(change)) {\n          indexToInsert = index+1;\n          return false;\n        }\n        return true;\n      }, this);\n      assert(indexToInsert);\n      this._history.insert(indexToInsert, change);\n\n      // Now we fix up any forward changes\n      var fixupDelta = change.delta;\n      this._history.walkForward(indexToInsert+1, function (c, index) {\n        if (! c.knowsAboutChange(change)) {\n          var origChange = c.clone();\n          this.logChange(\"^^fix\", c, function () {\n            var fixupResult = c.delta.transpose(fixupDelta);\n            console.log(\"  ^^real\");\n            var result = c.delta.transpose(fixupDelta);\n            c.delta = result[0];\n            c.known[change.clientId] = change.version;\n            fixupDelta = fixupResult[1];\n          }, \"clone:\", change.delta+\"\");\n          console.log(\"(trans)\", fixupDelta+\"\");\n          assert(c.knowsAboutChange(change));\n        }\n      }, this);\n\n      // Finally we return the transformed delta that represents\n      // changes that should be made to the state:\n\n      this.logHistory(\"!!\");\n      return fixupDelta;\n    },\n\n    promoteDelta: function (delta, deltaIndex, untilChange) {\n      this._history.walkForward(deltaIndex+1, function (c, index) {\n        if (untilChange.isBefore(c)) {\n          return false;\n        }\n        // FIXME: not sure if this clientId check here is right.  Maybe\n        // if untilChange.knowsAbout(c)?\n        if (untilChange.knowsAboutChange(c)) {\n          var result = c.delta.transpose(delta);\n          delta = result[1];\n        }\n        return true;\n      });\n      return delta;\n    },\n\n    logHistory: function (prefix) {\n      prefix = prefix || \"\";\n      var postfix = Array.prototype.slice.call(arguments, 1);\n      console.log.apply(console, [prefix + \"history\", this.clientId, \":\"].concat(postfix));\n      console.log(prefix + \" state:\", JSON.stringify(this.getStateSafe()));\n      var hstate;\n      this._history.walkForward(0, function (c, index) {\n        if (! index) {\n          assert(c.clientId == \"init\");\n          console.log(prefix + \" init:\", JSON.stringify(c.state));\n          hstate = c.state;\n        } else {\n          try {\n            hstate = c.delta.apply(hstate);\n          } catch (e) {\n            hstate = \"Error: \" + e;\n          }\n          console.log(prefix + \"  \", index, c+\"\", JSON.stringify(hstate));\n        }\n      });\n    },\n\n    logChange: function (prefix, change, callback) {\n      prefix = prefix || \"before\";\n      var postfix = Array.prototype.slice.call(arguments, 3);\n      console.log.apply(\n        console,\n        [prefix, this.clientId, \":\", change+\"\"].concat(postfix).concat([JSON.stringify(this.getStateSafe(true))]));\n      try {\n        callback();\n      } finally {\n        console.log(prefix + \" after:\", change+\"\", JSON.stringify(this.getStateSafe()));\n      }\n    },\n\n    addDelta: function (delta) {\n      var version = this._createVersion();\n      var change = Change(version, this.clientId, delta, util.extend(this.knownVersions));\n      this.add(change);\n      return change;\n    },\n\n    _createVersion: function () {\n      var max = 1;\n      for (var id in this.knownVersions) {\n        max = Math.max(max, this.knownVersions[id]);\n      }\n      max = Math.max(max, this.mostRecentLocalChange);\n      return max+1;\n    },\n\n    fault: function (change) {\n      throw new Error('Fault');\n    },\n\n    getState: function () {\n      var state;\n      this._history.walkForward(0, function (c) {\n        if (c.clientId == \"init\") {\n          // Initialization, has the state\n          state = c.state;\n        } else {\n          state = c.delta.apply(state);\n        }\n      }, this);\n      return state;\n    },\n\n    getStateSafe: function () {\n      try {\n        return this.getState();\n      } catch (e) {\n        return 'Error: ' + e;\n      }\n    }\n\n  });\n\n  ot.TextReplace = util.Class({\n\n    constructor: function (start, del, text) {\n      assert(typeof start == \"number\" && typeof del == \"number\" && typeof text == \"string\", start, del, text);\n      assert(start >=0 && del >= 0, start, del);\n      this.start = start;\n      this.del = del;\n      this.text = text;\n    },\n\n    toString: function () {\n      if (this.empty()) {\n        return '[no-op]';\n      }\n      if (! this.del) {\n        return '[insert ' + JSON.stringify(this.text) + ' @' + this.start + ']';\n      } else if (! this.text) {\n        return '[delete ' + this.del + ' chars @' + this.start + ']';\n      } else {\n        return '[replace ' + this.del + ' chars with ' + JSON.stringify(this.text) + ' @' + this.start + ']';\n      }\n    },\n\n    equals: function (other) {\n      return other.constructor === this.constructor &&\n          other.del === this.del &&\n          other.start === this.start &&\n          other.text === this.text;\n    },\n\n    clone: function (start, del, text) {\n      if (start === undefined) {\n        start = this.start;\n      }\n      if (del === undefined) {\n        del = this.del;\n      }\n      if (text === undefined) {\n        text = this.text;\n      }\n      return ot.TextReplace(start, del, text);\n    },\n\n    empty: function () {\n      return (! this.del) && (! this.text);\n    },\n\n    apply: function (text) {\n      if (this.empty()) {\n        return text;\n      }\n      if (this.start > text.length) {\n        console.trace();\n        throw new util.AssertionError(\"Start after end of text (\" + JSON.stringify(text) + \"/\" + text.length + \"): \" + this);\n      }\n      if (this.start + this.del > text.length) {\n        throw new util.AssertionError(\"Start+del after end of text (\" + JSON.stringify(text) + \"/\" + text.length + \"): \" + this);\n      }\n      return text.substr(0, this.start) + this.text + text.substr(this.start+this.del);\n    },\n\n    transpose: function (delta) {\n      /* Transform this delta as though the other delta had come before it.\n         Returns a [new_version_of_this, transformed_delta], where transformed_delta\n         satisfies:\n\n         result1 = new_version_of_this.apply(delta.apply(text));\n         result2 = transformed_delta.apply(this.apply(text));\n         assert(result1 == result2);\n\n         Does not modify this object.\n      */\n      var overlap;\n      assert(delta instanceof ot.TextReplace, \"Transposing with non-TextReplace:\", delta);\n      if (this.empty()) {\n        //console.log(\"  =this is empty\");\n        return [this.clone(), delta.clone()];\n      }\n      if (delta.empty()) {\n        //console.log(\"  =other is empty\");\n        return [this.clone(), delta.clone()];\n      }\n      if (delta.before(this)) {\n        //console.log(\"  =this after other\");\n        return [this.clone(this.start + delta.text.length - delta.del),\n                delta.clone()];\n      } else if (this.before(delta)) {\n        //console.log(\"  =this before other\");\n        return [this.clone(), delta.clone(delta.start + this.text.length - this.del)];\n      } else if (delta.sameRange(this)) {\n        //console.log(\"  =same range\");\n        return [this.clone(this.start+delta.text.length, 0),\n                delta.clone(undefined, 0)];\n      } else if (delta.contains(this)) {\n        //console.log(\"  =other contains this\");\n        return [this.clone(delta.start+delta.text.length, 0, this.text),\n                delta.clone(undefined, delta.del - this.del + this.text.length, delta.text + this.text)];\n      } else if (this.contains(delta)) {\n        //console.log(\"  =this contains other\");\n        return [this.clone(undefined, this.del - delta.del + delta.text.length, delta.text + this.text),\n                delta.clone(this.start, 0, delta.text)];\n      } else if (this.overlapsStart(delta)) {\n        //console.log(\"  =this overlaps start of other\");\n        overlap = this.start + this.del - delta.start;\n        return [this.clone(undefined, this.del - overlap),\n                delta.clone(this.start + this.text.length, delta.del - overlap)];\n      } else {\n        //console.log(\"  =this overlaps end of other\");\n        assert(delta.overlapsStart(this), delta+\"\", \"does not overlap start of\", this+\"\", delta.before(this));\n        overlap = delta.start + delta.del - this.start;\n        return [this.clone(delta.start + delta.text.length, this.del - overlap),\n                delta.clone(undefined, delta.del - overlap)];\n      }\n      throw 'Should not happen';\n    },\n\n    before: function (other) {\n      return this.start + this.del <= other.start;\n    },\n\n    contains: function (other) {\n      return other.start >= this.start && other.start + other.del < this.start + this.del;\n    },\n\n    sameRange: function (other) {\n      return other.start == this.start && other.del == this.del;\n    },\n\n    overlapsStart: function (other) {\n      return this.start < other.start && this.start + this.del > other.start;\n    },\n\n    classMethods: {\n\n      /* Make a new ot.TextReplace that converts oldValue to newValue. */\n      fromChange: function(oldValue, newValue) {\n        assert(typeof oldValue == \"string\");\n        assert(typeof newValue == \"string\");\n        var commonStart = 0;\n        while (commonStart < newValue.length &&\n               newValue.charAt(commonStart) == oldValue.charAt(commonStart)) {\n          commonStart++;\n        }\n        var commonEnd = 0;\n        while (commonEnd < (newValue.length - commonStart) &&\n               commonEnd < (oldValue.length - commonStart) &&\n               newValue.charAt(newValue.length - commonEnd - 1) ==\n               oldValue.charAt(oldValue.length - commonEnd - 1)) {\n          commonEnd++;\n        }\n        var removed = oldValue.substr(commonStart, oldValue.length - commonStart - commonEnd);\n        var inserted = newValue.substr(commonStart, newValue.length - commonStart - commonEnd);\n        if (! (removed.length || inserted)) {\n          return null;\n        }\n        return this(commonStart, removed.length, inserted);\n      },\n\n      random: function (source, generator) {\n        var text, start, len;\n        var ops = [\"ins\", \"del\", \"repl\"];\n        if (! source.length) {\n          ops = [\"ins\"];\n        }\n        switch (generator.pick(ops)) {\n        case \"ins\":\n          if (! generator.number(2)) {\n            text = generator.string(1);\n          } else {\n            text = generator.string(generator.number(3)+1);\n          }\n          if (! generator.number(4)) {\n            start = 0;\n          } else if (! generator.number(3)) {\n            start = source.length-1;\n          } else {\n            start = generator.number(source.length);\n          }\n          return this(start, 0, text);\n\n        case \"del\":\n          if (! generator.number(20)) {\n            return this(0, source.length, \"\");\n          }\n          start = generator.number(source.length-1);\n          if (! generator.number(2)) {\n            len = 1;\n          } else {\n            len = generator.number(5)+1;\n          }\n          len = Math.min(len, source.length - start);\n          return this(start, len, \"\");\n\n        case \"repl\":\n          start = generator.number(source.length-1);\n          len = generator.number(5);\n          len = Math.min(len, source.length - start);\n          text = generator.string(generator.number(2)+1);\n          return this(start, len, text);\n        }\n        throw 'Unreachable';\n      }\n    }\n  });\n\n  return ot;\n});\n"
  },
  {
    "path": "togetherjs/peers.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"util\", \"session\", \"storage\", \"require\", \"templates\"], function (util, session, storage, require, templates) {\n  var peers = util.Module(\"peers\");\n  var assert = util.assert;\n  var CHECK_ACTIVITY_INTERVAL = 10*1000; // Every 10 seconds see if someone has gone idle\n  var IDLE_TIME = 3*60*1000; // Idle time is 3 minutes\n  var TAB_IDLE_TIME = 2*60*1000; // When you tab away, after two minutes you'll say you are idle\n  var BYE_TIME = 10*60*1000; // After 10 minutes of inactivity the person is considered to be \"gone\"\n\n  var ui;\n  require([\"ui\"], function (uiModule) {\n    ui = uiModule;\n  });\n\n  var DEFAULT_NICKNAMES = templates(\"names\").split(/,\\s*/g);\n  var Peer = util.Class({\n\n    isSelf: false,\n\n    constructor: function (id, attrs) {\n      attrs = attrs || {};\n      assert(id);\n      assert(! Peer.peers[id]);\n      this.id = id;\n      this.identityId = attrs.identityId || null;\n      this.status = attrs.status || \"live\";\n      this.idle = attrs.status || \"active\";\n      this.name = attrs.name || null;\n      this.avatar = attrs.avatar || null;\n      this.color = attrs.color || \"#00FF00\";\n      this.view = ui.PeerView(this);\n      this.lastMessageDate = 0;\n      this.following = attrs.following || false;\n      Peer.peers[id] = this;\n      var joined = attrs.joined || false;\n      if (attrs.fromHelloMessage) {\n        this.updateFromHello(attrs.fromHelloMessage);\n        if (attrs.fromHelloMessage.type == \"hello\") {\n          joined = true;\n        }\n      }\n      peers.emit(\"new-peer\", this);\n      if (joined) {\n        this.view.notifyJoined();\n      }\n      this.view.update();\n    },\n\n    repr: function () {\n      return \"Peer(\" + JSON.stringify(this.id) + \")\";\n    },\n\n    serialize: function () {\n      return {\n        id: this.id,\n        status: this.status,\n        idle: this.idle,\n        url: this.url,\n        hash: this.hash,\n        title: this.title,\n        identityId: this.identityId,\n        rtcSupported: this.rtcSupported,\n        name: this.name,\n        avatar: this.avatar,\n        color: this.color,\n        following: this.following\n      };\n    },\n\n    destroy: function () {\n      this.view.destroy();\n      delete Peer.peers[this.id];\n    },\n\n    updateMessageDate: function (msg) {\n      if (this.idle == \"inactive\") {\n        this.update({idle: \"active\"});\n      }\n      if (this.status == \"bye\") {\n        this.unbye();\n      }\n      this.lastMessageDate = Date.now();\n    },\n\n    updateFromHello: function (msg) {\n      var urlUpdated = false;\n      var activeRTC = false;\n      var identityUpdated = false;\n      if (msg.url && msg.url != this.url) {\n        this.url = msg.url;\n        this.hash = null;\n        this.title = null;\n        urlUpdated = true;\n      }\n      if (msg.hash != this.hash) {\n        this.hash = msg.urlHash;\n        urlUpdated = true;\n      }\n      if (msg.title != this.title) {\n        this.title = msg.title;\n        urlUpdated = true;\n      }\n      if (msg.rtcSupported !== undefined) {\n        this.rtcSupported = msg.rtcSupported;\n      }\n      if (msg.identityId !== undefined) {\n        this.identityId = msg.identityId;\n      }\n      if (msg.name && msg.name != this.name) {\n        this.name = msg.name;\n        identityUpdated = true;\n      }\n      if (msg.avatar && msg.avatar != this.avatar) {\n        util.assertValidUrl(msg.avatar);\n        this.avatar = msg.avatar;\n        identityUpdated = true;\n      }\n      if (msg.color && msg.color != this.color) {\n        this.color = msg.color;\n        identityUpdated = true;\n      }\n      if (msg.isClient !== undefined) {\n        this.isCreator = ! msg.isClient;\n      }\n      if (this.status != \"live\") {\n        this.status = \"live\";\n        peers.emit(\"status-updated\", this);\n      }\n      if (this.idle != \"active\") {\n        this.idle = \"active\";\n        peers.emit(\"idle-updated\", this);\n      }\n      if (msg.rtcSupported) {\n        peers.emit(\"rtc-supported\", this);\n      }\n      if (urlUpdated) {\n        peers.emit(\"url-updated\", this);\n      }\n      if (identityUpdated) {\n        peers.emit(\"identity-updated\", this);\n      }\n      // FIXME: I can't decide if this is the only time we need to emit\n      // this message (and not .update() or other methods)\n      if (this.following) {\n        session.emit(\"follow-peer\", this);\n      }\n    },\n\n    update: function (attrs) {\n      // FIXME: should probably test that only a couple attributes are settable\n      // particularly status and idle\n      if (attrs.idle) {\n        this.idle = attrs.idle;\n      }\n      if (attrs.status) {\n        this.status = attrs.status;\n      }\n      this.view.update();\n    },\n\n    className: function (prefix) {\n      prefix = prefix || \"\";\n      return prefix + util.safeClassName(this.id);\n    },\n\n    bye: function () {\n      if (this.status != \"bye\") {\n        this.status = \"bye\";\n        peers.emit(\"status-updated\", this);\n      }\n      this.view.update();\n    },\n\n    unbye: function () {\n      if (this.status == \"bye\") {\n        this.status = \"live\";\n        peers.emit(\"status-updated\", this);\n      }\n      this.view.update();\n    },\n\n    nudge: function () {\n      session.send({\n        type: \"url-change-nudge\",\n        url: location.href,\n        to: this.id\n      });\n    },\n\n    follow: function () {\n      if (this.following) {\n        return;\n      }\n      peers.getAllPeers().forEach(function (p) {\n        if (p.following) {\n          p.unfollow();\n        }\n      });\n      this.following = true;\n      // We have to make sure we remember this, even if we change URLs:\n      storeSerialization();\n      this.view.update();\n      session.emit(\"follow-peer\", this);\n    },\n\n    unfollow: function () {\n      this.following = false;\n      storeSerialization();\n      this.view.update();\n    }\n\n  });\n\n  // FIXME: I can't decide where this should actually go, seems weird\n  // that it is emitted and handled in the same module\n  session.on(\"follow-peer\", function (peer) {\n    if (peer.url != session.currentUrl()) {\n      var url = peer.url;\n      if (peer.urlHash) {\n        url += peer.urlHash;\n      }\n      location.href = url;\n    }\n  });\n\n  Peer.peers = {};\n\n  Peer.deserialize = function (obj) {\n    obj.fromStorage = true;\n    var peer = Peer(obj.id, obj);\n  };\n\n  peers.Self = undefined;\n\n  session.on(\"start\", function () {\n    if (peers.Self) {\n      return;\n    }\n    /* Same interface as Peer, represents oneself (local user): */\n    peers.Self = util.mixinEvents({\n      isSelf: true,\n      id: session.clientId,\n      identityId: session.identityId,\n      status: \"live\",\n      idle: \"active\",\n      name: null,\n      avatar: null,\n      color: null,\n      defaultName: null,\n      loaded: false,\n      isCreator: ! session.isClient,\n\n      update: function (attrs) {\n        var updatePeers = false;\n        var updateIdle = false;\n        var updateMsg = {type: \"peer-update\"};\n        if (typeof attrs.name == \"string\" && attrs.name != this.name) {\n          this.name = attrs.name;\n          updateMsg.name = this.name;\n          if (! attrs.fromLoad) {\n            storage.settings.set(\"name\", this.name);\n            updatePeers = true;\n          }\n        }\n        if (attrs.avatar && attrs.avatar != this.avatar) {\n          util.assertValidUrl(attrs.avatar);\n          this.avatar = attrs.avatar;\n          updateMsg.avatar = this.avatar;\n          if (! attrs.fromLoad) {\n            storage.settings.set(\"avatar\", this.avatar);\n            updatePeers = true;\n          }\n        }\n        if (attrs.color && attrs.color != this.color) {\n          this.color = attrs.color;\n          updateMsg.color = this.color;\n          if (! attrs.fromLoad) {\n            storage.settings.set(\"color\", this.color);\n            updatePeers = true;\n          }\n        }\n        if (attrs.defaultName && attrs.defaultName != this.defaultName) {\n          this.defaultName = attrs.defaultName;\n          if (! attrs.fromLoad) {\n            storage.settings.set(\"defaultName\", this.defaultName);\n            updatePeers = true;\n          }\n        }\n        if (attrs.status && attrs.status != this.status) {\n          this.status = attrs.status;\n          peers.emit(\"status-updated\", this);\n        }\n        if (attrs.idle && attrs.idle != this.idle) {\n          this.idle = attrs.idle;\n          updateIdle = true;\n          peers.emit(\"idle-updated\", this);\n        }\n        this.view.update();\n        if (updatePeers && ! attrs.fromLoad) {\n          session.emit(\"self-updated\");\n          session.send(updateMsg);\n        }\n        if (updateIdle && ! attrs.fromLoad) {\n          session.send({\n            type: \"idle-status\",\n            idle: this.idle\n          });\n        }\n      },\n\n      className: function (prefix) {\n        prefix = prefix || \"\";\n        return prefix + \"self\";\n      },\n\n      _loadFromSettings: function () {\n        return util.resolveMany(\n          storage.settings.get(\"name\"),\n          storage.settings.get(\"avatar\"),\n          storage.settings.get(\"defaultName\"),\n          storage.settings.get(\"color\")).then((function (name, avatar, defaultName, color) {\n            if (! defaultName) {\n              defaultName = util.pickRandom(DEFAULT_NICKNAMES);\n\n              storage.settings.set(\"defaultName\", defaultName);\n            }\n            if (! color) {\n              color = Math.floor(Math.random() * 0xffffff).toString(16);\n              while (color.length < 6) {\n                color = \"0\" + color;\n              }\n              color = \"#\" + color;\n              storage.settings.set(\"color\", color);\n            }\n            if (! avatar) {\n              avatar = TogetherJS.baseUrl + \"/togetherjs/images/default-avatar.png\";\n            }\n            this.update({\n              name: name,\n              avatar: avatar,\n              defaultName: defaultName,\n              color: color,\n              fromLoad: true\n            });\n            peers._SelfLoaded.resolve();\n          }).bind(this)); // FIXME: ignoring error\n      },\n\n      _loadFromApp: function () {\n        // FIXME: I wonder if these should be optionally functions?\n        // We could test typeof==function to distinguish between a getter and a concrete value\n        var getUserName = TogetherJS.config.get(\"getUserName\");\n        var getUserColor = TogetherJS.config.get(\"getUserColor\");\n        var getUserAvatar = TogetherJS.config.get(\"getUserAvatar\");\n        var name, color, avatar;\n        if (getUserName) {\n          if (typeof getUserName == \"string\") {\n            name = getUserName;\n          } else {\n            name = getUserName();\n          }\n          if (name && typeof name != \"string\") {\n            // FIXME: test for HTML safe?  Not that we require it, but\n            // <>'s are probably a sign something is wrong.\n            console.warn(\"Error in getUserName(): should return a string (got\", name, \")\");\n            name = null;\n          }\n        }\n        if (getUserColor) {\n          if (typeof getUserColor == \"string\") {\n            color = getUserColor;\n          } else {\n            color = getUserColor();\n          }\n          if (color && typeof color != \"string\") {\n            // FIXME: would be nice to test for color-ness here.\n            console.warn(\"Error in getUserColor(): should return a string (got\", color, \")\");\n            color = null;\n          }\n        }\n        if (getUserAvatar) {\n          if (typeof getUserAvatar == \"string\") {\n            avatar = getUserAvatar;\n          } else {\n            avatar = getUserAvatar();\n          }\n          if (avatar && typeof avatar != \"string\") {\n            console.warn(\"Error in getUserAvatar(): should return a string (got\", avatar, \")\");\n            avatar = null;\n          }\n        }\n        if (name || color || avatar) {\n          this.update({\n            name: name,\n            color: color,\n            avatar: avatar\n          });\n        }\n      }\n    });\n\n    peers.Self.view = ui.PeerView(peers.Self);\n    storage.tab.get(\"peerCache\").then(deserialize);\n    peers.Self._loadFromSettings().then(function() {\n      peers.Self._loadFromApp();\n      peers.Self.view.update();\n      session.emit(\"self-updated\");\n    });\n  });\n\n  session.on(\"refresh-user-data\", function () {\n    if (peers.Self) {\n      peers.Self._loadFromApp();\n    }\n  });\n\n  TogetherJS.config.track(\n    \"getUserName\",\n    TogetherJS.config.track(\n      \"getUserColor\",\n      TogetherJS.config.track(\n        \"getUserAvatar\",\n        function () {\n          if (peers.Self) {\n            peers.Self._loadFromApp();\n          }\n        }\n      )\n    )\n  );\n\n  peers._SelfLoaded = util.Deferred();\n\n  function serialize() {\n    var peers = [];\n    util.forEachAttr(Peer.peers, function (peer) {\n      peers.push(peer.serialize());\n    });\n    return {\n      peers: peers\n    };\n  }\n\n  function deserialize(obj) {\n    if (! obj) {\n      return;\n    }\n    obj.peers.forEach(function (peer) {\n      Peer.deserialize(peer);\n    });\n  }\n\n  peers.getPeer = function getPeer(id, message, ignoreMissing) {\n    assert(id);\n    var peer = Peer.peers[id];\n    if (id === session.clientId) {\n      return peers.Self;\n    }\n    if (message && ! peer) {\n      peer = Peer(id, {fromHelloMessage: message});\n      return peer;\n    }\n    if (ignoreMissing && !peer) {\n      return null;\n    }\n    assert(peer, \"No peer with id:\", id);\n    if (message &&\n        (message.type == \"hello\" || message.type == \"hello-back\" ||\n         message.type == \"peer-update\")) {\n      peer.updateFromHello(message);\n      peer.view.update();\n    }\n    return Peer.peers[id];\n  };\n\n  peers.getAllPeers = function (liveOnly) {\n    var result = [];\n    util.forEachAttr(Peer.peers, function (peer) {\n      if (liveOnly && peer.status != \"live\") {\n        return;\n      }\n      result.push(peer);\n    });\n    return result;\n  };\n\n  function checkActivity() {\n    var ps = peers.getAllPeers();\n    var now = Date.now();\n    ps.forEach(function (p) {\n      if (p.idle == \"active\" && now - p.lastMessageDate > IDLE_TIME) {\n        p.update({idle: \"inactive\"});\n      }\n      if (p.status != \"bye\" && now - p.lastMessageDate > BYE_TIME) {\n        p.bye();\n      }\n    });\n  }\n\n  session.hub.on(\"bye\", function (msg) {\n    var peer = peers.getPeer(msg.clientId);\n    peer.bye();\n  });\n\n  var checkActivityTask = null;\n\n  session.on(\"start\", function () {\n    if (checkActivityTask) {\n      console.warn(\"Old peers checkActivityTask left over?\");\n      clearTimeout(checkActivityTask);\n    }\n    checkActivityTask = setInterval(checkActivity, CHECK_ACTIVITY_INTERVAL);\n  });\n\n  session.on(\"close\", function () {\n    util.forEachAttr(Peer.peers, function (peer) {\n      peer.destroy();\n    });\n    storage.tab.set(\"peerCache\", undefined);\n    clearTimeout(checkActivityTask);\n    checkActivityTask = null;\n  });\n\n  var tabIdleTimeout = null;\n\n  session.on(\"visibility-change\", function (hidden) {\n    if (hidden) {\n      if (tabIdleTimeout) {\n        clearTimeout(tabIdleTimeout);\n      }\n      tabIdleTimeout = setTimeout(function () {\n        peers.Self.update({idle: \"inactive\"});\n      }, TAB_IDLE_TIME);\n    } else {\n      if (tabIdleTimeout) {\n        clearTimeout(tabIdleTimeout);\n      }\n      if (peers.Self.idle == \"inactive\") {\n        peers.Self.update({idle: \"active\"});\n      }\n    }\n  });\n\n  session.hub.on(\"idle-status\", function (msg) {\n    msg.peer.update({idle: msg.idle});\n  });\n\n  // Pings are a straight alive check, and contain no more information:\n  session.hub.on(\"ping\", function () {\n    session.send({type: \"ping-back\"});\n  });\n\n  window.addEventListener(\"pagehide\", function () {\n    // FIXME: not certain if this should be tab local or not:\n    storeSerialization();\n  }, false);\n\n  function storeSerialization() {\n    storage.tab.set(\"peerCache\", serialize());\n  }\n\n  util.mixinEvents(peers);\n\n  util.testExpose({\n    setIdleTime: function (time) {\n      IDLE_TIME = time;\n      CHECK_ACTIVITY_INTERVAL = time / 2;\n      if (TogetherJS.running) {\n        clearTimeout(checkActivityTask);\n        checkActivityTask = setInterval(checkActivity, CHECK_ACTIVITY_INTERVAL);\n      }\n    }\n  });\n\n  util.testExpose({\n    setByeTime: function (time) {\n      BYE_TIME = time;\n      CHECK_ACTIVITY_INTERVAL = Math.min(CHECK_ACTIVITY_INTERVAL, time / 2);\n      if (TogetherJS.running) {\n        clearTimeout(checkActivityTask);\n        checkActivityTask = setInterval(checkActivity, CHECK_ACTIVITY_INTERVAL);\n      }\n    }\n  });\n\n  return peers;\n});\n"
  },
  {
    "path": "togetherjs/playback.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"jquery\", \"util\", \"session\", \"storage\", \"require\"], function ($, util, session, storage, require) {\n  var playback = util.Module(\"playback\");\n  var assert = util.assert;\n\n  var ALWAYS_REPLAY = {\n    \"cursor-update\": true,\n    \"scroll-update\": true\n  };\n\n  playback.getLogs = function (url) {\n    if (url.search(/^local:/) === 0) {\n      return $.Deferred(function (def) {\n        storage.get(\"recording.\" + url.substr(\"local:\".length)).then(function (logs) {\n          if (! logs) {\n            def.resolve(null);\n            return;\n          }\n          logs = parseLogs(logs);\n          def.resolve(logs);\n        }, function (error) {\n          def.reject(error);\n        });\n      });\n    }\n    return $.Deferred(function (def) {\n      $.ajax({\n        url: url,\n        dataType: \"text\"\n      }).then(\n        function (logs) {\n          logs = parseLogs(logs);\n          def.resolve(logs);\n        },\n        function (error) {\n          def.reject(error);\n        });\n    });\n  };\n\n  function parseLogs(logs) {\n    logs = logs.replace(/\\r\\n/g, '\\n');\n    logs = logs.split(/\\n/g);\n    var result = [];\n    for (var i=0; i<logs.length; i++) {\n      var line = logs[i];\n      line = line.replace(/^\\s+/, \"\").replace(/\\s+$/, \"\");\n      if (line.search(/\\/\\*/) === 0) {\n        var last = line.search(/\\*\\//);\n        if (last == -1) {\n          console.warn(\"bad line:\", line);\n          continue;\n        }\n        line = line.substr(last+2);\n      }\n      line = line.replace(/^\\s+/, \"\");\n      if (! line) {\n        continue;\n      }\n      line = JSON.parse(line);\n      result.push(line);\n    }\n    return Logs(result);\n  }\n\n  var Logs = util.Class({\n    constructor: function (logs, fromStorage) {\n      this.logs = logs;\n      this.fromStorage = fromStorage;\n      this.pos = 0;\n    },\n\n    play: function () {\n      this.start = Date.now();\n      if (this.pos >= this.logs.length) {\n        this.unload();\n        return;\n      }\n      if (this.pos !== 0) {\n        // First we need to play the hello\n        var toReplay = [];\n        var foundHello = false;\n        for (var i=this.pos-1; i>=0; i--) {\n          var item = this.logs[i];\n          if (ALWAYS_REPLAY[item.type]) {\n            toReplay.push(item);\n          }\n          if (item.type == \"hello\" || item.type == \"hello-back\") {\n            this.playItem(item);\n            foundHello = true;\n            break;\n          }\n        }\n        if (! foundHello) {\n          console.warn(\"No hello message found before position\", this.pos);\n        }\n        toReplay.reverse();\n        for (i=0; i<toReplay.length; i++) {\n          this.playItem(toReplay[i]);\n        }\n      }\n      this.playOne();\n    },\n\n    cancel: function () {\n      if (this.playTimer) {\n        clearTimeout(this.playTimer);\n        this.playTimer = null;\n      }\n      this.start = null;\n      this.pos = 0;\n      this.unload();\n    },\n\n    pause: function () {\n      if (this.playTimer) {\n        clearTimeout(this.playTimer);\n        this.playTimer = null;\n      }\n    },\n\n    playOne: function () {\n      this.playTimer = null;\n      if (this.pos >= this.logs.length) {\n        this.unload();\n        return;\n      }\n      var item = this.logs[this.pos];\n      this.playItem(item);\n      this.pos++;\n      if (this.pos >= this.logs.length) {\n        this.unload();\n        return;\n      }\n      var next = this.logs[this.pos];\n      var pause = next.date - item.date;\n      this.playTimer = setTimeout(this.playOne.bind(this), pause);\n      if (this.fromStorage) {\n        this.savePos();\n      }\n    },\n\n    playItem: function (item) {\n      if (item.type == \"hello\") {\n        // We may need to pause here\n        if (item.url != (location.href+\"\").replace(/\\#.*/, \"\")) {\n          this.pause();\n        }\n      }\n      try {\n        session._getChannel().onmessage(item);\n      } catch (e) {\n        console.warn(\"Could not play back message:\", item, \"error:\", e);\n      }\n    },\n\n    save: function () {\n      this.fromStorage = true;\n      storage.set(\"playback.logs\", this.logs);\n      this.savePos();\n    },\n\n    savePos: function () {\n      storage.set(\"playback.pos\", this.pos);\n    },\n\n    unload: function () {\n      if (this.fromStorage) {\n        storage.set(\"playback.logs\", undefined);\n        storage.set(\"playback.pos\", undefined);\n      }\n      // FIXME: should do a bye message here\n    }\n\n  });\n\n  playback.getRunningLogs = function () {\n    return storage.get(\"playback.logs\").then(function (value) {\n      if (! value) {\n        return null;\n      }\n      var logs = Logs(value, true);\n      return storage.get(\"playback.pos\").then(function (pos) {\n        pos = pos || 0;\n        logs.pos = pos;\n        return logs;\n      });\n    });\n  };\n\n  return playback;\n});\n"
  },
  {
    "path": "togetherjs/randomutil.js",
    "content": "define([\"util\", \"whrandom\"], function (util, RandomStream) {\n\n  var Randomizer = util.Class({\n    constructor: function (seed) {\n      this.stream = RandomStream(seed);\n    },\n    number: function (max) {\n      return Math.floor(this.stream() * max);\n    },\n    pick: function (seq) {\n      return seq[this.number(seq.length)];\n    },\n    pickDist: function (items) {\n      var total = 0;\n      for (var a in items) {\n        if (! items.hasOwnProperty(a)) {\n          continue;\n        }\n        if (typeof items[a] != \"number\") {\n          throw \"Bad property: \" + a + \" not a number\";\n        }\n        total += items[a];\n      }\n      var num = this.number(total);\n      var last;\n      for (a in items) {\n        if (! items.hasOwnProperty(a)) {\n          continue;\n        }\n        last = a;\n        if (num < items[a]) {\n          return a;\n        }\n        num -= items[a];\n      }\n      // FIXME: not sure if this should ever h\n      return last;\n    },\n    string: function (len, chars) {\n      var s = \"\";\n      for (var i=0; i<len; i++) {\n        s += this.character(chars);\n      }\n      return s;\n    },\n    character: function (chars) {\n      chars = chars || this.defaultChars;\n      return chars.charAt(this.number(chars.length));\n    }\n  });\n\n  Randomizer.prototype.lower = \"abcdefghijklmnopqrstuvwxyz\";\n  Randomizer.prototype.upper = Randomizer.prototype.lower.toUpperCase();\n  Randomizer.prototype.numberCharacters = \"0123456789\";\n  Randomizer.prototype.whitespace = \" \\t\\n\";\n  Randomizer.prototype.punctuation = \"~`!@#$%^&*()_-+={}[]|\\\\;:'\\\"<>,./?\";\n  Randomizer.prototype.defaultChars =\n      Randomizer.prototype.lower + Randomizer.prototype.upper +\n      Randomizer.prototype.numberCharacters + Randomizer.prototype.whitespace +\n      Randomizer.prototype.punctuation;\n\n  return Randomizer;\n});\n"
  },
  {
    "path": "togetherjs/recorder.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>TogetherJS recorder</title>\n    <script>\n      TogetherJSConfig_noAutoStart = true;\n    </script>\n    <script src=\"../togetherjs.js\"></script>\n    <script>\n      var config = TogetherJS._extend(TogetherJS.requireConfig);\n      config.deps = [\"recorder\"];\n      config.callback = function () {\n        console.log(\"got back\");\n        require({context: \"togetherjs\"})([\"recorder\"], function (recorder) {\n          recorder.start({\n            baseUrl: TogetherJS.baseUrl,\n            defaultHubBase: TogetherJS.config.get(\"hubBase\")\n          });\n        });\n      };\n      require = config;\n      console.log(\"required\");\n    </script>\n    <script src=\"./libs/require.js\"></script>\n    <link rel=\"stylesheet\" href=\"recorder.css\">\n  </head>\n  <body>\n\n<div id=\"connection-status\">\n  <span id=\"not-connected\" data-toggles=\"#connection-status span\">Not Connected</span>\n  <span id=\"connected\" data-toggles=\"#connection-status span\" style=\"display: none\">Connected</span>\n  <span id=\"no-session-id\" data-toggles=\"#connection-status span\" style=\"display: none\">There's no <code>#&amp;togetherjs=SESSION_ID</code> in the URL.</span>\n  <button id=\"restart\">Restart recording</button>\n  <button id=\"select\">Select record</button>\n</div>\n\n<div>\n  <textarea id=\"record\">/* TogetherJS session starts */\n\n</textarea>\n</div>\n\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/recorder.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"jquery\", \"util\", \"channels\"], function ($, util, channels) {\n  var recorder = util.Module(\"recorder\");\n  var assert = util.assert;\n  var channel = null;\n  var baseUrl = null;\n  var clientId = \"recorder\";\n\n  function display(el) {\n    el = $(el);\n    var toggles = el.attr(\"data-toggles\");\n    if (toggles) {\n      $(toggles).hide();\n    }\n    el.show();\n  }\n\n  recorder.start = function (options) {\n    $(function () {\n      $(\"#record\").css({height: $(window).height() - 50});\n      $(\"#restart\").click(function () {\n        location.reload();\n      });\n      $(\"#select\").click(function () {\n        $(\"#record\").select();\n      });\n      recorder.activate(options);\n    });\n  };\n\n  recorder.activate = function (options) {\n    var match;\n    baseUrl = options.baseUrl;\n    recorder.shareId = TogetherJS.startup._joinShareId;\n    if (! recorder.shareId) {\n      match = /\\&togetherjs=([^&]+)/.exec(location.hash);\n      if (! match) {\n        display(\"#no-session-id\");\n        return;\n      }\n      recorder.shareId = match[1];\n    }\n    var hubBase = options.defaultHubBase;\n    match = /\\&hubBase=([^&]+)/.exec(location.hash);\n    if (match) {\n      hubBase = match[1];\n    }\n    hubBase = hubBase.replace(/\\/*$/, \"\");\n    var url = hubBase + \"/hub/\" + recorder.shareId;\n    channel = channels.WebSocketChannel(url);\n    channel.onmessage = function (msg) {\n      if (msg.type == \"hello-back\") {\n        display(\"#connected\");\n      }\n      if (msg.type == \"hello\") {\n        sendHello(true);\n      }\n      if (msg.type == \"get-logs\") {\n        sendLogs(msg);\n        return;\n      }\n      recorder.logMessage(msg);\n    };\n    sendHello(false);\n  };\n\n  function sendHello(helloBack) {\n    var msg = {\n      type: helloBack ? \"hello-back\" : \"hello\",\n      name: \"Recorder 'bot\",\n      // FIXME: replace with robot:\n      avatar: TogetherJS.baseUrl + \"/togetherjs/images/robot-avatar.png\",\n      color: \"#888888\",\n      rtcSupported: false,\n      clientId: clientId,\n      url: \"about:blank\"\n    };\n    channel.send(msg);\n  }\n\n  function sendLogs(req) {\n    var msg = {\n      type: \"logs\",\n      clientId: clientId,\n      logs: $(\"#record\").val(),\n      request: req\n    };\n    channel.send(msg);\n  }\n\n  recorder.logMessage = function (msg) {\n    msg.date = Date.now();\n    msg = JSON.stringify(msg);\n    var $record = $(\"#record\");\n    $record.val($record.val() + msg + \"\\n\\n\");\n  };\n\n  $(window).unload(function () {\n    channel.send({\n      type: \"bye\",\n      clientId: clientId\n    });\n  });\n\n  return recorder;\n\n});\n"
  },
  {
    "path": "togetherjs/recorder.less",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\nbody {\n    font-family: sans-serif;\n}\n\n#record {\n    width: 100%;\n    height: 80%;\n}\n\n#connected {\n    font-weight: bold;\n    color: #090;\n}\n\n#not-connected {\n    color: #900;\n}\n"
  },
  {
    "path": "togetherjs/reset.less",
    "content": "/* .togetherjs reset */\n/* http://yuilibrary.com/yui/docs/cssreset/ */\n.togetherjs {\n\n* {\n    -webkit-box-sizing: content-box !important;\n    -moz-box-sizing: content-box !important;\n    box-sizing: content-box !important;\n}\n\nheader {\n    width: auto;\n}\n\n/*\nYUI 3.10.3 (build 2fb5187)\nCopyright 2013 Yahoo! Inc. All rights reserved.\nLicensed under the BSD License.\nhttp://yuilibrary.com/license/\n*/\n\ndiv,\ndl,\ndt,\ndd,\nul,\nol,\nli,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\npre,\ncode,\nform,\nfieldset,\nlegend,\ninput,\ntextarea,\np,\nblockquote,\nth,\ntd {\n\tmargin:0;\n\tpadding:0;\n}\ntable {\n\tborder-collapse:collapse;\n\tborder-spacing:0;\n}\nfieldset,\nimg {\n\tborder:0;\n}\n/*\n\tTODO think about hanlding inheritence differently, maybe letting IE6 fail a bit...\n*/\naddress,\ncaption,\ncite,\ncode,\ndfn,\nem,\nstrong,\nth,\nvar {\n\tfont-style:normal;\n\tfont-weight:normal;\n}\n\nol,\nul {\n\tlist-style:none;\n}\n\ncaption,\nth {\n\ttext-align:left;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n\tfont-size:100%;\n\tfont-weight:normal;\n}\nq:before,\nq:after {\n\tcontent:'';\n}\nabbr,\nacronym {\n\tborder:0;\n\tfont-variant:normal;\n}\n/* to preserve line-height and selector appearance */\nsup {\n\tvertical-align:text-top;\n}\nsub {\n\tvertical-align:text-bottom;\n}\ninput,\ntextarea,\nselect {\n\tfont-family:inherit;\n\tfont-size:inherit;\n\tfont-weight:inherit;\n}\n/*to enable resizing for IE*/\ninput,\ntextarea,\nselect {\n\t*font-size:100%;\n}\n/*because legend doesn't inherit in IE */\nlegend {\n\tcolor:#000;\n}\n\n}\n"
  },
  {
    "path": "togetherjs/session.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"require\", \"util\", \"channels\", \"jquery\", \"storage\"], function (require, util, channels, $, storage) {\n\n  var DEBUG = true;\n\n  // This is the amount of time in which a hello-back must be received after a hello\n  // for us to respect a URL change:\n  var HELLO_BACK_CUTOFF = 1500;\n\n  var session = util.mixinEvents(util.Module(\"session\"));\n  var assert = util.assert;\n\n  // We will load this module later (there's a circular import):\n  var peers;\n\n  // This is the hub we connect to:\n  session.shareId = null;\n  // This is the ID that identifies this client:\n  session.clientId = null;\n  session.router = channels.Router();\n  // Indicates if TogetherJS has just started (not continuing from a saved session):\n  session.firstRun = false;\n\n  // This is the key we use for localStorage:\n  var localStoragePrefix = \"togetherjs.\";\n  // This is the channel to the hub:\n  var channel = null;\n\n  // Setting, essentially global:\n  session.AVATAR_SIZE = 90;\n\n  var MAX_SESSION_AGE = 30*24*60*60*1000; // 30 days\n\n  /****************************************\n   * URLs\n   */\n  var includeHashInUrl = TogetherJS.config.get(\"includeHashInUrl\");\n  TogetherJS.config.close(\"includeHashInUrl\");\n  var currentUrl = (location.href + \"\").replace(/\\#.*$/, \"\");\n  if (includeHashInUrl) {\n    currentUrl = location.href;\n  }\n\n  session.hubUrl = function (id) {\n    id = id || session.shareId;\n    assert(id, \"URL cannot be resolved before TogetherJS.shareId has been initialized\");\n    TogetherJS.config.close(\"hubBase\");\n    var hubBase = TogetherJS.config.get(\"hubBase\");\n    return hubBase.replace(/\\/*$/, \"\") + \"/hub/\" + id;\n  };\n\n  session.shareUrl = function () {\n    assert(session.shareId, \"Attempted to access shareUrl() before shareId is set\");\n    var hash = location.hash;\n    var m = /\\?[^#]*/.exec(location.href);\n    var query = \"\";\n    if (m) {\n      query = m[0];\n    }\n    hash = hash.replace(/&?togetherjs-[a-zA-Z0-9]+/, \"\");\n    hash = hash || \"#\";\n    return location.protocol + \"//\" + location.host + location.pathname + query +\n           hash + \"&togetherjs=\" + session.shareId;\n  };\n\n  session.recordUrl = function () {\n    assert(session.shareId);\n    var url = TogetherJS.baseUrl.replace(/\\/*$/, \"\") + \"/togetherjs/recorder.html\";\n    url += \"#&togetherjs=\" + session.shareId + \"&hubBase=\" + TogetherJS.config.get(\"hubBase\");\n    return url;\n  };\n\n  /* location.href without the hash */\n  session.currentUrl = function () {\n    if (includeHashInUrl) {\n      return location.href;\n    } else {\n      return location.href.replace(/#.*/, \"\");\n    }\n  };\n\n  /****************************************\n   * Message handling/dispatching\n   */\n\n  session.hub = util.mixinEvents({});\n\n  var IGNORE_MESSAGES = TogetherJS.config.get(\"ignoreMessages\");\n  if (IGNORE_MESSAGES === true) {\n    DEBUG = false;\n    IGNORE_MESSAGES = [];\n  }\n  // These are messages sent by clients who aren't \"part\" of the TogetherJS session:\n  var MESSAGES_WITHOUT_CLIENTID = [\"who\", \"invite\", \"init-connection\"];\n\n  // We ignore incoming messages from the channel until this is true:\n  var readyForMessages = false;\n\n  function openChannel() {\n    assert(! channel, \"Attempt to re-open channel\");\n    console.info(\"Connecting to\", session.hubUrl(), location.href);\n    var c = channels.WebSocketChannel(session.hubUrl());\n    c.onmessage = function (msg) {\n      if (! readyForMessages) {\n        if (DEBUG) {\n          console.info(\"In (but ignored for being early):\", msg);\n        }\n        return;\n      }\n      if (DEBUG && IGNORE_MESSAGES.indexOf(msg.type) == -1) {\n        console.info(\"In:\", msg);\n      }\n      if (! peers) {\n        // We're getting messages before everything is fully initialized\n        console.warn(\"Message received before all modules loaded (ignoring):\", msg);\n        return;\n      }\n      if ((! msg.clientId) && MESSAGES_WITHOUT_CLIENTID.indexOf(msg.type) == -1) {\n        console.warn(\"Got message without clientId, where clientId is required\", msg);\n        return;\n      }\n      if (msg.clientId) {\n        msg.peer = peers.getPeer(msg.clientId, msg);\n      }\n      if (msg.type == \"hello\" || msg.type == \"hello-back\" || msg.type == \"peer-update\") {\n        // We do this here to make sure this is run before any other\n        // hello handlers:\n        msg.peer.updateFromHello(msg);\n      }\n      if (msg.peer) {\n        msg.sameUrl = msg.peer.url == currentUrl;\n        if (!msg.peer.isSelf) {\n          msg.peer.updateMessageDate(msg);\n        }\n      }\n      session.hub.emit(msg.type, msg);\n      TogetherJS._onmessage(msg);\n    };\n    channel = c;\n    session.router.bindChannel(channel);\n  }\n\n  session.send = function (msg) {\n    if (DEBUG && IGNORE_MESSAGES.indexOf(msg.type) == -1) {\n      console.info(\"Send:\", msg);\n    }\n    msg.clientId = session.clientId;\n    channel.send(msg);\n  };\n\n  session.appSend = function (msg) {\n    var type = msg.type;\n    if (type.search(/^togetherjs\\./) === 0) {\n      type = type.substr(\"togetherjs.\".length);\n    } else if (type.search(/^app\\./) === -1) {\n      type = \"app.\" + type;\n    }\n    msg.type = type;\n    session.send(msg);\n  };\n\n  /****************************************\n   * Standard message responses\n   */\n\n  /* Always say hello back, and keep track of peers: */\n  session.hub.on(\"hello hello-back\", function (msg) {\n    if (msg.type == \"hello\") {\n      sendHello(true);\n    }\n    if (session.isClient && (! msg.isClient) &&\n        session.firstRun && session.timeHelloSent &&\n        Date.now() - session.timeHelloSent < HELLO_BACK_CUTOFF) {\n      processFirstHello(msg);\n    }\n  });\n\n  session.hub.on(\"who\", function (msg) {\n    sendHello(true);\n  });\n\n  function processFirstHello(msg) {\n    if (! msg.sameUrl) {\n      var url = msg.url;\n      if (msg.urlHash) {\n        url += msg.urlHash;\n      }\n      require(\"ui\").showUrlChangeMessage(msg.peer, url);\n      location.href = url;\n    }\n  }\n\n  session.timeHelloSent = null;\n\n  function sendHello(helloBack) {\n    var msg = session.makeHelloMessage(helloBack);\n    if (! helloBack) {\n      session.timeHelloSent = Date.now();\n      peers.Self.url = msg.url;\n    }\n    session.send(msg);\n  }\n\n  session.makeHelloMessage = function (helloBack) {\n    var msg = {\n      name: peers.Self.name || peers.Self.defaultName,\n      avatar: peers.Self.avatar,\n      color: peers.Self.color,\n      url: session.currentUrl(),\n      urlHash: location.hash,\n      // FIXME: titles update, we should track those changes:\n      title: document.title,\n      rtcSupported: session.RTCSupported,\n      isClient: session.isClient\n    };\n    if (helloBack) {\n      msg.type = \"hello-back\";\n    } else {\n      msg.type = \"hello\";\n      msg.clientVersion = TogetherJS.version;\n    }\n    if (! TogetherJS.startup.continued) {\n      msg.starting = true;\n    }\n    // This is a chance for other modules to effect the hello message:\n    session.emit(\"prepare-hello\", msg);\n    return msg;\n  };\n  /****************************************\n   * Lifecycle (start and end)\n   */\n\n  // These are Javascript files that implement features, and so must\n  // be injected at runtime because they aren't pulled in naturally\n  // via define().\n  // ui must be the first item:\n  var features = [\"peers\", \"ui\", \"chat\", \"webrtc\", \"cursor\", \"startup\", \"videos\", \"forms\", \"visibilityApi\", \"youtubeVideos\"];\n\n  function getRoomName(prefix, maxSize) {\n    var findRoom = TogetherJS.config.get(\"hubBase\").replace(/\\/*$/, \"\") + \"/findroom\";\n    return $.ajax({\n      url: findRoom,\n      dataType: \"json\",\n      data: {prefix: prefix, max: maxSize}\n    }).then(function (resp) {\n      return resp.name;\n    });\n  }\n\n  function initIdentityId() {\n    return util.Deferred(function (def) {\n      if (session.identityId) {\n        def.resolve();\n        return;\n      }\n      storage.get(\"identityId\").then(function (identityId) {\n        if (! identityId) {\n          identityId = util.generateId();\n          storage.set(\"identityId\", identityId);\n        }\n        session.identityId = identityId;\n        // We don't actually have to wait for the set to succede, so\n        // long as session.identityId is set\n        def.resolve();\n      });\n    });\n  }\n\n  initIdentityId.done = initIdentityId();\n\n  function initShareId() {\n    return util.Deferred(function (def) {\n      var hash = location.hash;\n      var shareId = session.shareId;\n      var isClient = true;\n      var set = true;\n      var sessionId;\n      session.firstRun = ! TogetherJS.startup.continued;\n      if (! shareId) {\n        if (TogetherJS.startup._joinShareId) {\n          // Like, below, this *also* means we got the shareId from the hash\n          // (in togetherjs.js):\n          shareId = TogetherJS.startup._joinShareId;\n        }\n      }\n      if (! shareId) {\n        // FIXME: I'm not sure if this will ever happen, because togetherjs.js should\n        // handle it\n        var m = /&?togetherjs=([^&]*)/.exec(hash);\n        if (m) {\n          isClient = ! m[1];\n          shareId = m[2];\n          var newHash = hash.substr(0, m.index) + hash.substr(m.index + m[0].length);\n          location.hash = newHash;\n        }\n      }\n      return storage.tab.get(\"status\").then(function (saved) {\n        var findRoom = TogetherJS.config.get(\"findRoom\");\n        TogetherJS.config.close(\"findRoom\");\n        if (findRoom && saved && findRoom != saved.shareId) {\n          console.info(\"Ignoring findRoom in lieu of continued session\");\n        } else if (findRoom && TogetherJS.startup._joinShareId) {\n          console.info(\"Ignoring findRoom in lieu of explicit invite to session\");\n        }\n        if (findRoom && typeof findRoom == \"string\" && (! saved) && (! TogetherJS.startup._joinShareId)) {\n          isClient = true;\n          shareId = findRoom;\n          sessionId = util.generateId();\n        } else if (findRoom && (! saved) && (! TogetherJS.startup._joinShareId)) {\n          assert(findRoom.prefix && typeof findRoom.prefix == \"string\", \"Bad findRoom.prefix\", findRoom);\n          assert(findRoom.max && typeof findRoom.max == \"number\" && findRoom.max > 0,\n                 \"Bad findRoom.max\", findRoom);\n          sessionId = util.generateId();\n          if (findRoom.prefix.search(/[^a-zA-Z0-9]/) != -1) {\n            console.warn(\"Bad value for findRoom.prefix:\", JSON.stringify(findRoom.prefix));\n          }\n          getRoomName(findRoom.prefix, findRoom.max).then(function (shareId) {\n            // FIXME: duplicates code below:\n            session.clientId = session.identityId + \".\" + sessionId;\n            storage.tab.set(\"status\", {reason: \"joined\", shareId: shareId, running: true, date: Date.now(), sessionId: sessionId});\n            session.isClient = true;\n            session.shareId = shareId;\n            session.emit(\"shareId\");\n            def.resolve(session.shareId);\n          });\n          return;\n        } else if (TogetherJS.startup._launch) {\n          if (saved) {\n            isClient = saved.reason == \"joined\";\n            if (! shareId) {\n              shareId = saved.shareId;\n            }\n            sessionId = saved.sessionId;\n          } else {\n            isClient = TogetherJS.startup.reason == \"joined\";\n            assert(! sessionId);\n            sessionId = util.generateId();\n          }\n          if (! shareId) {\n            shareId = util.generateId();\n          }\n        } else if (saved) {\n          isClient = saved.reason == \"joined\";\n          TogetherJS.startup.reason = saved.reason;\n          TogetherJS.startup.continued = true;\n          shareId = saved.shareId;\n          sessionId = saved.sessionId;\n          // The only case when we don't need to set the storage status again is when\n          // we're already set to be running\n          set = ! saved.running;\n        } else {\n          throw new util.AssertionError(\"No saved status, and no startup._launch request; why did TogetherJS start?\");\n        }\n        assert(session.identityId);\n        session.clientId = session.identityId + \".\" + sessionId;\n        if (set) {\n          storage.tab.set(\"status\", {reason: TogetherJS.startup.reason, shareId: shareId, running: true, date: Date.now(), sessionId: sessionId});\n        }\n        session.isClient = isClient;\n        session.shareId = shareId;\n        session.emit(\"shareId\");\n        def.resolve(session.shareId);\n      });\n    });\n  }\n\n  function initStartTarget() {\n    var id;\n    if (TogetherJS.startup.button) {\n      id = TogetherJS.startup.button.id;\n      if (id) {\n        storage.set(\"startTarget\", id);\n      }\n      return;\n    }\n    storage.get(\"startTarget\").then(function (id) {\n      var el = document.getElementById(id);\n      if (el) {\n        TogetherJS.startup.button = el;\n      }\n    });\n  }\n  session.start = function () {\n    initStartTarget();\n    initIdentityId().then(function () {\n      initShareId().then(function () {\n        readyForMessages = false;\n        openChannel();\n        require([\"ui\"], function (ui) {\n          TogetherJS.running = true;\n          ui.prepareUI();\n          require(features, function () {\n            $(function () {\n              peers = require(\"peers\");\n              var startup = require(\"startup\");\n              session.emit(\"start\");\n              session.once(\"ui-ready\", function () {\n                readyForMessages = true;\n                startup.start();\n              });\n              ui.activateUI();\n              TogetherJS.config.close(\"enableAnalytics\");\n              if (TogetherJS.config.get(\"enableAnalytics\")) {\n                require([\"analytics\"], function (analytics) {\n                  analytics.activate();\n                });\n              }\n              peers._SelfLoaded.then(function () {\n                sendHello(false);\n              });\n              TogetherJS.emit(\"ready\");\n            });\n          });\n        });\n      });\n    });\n  };\n\n  session.close = function (reason) {\n    TogetherJS.running = false;\n    var msg = {type: \"bye\"};\n    if (reason) {\n      msg.reason = reason;\n    }\n    session.send(msg);\n    session.emit(\"close\");\n    var name = window.name;\n    storage.tab.get(\"status\").then(function (saved) {\n      if (! saved) {\n        console.warn(\"No session information saved in\", \"status.\" + name);\n      } else {\n        saved.running = false;\n        saved.date = Date.now();\n        storage.tab.set(\"status\", saved);\n      }\n      channel.close();\n      channel = null;\n      session.shareId = null;\n      session.emit(\"shareId\");\n      TogetherJS.emit(\"close\");\n      TogetherJS._teardown();\n    });\n  };\n\n  session.on(\"start\", function () {\n    $(window).on(\"resize\", resizeEvent);\n    if (includeHashInUrl) {\n      $(window).on(\"hashchange\", hashchangeEvent);\n    }\n  });\n\n  session.on(\"close\", function () {\n    $(window).off(\"resize\", resizeEvent);\n    if (includeHashInUrl) {\n      $(window).off(\"hashchange\", hashchangeEvent);\n    }\n  });\n\n  function hashchangeEvent() {\n    // needed because when message arives from peer this variable will be checked to\n    // decide weather to show actions or not\n    sendHello(false);\n  }\n\n  function resizeEvent() {\n    session.emit(\"resize\");\n  }\n\n  if (TogetherJS.startup._launch) {\n    setTimeout(session.start);\n  }\n\n  util.testExpose({\n    getChannel: function () {\n      return channel;\n    }\n  });\n\n  return session;\n});\n"
  },
  {
    "path": "togetherjs/startup.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/* This module handles all the different UI that happens (sometimes in order) when\n   TogetherJS is started:\n\n   - Introduce the session when you've been invited\n   - Show any browser compatibility indicators\n   - Show the walkthrough the first time\n   - Show the share link window\n\n   When everything is done it fires session.emit(\"startup-ready\")\n\n*/\ndefine([\"util\", \"require\", \"jquery\", \"windowing\", \"storage\"], function (util, require, $, windowing, storage) {\n  var assert = util.assert;\n  var startup = util.Module(\"startup\");\n  // Avoid circular import:\n  var session = null;\n\n  var STEPS = [\n    \"browserBroken\",\n    \"browserUnsupported\",\n    \"sessionIntro\",\n    \"walkthrough\",\n    // Look in the share() below if you add anything after here:\n    \"share\"\n    ];\n\n  var currentStep = null;\n\n  startup.start = function () {\n    if (! session) {\n      require([\"session\"], function (sessionModule) {\n        session = sessionModule;\n        startup.start();\n      });\n      return;\n    }\n    var index = -1;\n    if (currentStep) {\n      index = STEPS.indexOf(currentStep);\n    }\n    index++;\n    if (index >= STEPS.length) {\n      session.emit(\"startup-ready\");\n      return;\n    }\n    currentStep = STEPS[index];\n    handlers[currentStep](startup.start);\n  };\n\n  var handlers = {\n\n    browserBroken: function (next) {\n      if (window.WebSocket) {\n        next();\n        return;\n      }\n      windowing.show(\"#togetherjs-browser-broken\", {\n        onClose: function () {\n          session.close();\n        }\n      });\n      if ($.browser.msie) {\n        $(\"#togetherjs-browser-broken-is-ie\").show();\n      }\n    },\n\n    browserUnsupported: function (next) {\n        next();\n    },\n\n    sessionIntro: function (next) {\n      if ((! session.isClient) || ! session.firstRun) {\n        next();\n        return;\n      }\n      TogetherJS.config.close(\"suppressJoinConfirmation\");\n      if (TogetherJS.config.get(\"suppressJoinConfirmation\")) {\n        next();\n        return;\n      }\n      var cancelled = false;\n      windowing.show(\"#togetherjs-intro\", {\n        onClose: function () {\n          if (! cancelled) {\n            next();\n          }\n        }\n      });\n      $(\"#togetherjs-intro .togetherjs-modal-dont-join\").click(function () {\n        cancelled = true;\n        windowing.hide();\n        session.close(\"declined-join\");\n      });\n    },\n\n    walkthrough: function (next) {\n      storage.settings.get(\"seenIntroDialog\").then(function (seenIntroDialog) {\n        if (seenIntroDialog) {\n          next();\n          return;\n        }\n        require([\"walkthrough\"], function (walkthrough) {\n          walkthrough.start(true, function () {\n            storage.settings.set(\"seenIntroDialog\", true);\n            next();\n          });\n        });\n      });\n    },\n\n    share: function (next) {\n      TogetherJS.config.close(\"suppressInvite\");\n      if (session.isClient || (! session.firstRun) ||\n          TogetherJS.config.get(\"suppressInvite\")) {\n        next();\n        return;\n      }\n      require([\"windowing\"], function (windowing) {\n        windowing.show(\"#togetherjs-share\");\n        // FIXME: no way to detect when the window is closed\n        // If there was a next() step then it would not work\n      });\n    }\n\n  };\n\n  return startup;\n});\n"
  },
  {
    "path": "togetherjs/storage.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"util\"], function (util) {\n  var assert = util.assert;\n  var Deferred = util.Deferred;\n  var DEFAULT_SETTINGS = {\n    name: \"\",\n    defaultName: \"\",\n    avatar: null,\n    stickyShare: null,\n    color: null,\n    seenIntroDialog: false,\n    seenWalkthrough: false,\n    dontShowRtcInfo: false\n  };\n\n  var DEBUG_STORAGE = false;\n\n  var Storage = util.Class({\n    constructor: function (name, storage, prefix) {\n      this.name = name;\n      this.storage = storage;\n      this.prefix = prefix;\n    },\n\n    get: function (key, defaultValue) {\n      var self = this;\n      return Deferred(function (def) {\n        // Strictly this isn't necessary, but eventually I want to move to something more\n        // async for the storage, and this simulates that much better.\n        setTimeout(util.resolver(def, function () {\n          key = self.prefix + key;\n          var value = self.storage.getItem(key);\n          if (! value) {\n            value = defaultValue;\n            if (DEBUG_STORAGE) {\n              console.debug(\"Get storage\", key, \"defaults to\", value);\n            }\n          } else {\n            value = JSON.parse(value);\n            if (DEBUG_STORAGE) {\n              console.debug(\"Get storage\", key, \"=\", value);\n            }\n          }\n          return value;\n        }));\n      });\n    },\n\n    set: function (key, value) {\n      var self = this;\n      if (value !== undefined) {\n        value = JSON.stringify(value);\n      }\n      return Deferred(function (def) {\n        key = self.prefix + key;\n        if (value === undefined) {\n          self.storage.removeItem(key);\n          if (DEBUG_STORAGE) {\n            console.debug(\"Delete storage\", key);\n          }\n        } else {\n          self.storage.setItem(key, value);\n          if (DEBUG_STORAGE) {\n            console.debug(\"Set storage\", key, value);\n          }\n        }\n        setTimeout(def.resolve);\n      });\n    },\n\n    clear: function () {\n      var self = this;\n      var promises = [];\n      return Deferred((function (def) {\n        this.keys().then(function (keys) {\n          keys.forEach(function (key) {\n            // FIXME: technically we're ignoring the promise returned by all\n            // these sets:\n            promises.push(self.set(key, undefined));\n          });\n          util.resolveMany(promises).then(function () {\n            def.resolve();\n          });\n        });\n      }).bind(this));\n    },\n\n    keys: function (prefix, excludePrefix) {\n      // Returns a list of keys, potentially with the given prefix\n      var self = this;\n      return Deferred(function (def) {\n        setTimeout(util.resolver(def, function () {\n          prefix = prefix || \"\";\n          var result = [];\n          for (var i = 0; i < self.storage.length; i++) {\n            var key = self.storage.key(i);\n            if (key.indexOf(self.prefix + prefix) === 0) {\n              var shortKey = key.substr(self.prefix.length);\n              if (excludePrefix) {\n                shortKey = shortKey.substr(prefix.length);\n              }\n              result.push(shortKey);\n            }\n          }\n          return result;\n        }));\n      });\n    },\n\n    toString: function () {\n      return '[storage for ' + this.name + ']';\n    }\n\n  });\n\n  var namePrefix = TogetherJS.config.get(\"storagePrefix\");\n  TogetherJS.config.close(\"storagePrefix\");\n\n  var storage = Storage('localStorage', localStorage, namePrefix + \".\");\n\n  storage.settings = util.mixinEvents({\n    defaults: DEFAULT_SETTINGS,\n\n    get: function (name) {\n      assert(storage.settings.defaults.hasOwnProperty(name), \"Unknown setting:\", name);\n      return storage.get(\"settings.\" + name, storage.settings.defaults[name]);\n    },\n\n    set: function (name, value) {\n      assert(storage.settings.defaults.hasOwnProperty(name), \"Unknown setting:\", name);\n      return storage.set(\"settings.\" + name, value);\n    }\n\n  });\n\n  storage.tab = Storage('sessionStorage', sessionStorage, namePrefix + \"-session.\");\n\n  return storage;\n});\n"
  },
  {
    "path": "togetherjs/templates-localized.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([], function () {\n  return {\n    \"interface\": \"__interface_html__\",\n    walkthrough: \"__walkthrough_html__\",\n    names: \"__names__\"\n  };\n});\n"
  },
  {
    "path": "togetherjs/templates.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// FIXME: maybe it would be better to dynamically assemble the first\n// argument to define() here to include the localized module:\ndefine([\"util\", \"require\"], function (util, require) {\n  var assert = util.assert;\n\n  function clean(t) {\n    // Removes <% /* ... */ %> comments:\n    t = t.replace(/[<][%]\\s*\\/\\*[\\S\\s\\r\\n]*\\*\\/\\s*[%][>]/, \"\");\n    t = util.trim(t);\n    t = t.replace(/http:\\/\\/localhost:8080/g, TogetherJS.baseUrl);\n    t = t.replace(/TOOL_NAME/g, '<span class=\"togetherjs-tool-name\">TogetherJS</span>');\n    t = t.replace(/SITE_NAME/g, '<strong class=\"togetherjs-site-name\">[site name]</strong>');\n    t = t.replace(/TOOL_SITE_LINK/g, '<a href=\"https://togetherjs.com/\" target=\"_blank\"><span class=\"togetherjs-tool-name\">TogetherJS</span></a>');\n    return t;\n  }\n\n  var lang = TogetherJS.getConfig(\"lang\") || \"en-US\";\n  var moduleName = \"templates-\" + lang;\n  var templatesLang;\n  require([moduleName], function (mod) {\n    templatesLang = mod;\n  });\n\n  return function (resourceName) {\n    // Sometimes require([moduleName]) doesn't return even after the\n    // module has been loaded, but this sync version of require() will\n    // pick up the module in that case:\n    if (! templatesLang) {\n      try {\n        templatesLang = require(moduleName);\n      } catch (e) {\n        console.warn(\"Error requiring module:\", e);\n      }\n    }\n    assert(templatesLang, \"Templates not yet loaded\");\n    return clean(templatesLang[resourceName]);\n  };\n\n});\n"
  },
  {
    "path": "togetherjs/templating.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\ndefine([\"jquery\", \"util\", \"peers\", \"windowing\", \"session\"], function ($, util, peers, windowing, session) {\n  var assert = util.assert;\n  var templating = util.Module(\"templating\");\n\n  templating.clone = function (templateId) {\n    templateId = \"#togetherjs-template-\" + templateId;\n    var template = $(templateId);\n    assert(template.length, \"No template found with id:\", templateId);\n    template = template.clone();\n    template.attr(\"id\", null);\n    // FIXME: if called directly, doesn't emit new-element event:\n    return template;\n  };\n\n  templating.sub = function (templateId, variables) {\n    var template = templating.clone(templateId);\n    variables = variables || {};\n    util.forEachAttr(variables, function (value, attr) {\n      // FIXME: do the substitution... somehow?\n      var subs = template.find(\".togetherjs-sub-\" + attr).removeClass(\"togetherjs-sub-\" + attr);\n      if (subs.length) {\n        if (typeof value == \"string\") {\n          subs.text(value);\n        } else if (value instanceof $) {\n          subs.append(value);\n        } else {\n          assert(false, \"Unknown variable value type:\", attr, \"=\", value);\n        }\n      }\n      var ifs = template.find(\".togetherjs-if-\" + attr).removeClass(\"togetherjs-sub-\" + attr);\n      if (! value) {\n        ifs.hide();\n      }\n      ifs = template.find(\".togetherjs-ifnot-\" + attr).removeClass(\"togetherjs-ifnot-\" + attr);\n      if (value) {\n        ifs.hide();\n      }\n      var attrName = \"data-togetherjs-subattr-\" + attr;\n      var attrs = template.find(\"[\" + attrName + \"]\");\n      attrs.each(function (index, element) {\n        assert(typeof value == \"string\");\n        element = $(element);\n        var subAttribute = element.attr(attrName);\n        element.attr(attrName, null);\n        element.attr(subAttribute, value);\n      });\n    });\n    if (variables.peer) {\n      variables.peer.view.setElement(template);\n    }\n    if (variables.date) {\n      var date = variables.date;\n      if (typeof date == \"number\") {\n        date = new Date(date);\n      }\n      var ampm = \"AM\";\n      var hour = date.getHours();\n      if (hour > 12) {\n        hour -= 12;\n        ampm = \"PM\";\n      }\n      var minute = date.getMinutes();\n      var t = hour + \":\";\n      if (minute < 10) {\n        t += \"0\";\n      }\n      t += minute;\n      template.find(\".togetherjs-time\").text(t);\n      template.find(\".togetherjs-ampm\").text(ampm);\n    }\n\n    // FIXME: silly this is on session:\n    session.emit(\"new-element\", template);\n    return template;\n  };\n\n  return templating;\n});\n"
  },
  {
    "path": "togetherjs/tests/ace.js",
    "content": "(function(){function h(a){var c=function(a,b){return e(\"\",a,b)},f=b;a&&(b[a]||(b[a]={}),f=b[a]);if(!f.define||!f.define.packaged)d.original=f.define,f.define=d,f.define.packaged=!0;if(!f.require||!f.require.packaged)e.original=f.require,f.require=c,f.require.packaged=!0}var a=\"ace\",b=function(){return this}();if(!a&&typeof requirejs!=\"undefined\"){var c=b.define;b.define=function(a,b,d){return typeof d!=\"function\"?c.apply(this,arguments):ace.define(a,b,function(a,c,e){return b[2]==\"module\"&&(e.packaged=!0),d.apply(this,arguments)})},b.define.packaged=!0;return}var d=function(a,b,c){if(typeof a!=\"string\"){d.original?d.original.apply(window,arguments):(console.error(\"dropping module because define wasn't a string.\"),console.trace());return}arguments.length==2&&(c=b),d.modules||(d.modules={}),d.modules[a]=c},e=function(a,b,c){if(Object.prototype.toString.call(b)===\"[object Array]\"){var d=[];for(var f=0,h=b.length;f<h;++f){var i=g(a,b[f]);if(!i&&e.original)return e.original.apply(window,arguments);d.push(i)}c&&c.apply(null,d)}else{if(typeof b==\"string\"){var j=g(a,b);return!j&&e.original?e.original.apply(window,arguments):(c&&c(),j)}if(e.original)return e.original.apply(window,arguments)}},f=function(a,b){if(b.indexOf(\"!\")!==-1){var c=b.split(\"!\");return f(a,c[0])+\"!\"+f(a,c[1])}if(b.charAt(0)==\".\"){var d=a.split(\"/\").slice(0,-1).join(\"/\");b=d+\"/\"+b;while(b.indexOf(\".\")!==-1&&e!=b){var e=b;b=b.replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return b},g=function(a,b){b=f(a,b);var c=d.modules[b];if(!c)return null;if(typeof c==\"function\"){var g={},h={id:b,uri:\"\",exports:g,packaged:!0},i=function(a,c){return e(b,a,c)},j=c(i,g,h);return g=j||h.exports,d.modules[b]=g,g}return c};h(a)})(),ace.define(\"ace/requirejs/text\",[\"require\",\"exports\",\"module\"],function(a,b,c){b.load=function(b,c,d,e){a(\"ace/lib/net\").get(c.toUrl(b),d)}}),ace.define(\"ace/ace\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/editor\",\"ace/edit_session\",\"ace/undomanager\",\"ace/virtual_renderer\",\"ace/multi_select\",\"ace/worker/worker_client\",\"ace/keyboard/hash_handler\",\"ace/keyboard/state_handler\",\"ace/placeholder\",\"ace/config\",\"ace/theme/textmate\"],function(a,b,c){a(\"./lib/fixoldbrowsers\");var d=a(\"./lib/dom\"),e=a(\"./lib/event\"),f=a(\"./editor\").Editor,g=a(\"./edit_session\").EditSession,h=a(\"./undomanager\").UndoManager,i=a(\"./virtual_renderer\").VirtualRenderer,j=a(\"./multi_select\").MultiSelect;a(\"./worker/worker_client\"),a(\"./keyboard/hash_handler\"),a(\"./keyboard/state_handler\"),a(\"./placeholder\"),b.config=a(\"./config\"),b.edit=function(b){typeof b==\"string\"&&(b=document.getElementById(b));if(b.env&&b.env.editor instanceof f)return b.env.editor;var c=new g(d.getInnerText(b));c.setUndoManager(new h),b.innerHTML=\"\";var k=new f(new i(b,a(\"./theme/textmate\")));new j(k),k.setSession(c);var l={};return l.document=c,l.editor=k,k.resize(),e.addListener(window,\"resize\",function(){k.resize()}),b.env=l,k.env=l,k}}),ace.define(\"ace/lib/fixoldbrowsers\",[\"require\",\"exports\",\"module\",\"ace/lib/regexp\",\"ace/lib/es5-shim\"],function(a,b,c){a(\"./regexp\"),a(\"./es5-shim\")}),ace.define(\"ace/lib/regexp\",[\"require\",\"exports\",\"module\"],function(a,b,c){function g(a){return(a.global?\"g\":\"\")+(a.ignoreCase?\"i\":\"\")+(a.multiline?\"m\":\"\")+(a.extended?\"x\":\"\")+(a.sticky?\"y\":\"\")}function h(a,b,c){if(Array.prototype.indexOf)return a.indexOf(b,c);for(var d=c||0;d<a.length;d++)if(a[d]===b)return d;return-1}var d={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},e=d.exec.call(/()??/,\"\")[1]===undefined,f=function(){var a=/^/g;return d.test.call(a,\"\"),!a.lastIndex}();if(f&&e)return;RegExp.prototype.exec=function(a){var b=d.exec.apply(this,arguments),c,i;if(typeof a==\"string\"&&b){!e&&b.length>1&&h(b,\"\")>-1&&(i=RegExp(this.source,d.replace.call(g(this),\"g\",\"\")),d.replace.call(a.slice(b.index),i,function(){for(var a=1;a<arguments.length-2;a++)arguments[a]===undefined&&(b[a]=undefined)}));if(this._xregexp&&this._xregexp.captureNames)for(var j=1;j<b.length;j++)c=this._xregexp.captureNames[j-1],c&&(b[c]=b[j]);!f&&this.global&&!b[0].length&&this.lastIndex>b.index&&this.lastIndex--}return b},f||(RegExp.prototype.test=function(a){var b=d.exec.call(this,a);return b&&this.global&&!b[0].length&&this.lastIndex>b.index&&this.lastIndex--,!!b})}),ace.define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(a,b,c){function p(a){try{return Object.defineProperty(a,\"sentinel\",{}),\"sentinel\"in a}catch(b){}}Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!=\"function\")throw new TypeError;var d=g.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,h=c.apply(f,d.concat(g.call(arguments)));return h!==null&&Object(h)===h?h:f}return c.apply(b,d.concat(g.call(arguments)))};return e});var d=Function.prototype.call,e=Array.prototype,f=Object.prototype,g=e.slice,h=d.bind(f.toString),i=d.bind(f.hasOwnProperty),j,k,l,m,n;if(n=i(f,\"__defineGetter__\"))j=d.bind(f.__defineGetter__),k=d.bind(f.__defineSetter__),l=d.bind(f.__lookupGetter__),m=d.bind(f.__lookupSetter__);Array.isArray||(Array.isArray=function(b){return h(b)==\"[object Array]\"}),Array.prototype.forEach||(Array.prototype.forEach=function(b){var c=G(this),d=arguments[1],e=0,f=c.length>>>0;if(h(b)!=\"[object Function]\")throw new TypeError;while(e<f)e in c&&b.call(d,c[e],e,c),e++}),Array.prototype.map||(Array.prototype.map=function(b){var c=G(this),d=c.length>>>0,e=Array(d),f=arguments[1];if(h(b)!=\"[object Function]\")throw new TypeError;for(var g=0;g<d;g++)g in c&&(e[g]=b.call(f,c[g],g,c));return e}),Array.prototype.filter||(Array.prototype.filter=function(b){var c=G(this),d=c.length>>>0,e=[],f=arguments[1];if(h(b)!=\"[object Function]\")throw new TypeError;for(var g=0;g<d;g++)g in c&&b.call(f,c[g],g,c)&&e.push(c[g]);return e}),Array.prototype.every||(Array.prototype.every=function(b){var c=G(this),d=c.length>>>0,e=arguments[1];if(h(b)!=\"[object Function]\")throw new TypeError;for(var f=0;f<d;f++)if(f in c&&!b.call(e,c[f],f,c))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(b){var c=G(this),d=c.length>>>0,e=arguments[1];if(h(b)!=\"[object Function]\")throw new TypeError;for(var f=0;f<d;f++)if(f in c&&b.call(e,c[f],f,c))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(b){var c=G(this),d=c.length>>>0;if(h(b)!=\"[object Function]\")throw new TypeError;if(!d&&arguments.length==1)throw new TypeError;var e=0,f;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);for(;e<d;e++)e in c&&(f=b.call(void 0,f,c[e],e,c));return f}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(b){var c=G(this),d=c.length>>>0;if(h(b)!=\"[object Function]\")throw new TypeError;if(!d&&arguments.length==1)throw new TypeError;var e,f=d-1;if(arguments.length>=2)e=arguments[1];else do{if(f in c){e=c[f--];break}if(--f<0)throw new TypeError}while(!0);do f in this&&(e=b.call(void 0,e,c[f],f,c));while(f--);return e}),Array.prototype.indexOf||(Array.prototype.indexOf=function(b){var c=G(this),d=c.length>>>0;if(!d)return-1;var e=0;arguments.length>1&&(e=E(arguments[1])),e=e>=0?e:Math.max(0,d+e);for(;e<d;e++)if(e in c&&c[e]===b)return e;return-1}),Array.prototype.lastIndexOf||(Array.prototype.lastIndexOf=function(b){var c=G(this),d=c.length>>>0;if(!d)return-1;var e=d-1;arguments.length>1&&(e=Math.min(e,E(arguments[1]))),e=e>=0?e:d-Math.abs(e);for(;e>=0;e--)if(e in c&&b===c[e])return e;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(b){return b.__proto__||(b.constructor?b.constructor.prototype:f)});if(!Object.getOwnPropertyDescriptor){var o=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(b,c){if(typeof b!=\"object\"&&typeof b!=\"function\"||b===null)throw new TypeError(o+b);if(!i(b,c))return;var d,e,g;d={enumerable:!0,configurable:!0};if(n){var h=b.__proto__;b.__proto__=f;var e=l(b,c),g=m(b,c);b.__proto__=h;if(e||g)return e&&(d.get=e),g&&(d.set=g),d}return d.value=b[c],d}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(b){return Object.keys(b)}),Object.create||(Object.create=function(b,c){var d;if(b===null)d={__proto__:null};else{if(typeof b!=\"object\")throw new TypeError(\"typeof prototype[\"+typeof b+\"] != 'object'\");var e=function(){};e.prototype=b,d=new e,d.__proto__=b}return c!==void 0&&Object.defineProperties(d,c),d});if(Object.defineProperty){var q=p({}),r=typeof document==\"undefined\"||p(document.createElement(\"div\"));if(!q||!r)var s=Object.defineProperty}if(!Object.defineProperty||s){var t=\"Property description must be an object: \",u=\"Object.defineProperty called on non-object: \",v=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(b,c,d){if(typeof b!=\"object\"&&typeof b!=\"function\"||b===null)throw new TypeError(u+b);if(typeof d!=\"object\"&&typeof d!=\"function\"||d===null)throw new TypeError(t+d);if(s)try{return s.call(Object,b,c,d)}catch(e){}if(i(d,\"value\"))if(n&&(l(b,c)||m(b,c))){var g=b.__proto__;b.__proto__=f,delete b[c],b[c]=d.value,b.__proto__=g}else b[c]=d.value;else{if(!n)throw new TypeError(v);i(d,\"get\")&&j(b,c,d.get),i(d,\"set\")&&k(b,c,d.set)}return b}}Object.defineProperties||(Object.defineProperties=function(b,c){for(var d in c)i(c,d)&&Object.defineProperty(b,d,c[d]);return b}),Object.seal||(Object.seal=function(b){return b}),Object.freeze||(Object.freeze=function(b){return b});try{Object.freeze(function(){})}catch(w){Object.freeze=function(b){return function(c){return typeof c==\"function\"?c:b(c)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(b){return b}),Object.isSealed||(Object.isSealed=function(b){return!1}),Object.isFrozen||(Object.isFrozen=function(b){return!1}),Object.isExtensible||(Object.isExtensible=function(b){if(Object(b)===b)throw new TypeError;var c=\"\";while(i(b,c))c+=\"?\";b[c]=!0;var d=i(b,c);return delete b[c],d});if(!Object.keys){var x=!0,y=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],z=y.length;for(var A in{toString:null})x=!1;Object.keys=function H(a){if(typeof a!=\"object\"&&typeof a!=\"function\"||a===null)throw new TypeError(\"Object.keys called on a non-object\");var H=[];for(var b in a)i(a,b)&&H.push(b);if(x)for(var c=0,d=z;c<d;c++){var e=y[c];i(a,e)&&H.push(e)}return H}}if(!Date.prototype.toISOString||(new Date(-621987552e5)).toISOString().indexOf(\"-000001\")===-1)Date.prototype.toISOString=function(){var b,c,d,e;if(!isFinite(this))throw new RangeError;b=[this.getUTCMonth()+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()],e=this.getUTCFullYear(),e=(e<0?\"-\":e>9999?\"+\":\"\")+(\"00000\"+Math.abs(e)).slice(0<=e&&e<=9999?-4:-6),c=b.length;while(c--)d=b[c],d<10&&(b[c]=\"0\"+d);return e+\"-\"+b.slice(0,2).join(\"-\")+\"T\"+b.slice(2).join(\":\")+\".\"+(\"000\"+this.getUTCMilliseconds()).slice(-3)+\"Z\"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(b){if(typeof this.toISOString!=\"function\")throw new TypeError;return this.toISOString()}),Date.parse(\"+275760-09-13T00:00:00.000Z\")!==864e13&&(Date=function(a){var b=function e(b,c,d,f,g,h,i){var j=arguments.length;if(this instanceof a){var k=j==1&&String(b)===b?new a(e.parse(b)):j>=7?new a(b,c,d,f,g,h,i):j>=6?new a(b,c,d,f,g,h):j>=5?new a(b,c,d,f,g):j>=4?new a(b,c,d,f):j>=3?new a(b,c,d):j>=2?new a(b,c):j>=1?new a(b):new a;return k.constructor=e,k}return a.apply(this,arguments)},c=new RegExp(\"^(\\\\d{4}|[+-]\\\\d{6})(?:-(\\\\d{2})(?:-(\\\\d{2})(?:T(\\\\d{2}):(\\\\d{2})(?::(\\\\d{2})(?:\\\\.(\\\\d{3}))?)?(?:Z|(?:([-+])(\\\\d{2}):(\\\\d{2})))?)?)?)?$\");for(var d in a)b[d]=a[d];return b.now=a.now,b.UTC=a.UTC,b.prototype=a.prototype,b.prototype.constructor=b,b.parse=function(d){var e=c.exec(d);if(e){e.shift();for(var f=1;f<7;f++)e[f]=+(e[f]||(f<3?1:0)),f==1&&e[f]--;var g=+e.pop(),h=+e.pop(),i=e.pop(),j=0;if(i){if(h>23||g>59)return NaN;j=(h*60+g)*6e4*(i==\"+\"?-1:1)}var k=+e[0];return 0<=k&&k<=99?(e[0]=k+400,a.UTC.apply(this,e)+j-126227808e5):a.UTC.apply(this,e)+j}return a.parse.apply(this,arguments)},b}(Date));var B=\"\t\\n\u000b\\f\\r   ᠎             　\\u2028\\u2029﻿\";if(!String.prototype.trim||B.trim()){B=\"[\"+B+\"]\";var C=new RegExp(\"^\"+B+B+\"*\"),D=new RegExp(B+B+\"*$\");String.prototype.trim=function(){return String(this).replace(C,\"\").replace(D,\"\")}}var E=function(a){return a=+a,a!==a?a=0:a!==0&&a!==1/0&&a!==-Infinity&&(a=(a>0||-1)*Math.floor(Math.abs(a))),a},F=\"a\"[0]!=\"a\",G=function(a){if(a==null)throw new TypeError;return F&&typeof a==\"string\"&&a?a.split(\"\"):Object(a)}}),ace.define(\"ace/lib/dom\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=\"http://www.w3.org/1999/xhtml\";b.createElement=function(a,b){return document.createElementNS?document.createElementNS(b||d,a):document.createElement(a)},b.setText=function(a,b){a.innerText!==undefined&&(a.innerText=b),a.textContent!==undefined&&(a.textContent=b)},b.hasCssClass=function(a,b){var c=a.className.split(/\\s+/g);return c.indexOf(b)!==-1},b.addCssClass=function(a,c){b.hasCssClass(a,c)||(a.className+=\" \"+c)},b.removeCssClass=function(a,b){var c=a.className.split(/\\s+/g);for(;;){var d=c.indexOf(b);if(d==-1)break;c.splice(d,1)}a.className=c.join(\" \")},b.toggleCssClass=function(a,b){var c=a.className.split(/\\s+/g),d=!0;for(;;){var e=c.indexOf(b);if(e==-1)break;d=!1,c.splice(e,1)}return d&&c.push(b),a.className=c.join(\" \"),d},b.setCssClass=function(a,c,d){d?b.addCssClass(a,c):b.removeCssClass(a,c)},b.hasCssString=function(a,b){var c=0,d;b=b||document;if(b.createStyleSheet&&(d=b.styleSheets)){while(c<d.length)if(d[c++].owningElement.id===a)return!0}else if(d=b.getElementsByTagName(\"style\"))while(c<d.length)if(d[c++].id===a)return!0;return!1},b.importCssString=function(c,e,f){f=f||document;if(e&&b.hasCssString(e,f))return null;var g;if(f.createStyleSheet)g=f.createStyleSheet(),g.cssText=c,e&&(g.owningElement.id=e);else{g=f.createElementNS?f.createElementNS(d,\"style\"):f.createElement(\"style\"),g.appendChild(f.createTextNode(c)),e&&(g.id=e);var h=f.getElementsByTagName(\"head\")[0]||f.documentElement;h.appendChild(g)}},b.importCssStylsheet=function(a,c){if(c.createStyleSheet)c.createStyleSheet(a);else{var d=b.createElement(\"link\");d.rel=\"stylesheet\",d.href=a;var e=c.getElementsByTagName(\"head\")[0]||c.documentElement;e.appendChild(d)}},b.getInnerWidth=function(a){return parseInt(b.computedStyle(a,\"paddingLeft\"),10)+parseInt(b.computedStyle(a,\"paddingRight\"),10)+a.clientWidth},b.getInnerHeight=function(a){return parseInt(b.computedStyle(a,\"paddingTop\"),10)+parseInt(b.computedStyle(a,\"paddingBottom\"),10)+a.clientHeight},window.pageYOffset!==undefined?(b.getPageScrollTop=function(){return window.pageYOffset},b.getPageScrollLeft=function(){return window.pageXOffset}):(b.getPageScrollTop=function(){return document.body.scrollTop},b.getPageScrollLeft=function(){return document.body.scrollLeft}),window.getComputedStyle?b.computedStyle=function(a,b){return b?(window.getComputedStyle(a,\"\")||{})[b]||\"\":window.getComputedStyle(a,\"\")||{}}:b.computedStyle=function(a,b){return b?a.currentStyle[b]:a.currentStyle},b.scrollbarWidth=function(a){var c=b.createElement(\"p\");c.style.width=\"100%\",c.style.minWidth=\"0px\",c.style.height=\"200px\";var d=b.createElement(\"div\"),e=d.style;e.position=\"absolute\",e.left=\"-10000px\",e.overflow=\"hidden\",e.width=\"200px\",e.minWidth=\"0px\",e.height=\"150px\",d.appendChild(c);var f=a.body||a.documentElement;f.appendChild(d);var g=c.offsetWidth;e.overflow=\"scroll\";var h=c.offsetWidth;return g==h&&(h=d.clientWidth),f.removeChild(d),g-h},b.setInnerHtml=function(a,b){var c=a.cloneNode(!1);return c.innerHTML=b,a.parentNode.replaceChild(c,a),c},b.setInnerText=function(a,b){var c=a.ownerDocument;c.body&&\"textContent\"in c.body?a.textContent=b:a.innerText=b},b.getInnerText=function(a){var b=a.ownerDocument;return b.body&&\"textContent\"in b.body?a.textContent:a.innerText||a.textContent||\"\"},b.getParentWindow=function(a){return a.defaultView||a.parentWindow}}),ace.define(\"ace/lib/event\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\",\"ace/lib/dom\"],function(a,b,c){function g(a,b,c){var f=0;!e.isOpera||\"KeyboardEvent\"in window||!e.isMac?f=0|(b.ctrlKey?1:0)|(b.altKey?2:0)|(b.shiftKey?4:0)|(b.metaKey?8:0):f=0|(b.metaKey?1:0)|(b.altKey?2:0)|(b.shiftKey?4:0)|(b.ctrlKey?8:0);if(c in d.MODIFIER_KEYS){switch(d.MODIFIER_KEYS[c]){case\"Alt\":f=2;break;case\"Shift\":f=4;break;case\"Ctrl\":f=1;break;default:f=8}c=0}return f&8&&(c==91||c==93)&&(c=0),!!f||c in d.FUNCTION_KEYS||c in d.PRINTABLE_KEYS?a(b,f,c):!1}var d=a(\"./keys\"),e=a(\"./useragent\"),f=a(\"./dom\");b.addListener=function(a,b,c){if(a.addEventListener)return a.addEventListener(b,c,!1);if(a.attachEvent){var d=function(){c(window.event)};c._wrapper=d,a.attachEvent(\"on\"+b,d)}},b.removeListener=function(a,b,c){if(a.removeEventListener)return a.removeEventListener(b,c,!1);a.detachEvent&&a.detachEvent(\"on\"+b,c._wrapper||c)},b.stopEvent=function(a){return b.stopPropagation(a),b.preventDefault(a),!1},b.stopPropagation=function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},b.preventDefault=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},b.getButton=function(a){return a.type==\"dblclick\"?0:a.type==\"contextmenu\"||a.ctrlKey&&e.isMac?2:a.preventDefault?a.button:{1:0,2:2,4:1}[a.button]},document.documentElement.setCapture?b.capture=function(a,c,d){function f(g){c(g),e||(e=!0,d(g)),b.removeListener(a,\"mousemove\",c),b.removeListener(a,\"mouseup\",f),b.removeListener(a,\"losecapture\",f),a.releaseCapture()}var e=!1;b.addListener(a,\"mousemove\",c),b.addListener(a,\"mouseup\",f),b.addListener(a,\"losecapture\",f),a.setCapture()}:b.capture=function(a,b,c){function d(a){b&&b(a),c&&c(a),document.removeEventListener(\"mousemove\",b,!0),document.removeEventListener(\"mouseup\",d,!0),a.stopPropagation()}document.addEventListener(\"mousemove\",b,!0),document.addEventListener(\"mouseup\",d,!0)},b.addMouseWheelListener=function(a,c){var d=8,e=function(a){a.wheelDelta!==undefined?a.wheelDeltaX!==undefined?(a.wheelX=-a.wheelDeltaX/d,a.wheelY=-a.wheelDeltaY/d):(a.wheelX=0,a.wheelY=-a.wheelDelta/d):a.axis&&a.axis==a.HORIZONTAL_AXIS?(a.wheelX=(a.detail||0)*5,a.wheelY=0):(a.wheelX=0,a.wheelY=(a.detail||0)*5),c(a)};b.addListener(a,\"DOMMouseScroll\",e),b.addListener(a,\"mousewheel\",e)},b.addMultiMouseDownListener=function(a,c,d,f){var g=0,h,i,j,k={2:\"dblclick\",3:\"tripleclick\",4:\"quadclick\"};b.addListener(a,\"mousedown\",function(a){if(b.getButton(a)!=0)g=0;else{var e=Math.abs(a.clientX-h)>5||Math.abs(a.clientY-i)>5;if(!j||e)g=0;g+=1,j&&clearTimeout(j),j=setTimeout(function(){j=null},c[g-1]||600)}g==1&&(h=a.clientX,i=a.clientY),d[f](\"mousedown\",a);if(g>4)g=0;else if(g>1)return d[f](k[g],a)}),e.isOldIE&&b.addListener(a,\"dblclick\",function(a){g=2,j&&clearTimeout(j),j=setTimeout(function(){j=null},c[g-1]||600),d[f](\"mousedown\",a),d[f](k[g],a)})},b.addCommandKeyListener=function(a,c){var d=b.addListener;if(e.isOldGecko||e.isOpera&&!(\"KeyboardEvent\"in window)){var f=null;d(a,\"keydown\",function(a){f=a.keyCode}),d(a,\"keypress\",function(a){return g(c,a,f)})}else{var h=null;d(a,\"keydown\",function(a){return h=a.keyIdentifier||a.keyCode,g(c,a,a.keyCode)})}};if(window.postMessage&&!e.isOldIE){var h=1;b.nextTick=function(a,c){c=c||window;var d=\"zero-timeout-message-\"+h;b.addListener(c,\"message\",function e(f){f.data==d&&(b.stopPropagation(f),b.removeListener(c,\"message\",e),a())}),c.postMessage(d,\"*\")}}else b.nextTick=function(a,b){b=b||window,window.setTimeout(a,0)}}),ace.define(\"ace/lib/keys\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\"],function(a,b,c){var d=a(\"./oop\"),e=function(){var a={MODIFIER_KEYS:{16:\"Shift\",17:\"Ctrl\",18:\"Alt\",224:\"Meta\"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,meta:8,command:8},FUNCTION_KEYS:{8:\"Backspace\",9:\"Tab\",13:\"Return\",19:\"Pause\",27:\"Esc\",32:\"Space\",33:\"PageUp\",34:\"PageDown\",35:\"End\",36:\"Home\",37:\"Left\",38:\"Up\",39:\"Right\",40:\"Down\",44:\"Print\",45:\"Insert\",46:\"Delete\",96:\"Numpad0\",97:\"Numpad1\",98:\"Numpad2\",99:\"Numpad3\",100:\"Numpad4\",101:\"Numpad5\",102:\"Numpad6\",103:\"Numpad7\",104:\"Numpad8\",105:\"Numpad9\",112:\"F1\",113:\"F2\",114:\"F3\",115:\"F4\",116:\"F5\",117:\"F6\",118:\"F7\",119:\"F8\",120:\"F9\",121:\"F10\",122:\"F11\",123:\"F12\",144:\"Numlock\",145:\"Scrolllock\"},PRINTABLE_KEYS:{32:\" \",48:\"0\",49:\"1\",50:\"2\",51:\"3\",52:\"4\",53:\"5\",54:\"6\",55:\"7\",56:\"8\",57:\"9\",59:\";\",61:\"=\",65:\"a\",66:\"b\",67:\"c\",68:\"d\",69:\"e\",70:\"f\",71:\"g\",72:\"h\",73:\"i\",74:\"j\",75:\"k\",76:\"l\",77:\"m\",78:\"n\",79:\"o\",80:\"p\",81:\"q\",82:\"r\",83:\"s\",84:\"t\",85:\"u\",86:\"v\",87:\"w\",88:\"x\",89:\"y\",90:\"z\",107:\"+\",109:\"-\",110:\".\",188:\",\",190:\".\",191:\"/\",192:\"`\",219:\"[\",220:\"\\\\\",221:\"]\",222:\"'\"}};for(var b in a.FUNCTION_KEYS){var c=a.FUNCTION_KEYS[b].toUpperCase();a[c]=parseInt(b,10)}return d.mixin(a,a.MODIFIER_KEYS),d.mixin(a,a.PRINTABLE_KEYS),d.mixin(a,a.FUNCTION_KEYS),a}();d.mixin(b,e),b.keyCodeToString=function(a){return(e[a]||String.fromCharCode(a)).toLowerCase()}}),ace.define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(a,b,c){b.inherits=function(){var a=function(){};return function(b,c){a.prototype=c.prototype,b.super_=c.prototype,b.prototype=new a,b.prototype.constructor=b}}(),b.mixin=function(a,b){for(var c in b)a[c]=b[c]},b.implement=function(a,c){b.mixin(a,c)}}),ace.define(\"ace/lib/useragent\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=(navigator.platform.match(/mac|win|linux/i)||[\"other\"])[0].toLowerCase(),e=navigator.userAgent;b.isWin=d==\"win\",b.isMac=d==\"mac\",b.isLinux=d==\"linux\",b.isIE=navigator.appName==\"Microsoft Internet Explorer\"&&parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\\.0-9]+)/)[1]),b.isOldIE=b.isIE&&b.isIE<9,b.isGecko=b.isMozilla=window.controllers&&window.navigator.product===\"Gecko\",b.isOldGecko=b.isGecko&&parseInt((navigator.userAgent.match(/rv\\:(\\d+)/)||[])[1],10)<4,b.isOpera=window.opera&&Object.prototype.toString.call(window.opera)==\"[object Opera]\",b.isWebKit=parseFloat(e.split(\"WebKit/\")[1])||undefined,b.isChrome=parseFloat(e.split(\" Chrome/\")[1])||undefined,b.isAIR=e.indexOf(\"AdobeAIR\")>=0,b.isIPad=e.indexOf(\"iPad\")>=0,b.isTouchPad=e.indexOf(\"TouchPad\")>=0,b.OS={LINUX:\"LINUX\",MAC:\"MAC\",WINDOWS:\"WINDOWS\"},b.getOS=function(){return b.isMac?b.OS.MAC:b.isLinux?b.OS.LINUX:b.OS.WINDOWS}}),ace.define(\"ace/editor\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/keyboard/textinput\",\"ace/mouse/mouse_handler\",\"ace/mouse/fold_handler\",\"ace/keyboard/keybinding\",\"ace/edit_session\",\"ace/search\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/commands/command_manager\",\"ace/commands/default_commands\"],function(a,b,c){a(\"./lib/fixoldbrowsers\");var d=a(\"./lib/oop\"),e=a(\"./lib/lang\"),f=a(\"./lib/useragent\"),g=a(\"./keyboard/textinput\").TextInput,h=a(\"./mouse/mouse_handler\").MouseHandler,i=a(\"./mouse/fold_handler\").FoldHandler,j=a(\"./keyboard/keybinding\").KeyBinding,k=a(\"./edit_session\").EditSession,l=a(\"./search\").Search,m=a(\"./range\").Range,n=a(\"./lib/event_emitter\").EventEmitter,o=a(\"./commands/command_manager\").CommandManager,p=a(\"./commands/default_commands\").commands,q=function(a,b){var c=a.getContainerElement();this.container=c,this.renderer=a,this.commands=new o(f.isMac?\"mac\":\"win\",p),this.textInput=new g(a.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.keyBinding=new j(this),f.isIPad||(this.$mouseHandler=new h(this),new i(this)),this.$blockScrolling=0,this.$search=(new l).set({wrap:!0}),this.setSession(b||new k(\"\"))};(function(){d.implement(this,n),this.setKeyboardHandler=function(a){this.keyBinding.setKeyboardHandler(a)},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(a){if(this.session==a)return;if(this.session){var b=this.session;this.session.removeEventListener(\"change\",this.$onDocumentChange),this.session.removeEventListener(\"changeMode\",this.$onChangeMode),this.session.removeEventListener(\"tokenizerUpdate\",this.$onTokenizerUpdate),this.session.removeEventListener(\"changeTabSize\",this.$onChangeTabSize),this.session.removeEventListener(\"changeWrapLimit\",this.$onChangeWrapLimit),this.session.removeEventListener(\"changeWrapMode\",this.$onChangeWrapMode),this.session.removeEventListener(\"onChangeFold\",this.$onChangeFold),this.session.removeEventListener(\"changeFrontMarker\",this.$onChangeFrontMarker),this.session.removeEventListener(\"changeBackMarker\",this.$onChangeBackMarker),this.session.removeEventListener(\"changeBreakpoint\",this.$onChangeBreakpoint),this.session.removeEventListener(\"changeAnnotation\",this.$onChangeAnnotation),this.session.removeEventListener(\"changeOverwrite\",this.$onCursorChange),this.session.removeEventListener(\"changeScrollTop\",this.$onScrollTopChange),this.session.removeEventListener(\"changeLeftTop\",this.$onScrollLeftChange);var c=this.session.getSelection();c.removeEventListener(\"changeCursor\",this.$onCursorChange),c.removeEventListener(\"changeSelection\",this.$onSelectionChange)}this.session=a,this.$onDocumentChange=this.onDocumentChange.bind(this),a.addEventListener(\"change\",this.$onDocumentChange),this.renderer.setSession(a),this.$onChangeMode=this.onChangeMode.bind(this),a.addEventListener(\"changeMode\",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),a.addEventListener(\"tokenizerUpdate\",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),a.addEventListener(\"changeTabSize\",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),a.addEventListener(\"changeWrapLimit\",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),a.addEventListener(\"changeWrapMode\",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),a.addEventListener(\"changeFold\",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.addEventListener(\"changeFrontMarker\",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.addEventListener(\"changeBackMarker\",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.addEventListener(\"changeBreakpoint\",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.addEventListener(\"changeAnnotation\",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.addEventListener(\"changeOverwrite\",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.addEventListener(\"changeScrollTop\",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.addEventListener(\"changeScrollLeft\",this.$onScrollLeftChange),this.selection=a.getSelection(),this.selection.addEventListener(\"changeCursor\",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.addEventListener(\"changeSelection\",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull(),this._emit(\"changeSession\",{session:a,oldSession:b})},this.getSession=function(){return this.session},this.setValue=function(a,b){return this.session.doc.setValue(a),b?b==1?this.navigateFileEnd():b==-1&&this.navigateFileStart():this.selectAll(),a},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(a){this.renderer.onResize(a)},this.setTheme=function(a){this.renderer.setTheme(a)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(a){this.renderer.setStyle(a)},this.unsetStyle=function(a){this.renderer.unsetStyle(a)},this.setFontSize=function(a){this.container.style.fontSize=a,this.renderer.updateFontSize()},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var a=this;this.$highlightPending=!0,setTimeout(function(){a.$highlightPending=!1;var b=a.session.findMatchingBracket(a.getCursorPosition());if(b){var c=new m(b.row,b.column,b.row,b.column+1);a.session.$bracketHighlight=a.session.addMarker(c,\"ace_bracket\",\"text\")}},10)},this.focus=function(){var a=this;setTimeout(function(){a.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(){if(this.$isFocused)return;this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit(\"focus\")},this.onBlur=function(){if(!this.$isFocused)return;this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit(\"blur\")},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(a){var b=a.data,c=b.range,d;c.start.row==c.end.row&&b.action!=\"insertLines\"&&b.action!=\"removeLines\"?d=c.end.row:d=Infinity,this.renderer.updateLines(c.start.row,d),this._emit(\"change\",a),this.$cursorChange()},this.onTokenizerUpdate=function(a){var b=a.data;this.renderer.updateLines(b.first,b.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||this.renderer.scrollCursorIntoView(),this.$highlightBrackets(),this.$updateHighlightActiveLine(),this._emit(\"changeSelection\")},this.$updateHighlightActiveLine=function(){var a=this.getSession();a.$highlightLineMarker&&a.removeMarker(a.$highlightLineMarker),a.$highlightLineMarker=null;if(this.$highlightActiveLine){var b=this.getCursorPosition(),c=this.session.getFoldLine(b.row);if(this.getSelectionStyle()!=\"line\"||!this.selection.isMultiLine()){var d;c?d=new m(c.start.row,0,c.end.row+1,0):d=new m(b.row,0,b.row+1,0),a.$highlightLineMarker=a.addMarker(d,\"ace_active_line\",\"background\")}}},this.onSelectionChange=function(a){var b=this.session;b.$selectionMarker&&b.removeMarker(b.$selectionMarker),b.$selectionMarker=null;if(!this.selection.isEmpty()){var c=this.selection.getRange(),d=this.getSelectionStyle();b.$selectionMarker=b.addMarker(c,\"ace_selection\",d)}else this.$updateHighlightActiveLine();var e=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(e),this._emit(\"changeSelection\")},this.$getSelectionHighLightRegexp=function(){var a=this.session,b=this.getSelectionRange();if(b.isEmpty()||b.isMultiLine())return;var c=b.start.column-1,d=b.end.column+1,e=a.getLine(b.start.row),f=e.length,g=e.substring(Math.max(c,0),Math.min(d,f));if(c>=0&&/^[\\w\\d]/.test(g)||d<=f&&/[\\w\\d]$/.test(g))return;g=e.substring(b.start.column,b.end.column);if(!/^[\\w\\d]+$/.test(g))return;var h=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:g});return h},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(){this.renderer.updateText()},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getCopyText=function(){var a=\"\";return this.selection.isEmpty()||(a=this.session.getTextRange(this.getSelectionRange())),this._emit(\"copy\",a),a},this.onCopy=function(){this.commands.exec(\"copy\",this)},this.onCut=function(){this.commands.exec(\"cut\",this)},this.onPaste=function(a){if(this.$readOnly)return;this._emit(\"paste\",a),this.insert(a)},this.insert=function(a){var b=this.session,c=b.getMode(),d=this.getCursorPosition();if(this.getBehavioursEnabled()){var e=c.transformAction(b.getState(d.row),\"insertion\",this,b,a);e&&(a=e.text)}a=a.replace(\"\t\",this.session.getTabString());if(!this.selection.isEmpty())d=this.session.remove(this.getSelectionRange()),this.clearSelection();else if(this.session.getOverwrite()){var f=new m.fromPoints(d,d);f.end.column+=a.length,this.session.remove(f)}this.clearSelection();var g=d.column,h=b.getState(d.row),i=c.checkOutdent(h,b.getLine(d.row),a),j=b.getLine(d.row),k=c.getNextLineIndent(h,j.slice(0,d.column),b.getTabString()),l=b.insert(d,a);e&&e.selection&&(e.selection.length==2?this.selection.setSelectionRange(new m(d.row,g+e.selection[0],d.row,g+e.selection[1])):this.selection.setSelectionRange(new m(d.row+e.selection[0],e.selection[1],d.row+e.selection[2],e.selection[3])));var h=b.getState(d.row);if(b.getDocument().isNewLine(a)){this.moveCursorTo(d.row+1,0);var n=b.getTabSize(),o=Number.MAX_VALUE;for(var p=d.row+1;p<=l.row;++p){var q=0;j=b.getLine(p);for(var r=0;r<j.length;++r)if(j.charAt(r)==\"\t\")q+=n;else{if(j.charAt(r)!=\" \")break;q+=1}/[^\\s]/.test(j)&&(o=Math.min(q,o))}for(var p=d.row+1;p<=l.row;++p){var s=o;j=b.getLine(p);for(var r=0;r<j.length&&s>0;++r)j.charAt(r)==\"\t\"?s-=n:j.charAt(r)==\" \"&&(s-=1);b.remove(new m(p,0,p,r))}b.indentRows(d.row+1,l.row,k)}i&&c.autoOutdent(h,b,d.row)},this.onTextInput=function(a){this.keyBinding.onTextInput(a)},this.onCommandKey=function(a,b,c){this.keyBinding.onCommandKey(a,b,c)},this.setOverwrite=function(a){this.session.setOverwrite(a)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(a){this.$mouseHandler.setScrollSpeed(a)},this.getScrollSpeed=function(){return this.$mouseHandler.getScrollSpeed()},this.setDragDelay=function(a){this.$mouseHandler.setDragDelay(a)},this.getDragDelay=function(){return this.$mouseHandler.getDragDelay()},this.$selectionStyle=\"line\",this.setSelectionStyle=function(a){if(this.$selectionStyle==a)return;this.$selectionStyle=a,this.onSelectionChange(),this._emit(\"changeSelectionStyle\",{data:a})},this.getSelectionStyle=function(){return this.$selectionStyle},this.$highlightActiveLine=!0,this.setHighlightActiveLine=function(a){if(this.$highlightActiveLine==a)return;this.$highlightActiveLine=a,this.$updateHighlightActiveLine()},this.getHighlightActiveLine=function(){return this.$highlightActiveLine},this.$highlightGutterLine=!0,this.setHighlightGutterLine=function(a){if(this.$highlightGutterLine==a)return;this.renderer.setHighlightGutterLine(a),this.$highlightGutterLine=a},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$highlightSelectedWord=!0,this.setHighlightSelectedWord=function(a){if(this.$highlightSelectedWord==a)return;this.$highlightSelectedWord=a,this.$onSelectionChange()},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(a){this.renderer.setAnimatedScroll(a)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(a){this.renderer.setShowInvisibles(a)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(a){this.renderer.setDisplayIndentGuides(a)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(a){this.renderer.setShowPrintMargin(a)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(a){this.renderer.setPrintMarginColumn(a)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.$readOnly=!1,this.setReadOnly=function(a){this.$readOnly=a},this.getReadOnly=function(){return this.$readOnly},this.$modeBehaviours=!0,this.setBehavioursEnabled=function(a){this.$modeBehaviours=a},this.getBehavioursEnabled=function(){return this.$modeBehaviours},this.setShowFoldWidgets=function(a){var b=this.renderer.$gutterLayer;if(b.getShowFoldWidgets()==a)return;this.renderer.$gutterLayer.setShowFoldWidgets(a),this.$showFoldWidgets=a,this.renderer.updateFull()},this.getShowFoldWidgets=function(){return this.renderer.$gutterLayer.getShowFoldWidgets()},this.setFadeFoldWidgets=function(a){this.renderer.setFadeFoldWidgets(a)},this.getFadeFoldWidgets=function(){return this.renderer.getFadeFoldWidgets()},this.remove=function(a){this.selection.isEmpty()&&(a==\"left\"?this.selection.selectLeft():this.selection.selectRight());var b=this.getSelectionRange();if(this.getBehavioursEnabled()){var c=this.session,d=c.getState(b.start.row),e=c.getMode().transformAction(d,\"deletion\",this,c,b);e&&(b=e)}this.session.remove(b),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var a=this.getSelectionRange();a.start.column==a.end.column&&a.start.row==a.end.row&&(a.end.column=0,a.end.row++),this.session.remove(a),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var a=this.getCursorPosition();this.insert(\"\\n\"),this.moveCursorToPosition(a)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var a=this.getCursorPosition(),b=a.column;if(b===0)return;var c=this.session.getLine(a.row),d,e;b<c.length?(d=c.charAt(b)+c.charAt(b-1),e=new m(a.row,b-1,a.row,b+1)):(d=c.charAt(b-1)+c.charAt(b-2),e=new m(a.row,b-2,a.row,b)),this.session.replace(e,d)},this.toLowerCase=function(){var a=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var b=this.getSelectionRange(),c=this.session.getTextRange(b);this.session.replace(b,c.toLowerCase()),this.selection.setSelectionRange(a)},this.toUpperCase=function(){var a=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var b=this.getSelectionRange(),c=this.session.getTextRange(b);this.session.replace(b,c.toUpperCase()),this.selection.setSelectionRange(a)},this.indent=function(){var a=this.session,b=this.getSelectionRange();if(!(b.start.row<b.end.row||b.start.column<b.end.column)){var d;if(this.session.getUseSoftTabs()){var f=a.getTabSize(),g=this.getCursorPosition(),h=a.documentToScreenColumn(g.row,g.column),i=f-h%f;d=e.stringRepeat(\" \",i)}else d=\"\t\";return this.insert(d)}var c=this.$getSelectedRows();a.indentRows(c.first,c.last,\"\t\")},this.blockOutdent=function(){var a=this.session.getSelection();this.session.outdentRows(a.getRange())},this.toggleCommentLines=function(){var a=this.session.getState(this.getCursorPosition().row),b=this.$getSelectedRows();this.session.getMode().toggleCommentLines(a,this.session,b.first,b.last)},this.removeLines=function(){var a=this.$getSelectedRows(),b;a.first===0||a.last+1<this.session.getLength()?b=new m(a.first,0,a.last+1,0):b=new m(a.first-1,this.session.getLine(a.first-1).length,a.last,this.session.getLine(a.last).length),this.session.remove(b),this.clearSelection()},this.duplicateSelection=function(){var a=this.selection,b=this.session,c=a.getRange();if(c.isEmpty()){var d=c.start.row;b.duplicateLines(d,d)}else{var e=a.isBackwards(),f=a.isBackwards()?c.start:c.end,g=b.insert(f,b.getTextRange(c),!1);c.start=f,c.end=g,a.setSelectionRange(c,e)}},this.moveLinesDown=function(){this.$moveLines(function(a,b){return this.session.moveLinesDown(a,b)})},this.moveLinesUp=function(){this.$moveLines(function(a,b){return this.session.moveLinesUp(a,b)})},this.moveText=function(a,b){return this.$readOnly?null:this.session.moveText(a,b)},this.copyLinesUp=function(){this.$moveLines(function(a,b){return this.session.duplicateLines(a,b),0})},this.copyLinesDown=function(){this.$moveLines(function(a,b){return this.session.duplicateLines(a,b)})},this.$moveLines=function(a){var b=this.$getSelectedRows(),c=this.selection;if(!c.isMultiLine())var d=c.getRange(),e=c.isBackwards();var f=a.call(this,b.first,b.last);d?(d.start.row+=f,d.end.row+=f,c.setSelectionRange(d,e)):(c.setSelectionAnchor(b.last+f+1,0),c.$moveSelection(function(){c.moveCursorTo(b.first+f,0)}))},this.$getSelectedRows=function(){var a=this.getSelectionRange().collapseRows();return{first:a.start.row,last:a.end.row}},this.onCompositionStart=function(a){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(a){this.renderer.setCompositionText(a)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(a){return a>=this.getFirstVisibleRow()&&a<=this.getLastVisibleRow()},this.isRowFullyVisible=function(a){return a>=this.renderer.getFirstFullyVisibleRow()&&a<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(a,b){var c=this.renderer,d=this.renderer.layerConfig,e=a*Math.floor(d.height/d.lineHeight);this.$blockScrolling++,b==1?this.selection.$moveSelection(function(){this.moveCursorBy(e,0)}):b==0&&(this.selection.moveCursorBy(e,0),this.selection.clearSelection()),this.$blockScrolling--;var f=c.scrollTop;c.scrollBy(0,e*d.lineHeight),b!=null&&c.scrollCursorIntoView(null,.5),c.animateScrolling(f)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(a){this.renderer.scrollToRow(a)},this.scrollToLine=function(a,b,c,d){this.renderer.scrollToLine(a,b,c,d)},this.centerSelection=function(){var a=this.getSelectionRange(),b={row:Math.floor(a.start.row+(a.end.row-a.start.row)/2),column:Math.floor(a.start.column+(a.end.column-a.start.column)/2)};this.renderer.alignCursor(b,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(a,b){this.selection.moveCursorTo(a,b)},this.moveCursorToPosition=function(a){this.selection.moveCursorToPosition(a)},this.jumpToMatching=function(a){var b=this.getCursorPosition(),c=this.session.getBracketRange(b);if(!c){c=this.find({needle:/[{}()\\[\\]]/g,preventScroll:!0,start:{row:b.row,column:b.column-1}});if(!c)return;var d=c.start;d.row==b.row&&Math.abs(d.column-b.column)<2&&(c=this.session.getBracketRange(d))}d=c&&c.cursor||d,d&&(a?c&&c.isEqual(this.getSelectionRange())?this.clearSelection():this.selection.selectTo(d.row,d.column):(this.clearSelection(),this.moveCursorTo(d.row,d.column)))},this.gotoLine=function(a,b,c){this.selection.clearSelection(),this.session.unfold({row:a-1,column:b||0}),this.$blockScrolling+=1,this.moveCursorTo(a-1,b||0),this.$blockScrolling-=1,this.isRowFullyVisible(a-1)||this.scrollToLine(a-1,!0,c)},this.navigateTo=function(a,b){this.clearSelection(),this.moveCursorTo(a,b)},this.navigateUp=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(-a,0)},this.navigateDown=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(a,0)},this.navigateLeft=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().start;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().end;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){var a=this.renderer.scrollTop;this.selection.moveCursorFileEnd(),this.clearSelection(),this.renderer.animateScrolling(a)},this.navigateFileStart=function(){var a=this.renderer.scrollTop;this.selection.moveCursorFileStart(),this.clearSelection(),this.renderer.animateScrolling(a)},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(a,b){b&&this.$search.set(b);var c=this.$search.find(this.session),d=0;return c?(this.$tryReplace(c,a)&&(d=1),c!==null&&(this.selection.setSelectionRange(c),this.renderer.scrollSelectionIntoView(c.start,c.end)),d):d},this.replaceAll=function(a,b){b&&this.$search.set(b);var c=this.$search.findAll(this.session),d=0;if(!c.length)return d;this.$blockScrolling+=1;var e=this.getSelectionRange();this.clearSelection(),this.selection.moveCursorTo(0,0);for(var f=c.length-1;f>=0;--f)this.$tryReplace(c[f],a)&&d++;return this.selection.setSelectionRange(e),this.$blockScrolling-=1,d},this.$tryReplace=function(a,b){var c=this.session.getTextRange(a);return b=this.$search.replace(c,b),b!==null?(a.end=this.session.replace(a,b),a):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(a,b,c){b||(b={}),typeof a==\"string\"||a instanceof RegExp?b.needle=a:typeof a==\"object\"&&d.mixin(b,a);var e=this.selection.getRange();b.needle==null&&(a=this.session.getTextRange(e)||this.$search.$options.needle,a||(e=this.session.getWordRange(e.start.row,e.start.column),a=this.session.getTextRange(e)),this.$search.set({needle:a})),this.$search.set(b),b.start||this.$search.set({start:e});var f=this.$search.find(this.session);if(b.preventScroll)return f;if(f)return this.revealRange(f,c),f;b.backwards?e.start=e.end:e.end=e.start,this.selection.setRange(e)},this.findNext=function(a,b){this.find({skipCurrent:!0,backwards:!1},a,b)},this.findPrevious=function(a,b){this.find(a,{skipCurrent:!0,backwards:!0},b)},this.revealRange=function(a,b){this.$blockScrolling+=1,this.session.unfold(a),this.selection.setSelectionRange(a),this.$blockScrolling-=1;var c=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(a.start,a.end,.5),b!=0&&this.renderer.animateScrolling(c)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy()}}).call(q.prototype),b.Editor=q}),ace.define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(a,b,c){b.stringReverse=function(a){return a.split(\"\").reverse().join(\"\")},b.stringRepeat=function(a,b){return(new Array(b+1)).join(a)};var d=/^\\s\\s*/,e=/\\s\\s*$/;b.stringTrimLeft=function(a){return a.replace(d,\"\")},b.stringTrimRight=function(a){return a.replace(e,\"\")},b.copyObject=function(a){var b={};for(var c in a)b[c]=a[c];return b},b.copyArray=function(a){var b=[];for(var c=0,d=a.length;c<d;c++)a[c]&&typeof a[c]==\"object\"?b[c]=this.copyObject(a[c]):b[c]=a[c];return b},b.deepCopy=function(a){if(typeof a!=\"object\")return a;var b=a.constructor();for(var c in a)typeof a[c]==\"object\"?b[c]=this.deepCopy(a[c]):b[c]=a[c];return b},b.arrayToMap=function(a){var b={};for(var c=0;c<a.length;c++)b[a[c]]=1;return b},b.createMap=function(a){var b=Object.create(null);for(var c in a)b[c]=a[c];return b},b.arrayRemove=function(a,b){for(var c=0;c<=a.length;c++)b===a[c]&&a.splice(c,1)},b.escapeRegExp=function(a){return a.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},b.getMatchOffsets=function(a,b){var c=[];return a.replace(b,function(a){c.push({offset:arguments[arguments.length-2],length:a.length})}),c},b.deferredCall=function(a){var b=null,c=function(){b=null,a()},d=function(a){return d.cancel(),b=setTimeout(c,a||0),d};return d.schedule=d,d.call=function(){return this.cancel(),a(),d},d.cancel=function(){return clearTimeout(b),b=null,d},d}}),ace.define(\"ace/keyboard/textinput\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/lib/dom\"],function(a,b,c){var d=a(\"../lib/event\"),e=a(\"../lib/useragent\"),f=a(\"../lib/dom\"),g=function(a,b){function l(a){try{a?(c.value=g,c.selectionStart=0,c.selectionEnd=1):c.select()}catch(b){}}function m(a){if(!i){var d=a||c.value;d&&(d.length>1&&(d.charAt(0)==g?d=d.substr(1):d.charAt(d.length-1)==g&&(d=d.slice(0,-1))),d&&d!=g&&(j?b.onPaste(d):b.onTextInput(d)))}i=!1,j=!1,l(!0)}function v(){return document.activeElement===c}function w(){setTimeout(function(){k&&(c.style.cssText=k,k=\"\"),m(),b.renderer.$keepTextAreaAtCursor==null&&(b.renderer.$keepTextAreaAtCursor=!0,b.renderer.$moveTextAreaToCursor())},0)}var c=f.createElement(\"textarea\");e.isTouchPad&&c.setAttribute(\"x-palm-disable-auto-cap\",!0),c.setAttribute(\"wrap\",\"off\"),c.style.top=\"-2em\",a.insertBefore(c,a.firstChild);var g=e.isIE?\"\u0001\":\"\u0001\";m();var h=!1,i=!1,j=!1,k=\"\",n=function(a){h||m(a.data),setTimeout(function(){h||l(!0)},0)},o=function(a){setTimeout(function(){h||c.value!=\"\"&&m()},0)},p=function(a){h=!0,b.onCompositionStart(),setTimeout(q,0)},q=function(){if(!h)return;b.onCompositionUpdate(c.value)},r=function(a){h=!1,b.onCompositionEnd()},s=function(a){i=!0;var d=b.getCopyText();d?c.value=d:a.preventDefault(),l(),setTimeout(function(){m()},0)},t=function(a){i=!0;var d=b.getCopyText();d?(c.value=d,b.onCut()):a.preventDefault(),l(),setTimeout(function(){m()},0)};d.addCommandKeyListener(c,b.onCommandKey.bind(b)),d.addListener(c,\"input\",n);if(e.isOldIE){var u={13:1,27:1};d.addListener(c,\"keyup\",function(a){h&&(!c.value||u[a.keyCode])&&setTimeout(r,0);if((c.value.charCodeAt(0)|0)<129)return;h?q():p()}),d.addListener(c,\"propertychange\",function(){c.value!=g&&setTimeout(m,0)})}d.addListener(c,\"paste\",function(a){j=!0,a.clipboardData&&a.clipboardData.getData?(m(a.clipboardData.getData(\"text/plain\")),a.preventDefault()):o()}),\"onbeforecopy\"in c&&typeof clipboardData!=\"undefined\"?(d.addListener(c,\"beforecopy\",function(a){if(k)return;var c=b.getCopyText();c?clipboardData.setData(\"Text\",c):a.preventDefault()}),d.addListener(a,\"keydown\",function(a){if(a.ctrlKey&&a.keyCode==88){var c=b.getCopyText();c&&(clipboardData.setData(\"Text\",c),b.onCut()),d.preventDefault(a)}}),d.addListener(c,\"cut\",t)):!e.isOpera||\"KeyboardEvent\"in window?(d.addListener(c,\"copy\",s),d.addListener(c,\"cut\",t)):d.addListener(a,\"keydown\",function(a){if(e.isMac&&!a.metaKey||!a.ctrlKey)return;if(a.keyCode==88||a.keyCode==67){var d=b.getCopyText();d&&(c.value=d,c.select(),a.keyCode==88&&b.onCut())}}),d.addListener(c,\"compositionstart\",p),e.isGecko&&d.addListener(c,\"text\",q),e.isWebKit&&d.addListener(c,\"keyup\",q),d.addListener(c,\"compositionend\",r),d.addListener(c,\"blur\",function(){b.onBlur()}),d.addListener(c,\"focus\",function(){b.onFocus(),l()}),this.focus=function(){l(),c.focus()},this.blur=function(){c.blur()},this.isFocused=v,this.getElement=function(){return c},this.onContextMenu=function(a){k||(k=c.style.cssText),c.style.cssText=\"position:fixed; z-index:100000;\"+(e.isIE?\"background:rgba(0, 0, 0, 0.03); opacity:0.1;\":\"\")+\"left:\"+(a.clientX-2)+\"px; top:\"+(a.clientY-2)+\"px;\",b.selection.isEmpty()?c.value=\"\":l(!0);if(a.type!=\"mousedown\")return;b.renderer.$keepTextAreaAtCursor&&(b.renderer.$keepTextAreaAtCursor=null),e.isWin&&(e.isGecko||e.isIE)&&d.capture(b.container,function(a){c.style.left=a.clientX-2+\"px\",c.style.top=a.clientY-2+\"px\"},w)},this.onContextMenuClose=w,e.isGecko||d.addListener(c,\"contextmenu\",function(a){b.textInput.onContextMenu(a),w()})};b.TextInput=g}),ace.define(\"ace/mouse/mouse_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/mouse/default_handlers\",\"ace/mouse/default_gutter_handler\",\"ace/mouse/mouse_event\",\"ace/mouse/dragdrop\"],function(a,b,c){var d=a(\"../lib/event\"),e=a(\"../lib/useragent\"),f=a(\"./default_handlers\").DefaultHandlers,g=a(\"./default_gutter_handler\").GutterHandler,h=a(\"./mouse_event\").MouseEvent,i=a(\"./dragdrop\").DragdropHandler,j=function(a){this.editor=a,new f(this),new g(this),new i(this),d.addListener(a.container,\"mousedown\",function(b){return a.focus(),d.preventDefault(b)});var b=a.renderer.getMouseEventTarget();d.addListener(b,\"click\",this.onMouseEvent.bind(this,\"click\")),d.addListener(b,\"mousemove\",this.onMouseMove.bind(this,\"mousemove\")),d.addMultiMouseDownListener(b,[300,300,250],this,\"onMouseEvent\"),d.addMouseWheelListener(a.container,this.onMouseWheel.bind(this,\"mousewheel\"));var c=a.renderer.$gutter;d.addListener(c,\"mousedown\",this.onMouseEvent.bind(this,\"guttermousedown\")),d.addListener(c,\"click\",this.onMouseEvent.bind(this,\"gutterclick\")),d.addListener(c,\"dblclick\",this.onMouseEvent.bind(this,\"gutterdblclick\")),d.addListener(c,\"mousemove\",this.onMouseEvent.bind(this,\"guttermousemove\"))};(function(){this.$scrollSpeed=1,this.setScrollSpeed=function(a){this.$scrollSpeed=a},this.getScrollSpeed=function(){return this.$scrollSpeed},this.onMouseEvent=function(a,b){this.editor._emit(a,new h(b,this.editor))},this.$dragDelay=250,this.setDragDelay=function(a){this.$dragDelay=a},this.getDragDelay=function(){return this.$dragDelay},this.onMouseMove=function(a,b){var c=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!c||!c.length)return;this.editor._emit(a,new h(b,this.editor))},this.onMouseWheel=function(a,b){var c=new h(b,this.editor);c.speed=this.$scrollSpeed*2,c.wheelX=b.wheelX,c.wheelY=b.wheelY,this.editor._emit(a,c)},this.setState=function(a){this.state=a},this.captureMouse=function(a,b){b&&this.setState(b),this.x=a.x,this.y=a.y;var c=this.editor.renderer;c.$keepTextAreaAtCursor&&(c.$keepTextAreaAtCursor=null);var f=this,g=function(a){f.x=a.clientX,f.y=a.clientY},h=function(a){clearInterval(j),f[f.state+\"End\"]&&f[f.state+\"End\"](a),f.$clickSelection=null,c.$keepTextAreaAtCursor==null&&(c.$keepTextAreaAtCursor=!0,c.$moveTextAreaToCursor())},i=function(){f[f.state]&&f[f.state]()};if(e.isOldIE&&a.domEvent.type==\"dblclick\"){setTimeout(function(){i(),h(a.domEvent)});return}d.capture(this.editor.container,g,h);var j=setInterval(i,20)}}).call(j.prototype),b.MouseHandler=j}),ace.define(\"ace/mouse/default_handlers\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/useragent\"],function(a,b,c){function g(a){a.$clickSelection=null;var b=a.editor;b.setDefaultHandler(\"mousedown\",this.onMouseDown.bind(a)),b.setDefaultHandler(\"dblclick\",this.onDoubleClick.bind(a)),b.setDefaultHandler(\"tripleclick\",this.onTripleClick.bind(a)),b.setDefaultHandler(\"quadclick\",this.onQuadClick.bind(a)),b.setDefaultHandler(\"mousewheel\",this.onScroll.bind(a));var c=[\"select\",\"startSelect\",\"drag\",\"dragEnd\",\"dragWait\",\"dragWaitEnd\",\"startDrag\",\"focusWait\"];c.forEach(function(b){a[b]=this[b]},this),a.selectByLines=this.extendSelectionBy.bind(a,\"getLineRange\"),a.selectByWords=this.extendSelectionBy.bind(a,\"getWordRange\"),a.$focusWaitTimout=250}function h(a,b,c,d){return Math.sqrt(Math.pow(c-a,2)+Math.pow(d-b,2))}function i(a,b){if(a.start.row==a.end.row)var c=2*b.column-a.start.column-a.end.column;else var c=2*b.row-a.start.row-a.end.row;return c<0?{cursor:a.start,anchor:a.end}:{cursor:a.end,anchor:a.start}}var d=a(\"../lib/dom\"),e=a(\"../lib/useragent\"),f=5;(function(){this.onMouseDown=function(a){var b=a.inSelection(),c=a.getDocumentPosition();this.mousedownEvent=a;var d=this.editor,e=a.getButton();if(e!==0){var f=d.getSelectionRange(),g=f.isEmpty();g&&(d.moveCursorToPosition(c),d.selection.clearSelection()),d.textInput.onContextMenu(a.domEvent);return}if(b&&!d.isFocused()){d.focus();if(this.$focusWaitTimout&&!this.$clickSelection)return this.setState(\"focusWait\"),this.captureMouse(a),a.preventDefault()}return!b||this.$clickSelection||a.getShiftKey()?this.startSelect(c):b&&(this.mousedownEvent.time=(new Date).getTime(),this.setState(\"dragWait\")),this.captureMouse(a),a.preventDefault()},this.startSelect=function(a){a=a||this.editor.renderer.screenToTextCoordinates(this.x,this.y),this.mousedownEvent.getShiftKey()?this.editor.selection.selectToPosition(a):this.$clickSelection||(this.editor.moveCursorToPosition(a),this.editor.selection.clearSelection()),this.setState(\"select\")},this.select=function(){var a,b=this.editor,c=b.renderer.screenToTextCoordinates(this.x,this.y);if(this.$clickSelection){var d=this.$clickSelection.comparePoint(c);if(d==-1)a=this.$clickSelection.end;else if(d==1)a=this.$clickSelection.start;else{var e=i(this.$clickSelection,c);c=e.cursor,a=e.anchor}b.selection.setSelectionAnchor(a.row,a.column)}b.selection.selectToPosition(c),b.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(a){var b,c=this.editor,d=c.renderer.screenToTextCoordinates(this.x,this.y),e=c.selection[a](d.row,d.column);if(this.$clickSelection){var f=this.$clickSelection.comparePoint(e.start),g=this.$clickSelection.comparePoint(e.end);if(f==-1&&g<=0){b=this.$clickSelection.end;if(e.end.row!=d.row||e.end.column!=d.column)d=e.start}else if(g==1&&f>=0){b=this.$clickSelection.start;if(e.start.row!=d.row||e.start.column!=d.column)d=e.end}else if(f==-1&&g==1)d=e.end,b=e.start;else{var h=i(this.$clickSelection,d);d=h.cursor,b=h.anchor}c.selection.setSelectionAnchor(b.row,b.column)}c.selection.selectToPosition(d),c.renderer.scrollCursorIntoView()},this.startDrag=function(){var a=this.editor;this.setState(\"drag\"),this.dragRange=a.getSelectionRange();var b=a.getSelectionStyle();this.dragSelectionMarker=a.session.addMarker(this.dragRange,\"ace_selection\",b),a.clearSelection(),d.addCssClass(a.container,\"ace_dragging\"),this.$dragKeybinding||(this.$dragKeybinding={handleKeyboard:function(a,b,c,d){if(c==\"esc\")return{command:this.command}},command:{exec:function(a){var b=a.$mouseHandler;b.dragCursor=null,b.dragEnd(),b.startSelect()}}}),a.keyBinding.addKeyboardHandler(this.$dragKeybinding)},this.focusWait=function(){var a=h(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),b=(new Date).getTime();(a>f||b-this.mousedownEvent.time>this.$focusWaitTimout)&&this.startSelect()},this.dragWait=function(a){var b=h(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),c=(new Date).getTime(),d=this.editor;b>f?this.startSelect(this.mousedownEvent.getDocumentPosition()):c-this.mousedownEvent.time>d.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(a){this.mousedownEvent.domEvent=a,this.startSelect()},this.drag=function(){var a=this.editor;this.dragCursor=a.renderer.screenToTextCoordinates(this.x,this.y),a.moveCursorToPosition(this.dragCursor),a.renderer.scrollCursorIntoView()},this.dragEnd=function(a){var b=this.editor,c=this.dragCursor,e=this.dragRange;d.removeCssClass(b.container,\"ace_dragging\"),b.session.removeMarker(this.dragSelectionMarker),b.keyBinding.removeKeyboardHandler(this.$dragKeybinding);if(!c)return;b.clearSelection();if(a&&(a.ctrlKey||a.altKey)){var f=b.session,g=e;g.end=f.insert(c,f.getTextRange(e)),g.start=c}else{if(e.contains(c.row,c.column))return;var g=b.moveText(e,c)}if(!g)return;b.selection.setSelectionRange(g)},this.onDoubleClick=function(a){var b=a.getDocumentPosition(),c=this.editor,d=c.session,e=d.getBracketRange(b);if(e){e.isEmpty()&&(e.start.column--,e.end.column++),this.$clickSelection=e,this.setState(\"select\");return}this.$clickSelection=c.selection.getWordRange(b.row,b.column),this.setState(\"selectByWords\")},this.onTripleClick=function(a){var b=a.getDocumentPosition(),c=this.editor;this.setState(\"selectByLines\"),this.$clickSelection=c.selection.getLineRange(b.row)},this.onQuadClick=function(a){var b=this.editor;b.selectAll(),this.$clickSelection=b.getSelectionRange(),this.setState(\"null\")},this.onScroll=function(a){var b=this.editor,c=b.renderer.isScrollableBy(a.wheelX*a.speed,a.wheelY*a.speed);if(c)this.$passScrollEvent=!1;else{if(this.$passScrollEvent)return;if(!this.$scrollStopTimeout){var d=this;this.$scrollStopTimeout=setTimeout(function(){d.$passScrollEvent=!0,d.$scrollStopTimeout=null},200)}}return b.renderer.scrollBy(a.wheelX*a.speed,a.wheelY*a.speed),a.preventDefault()}}).call(g.prototype),b.DefaultHandlers=g}),ace.define(\"ace/mouse/default_gutter_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/event\"],function(a,b,c){function f(a){function j(){h=d.createElement(\"div\"),h.className=\"ace_gutter_tooltip\",h.style.maxWidth=\"500px\",h.style.display=\"none\",b.container.appendChild(h)}function k(){h||j();var a=g.getDocumentPosition().row,d=c.$annotations[a];if(!d)return l();var e=b.session.getLength();if(a==e){var f=b.renderer.pixelToScreenCoordinates(0,g.y).row,k=g.$pos;if(f>b.session.documentToScreenRow(k.row,k.column))return l()}if(i==d)return;i=d.text.join(\"\\n\"),h.style.display=\"block\",h.innerHTML=i,b.on(\"mousewheel\",l),m(g)}function l(){f&&(f=clearTimeout(f)),i&&(h.style.display=\"none\",i=null,b.removeEventListener(\"mousewheel\",l))}function m(a){var c=b.renderer.$gutter.getBoundingClientRect();h.style.left=a.x-c.left+15+\"px\",a.y+3*b.renderer.lineHeight+15<c.bottom?(h.style.bottom=\"\",h.style.top=a.y-c.top+15+\"px\"):(h.style.top=\"\",h.style.bottom=c.bottom-a.y+5+\"px\")}var b=a.editor,c=b.renderer.$gutterLayer;a.editor.setDefaultHandler(\"guttermousedown\",function(d){if(!b.isFocused())return;var e=c.getRegion(d);if(e)return;var f=d.getDocumentPosition().row,g=b.session.selection;return d.getShiftKey()?g.selectTo(f,0):a.$clickSelection=b.selection.getLineRange(f),a.captureMouse(d,\"selectByLines\"),d.preventDefault()});var f,g,h,i;a.editor.setDefaultHandler(\"guttermousemove\",function(a){var b=a.domEvent.target||a.domEvent.srcElement;if(d.hasCssClass(b,\"ace_fold-widget\"))return l();i&&m(a),g=a;if(f)return;f=setTimeout(function(){f=null,g?k():l()},50)}),e.addListener(b.renderer.$gutter,\"mouseout\",function(a){g=null;if(!i||f)return;f=setTimeout(function(){f=null,l()},50)})}var d=a(\"../lib/dom\"),e=a(\"../lib/event\");b.GutterHandler=f}),ace.define(\"ace/mouse/mouse_event\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"],function(a,b,c){var d=a(\"../lib/event\"),e=a(\"../lib/useragent\"),f=b.MouseEvent=function(a,b){this.domEvent=a,this.editor=b,this.x=this.clientX=a.clientX,this.y=this.clientY=a.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){d.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){d.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var a=this.editor;if(a.getReadOnly())this.$inSelection=!1;else{var b=a.getSelectionRange();if(b.isEmpty())this.$inSelection=!1;else{var c=this.getDocumentPosition();this.$inSelection=b.contains(c.row,c.column)}}return this.$inSelection},this.getButton=function(){return d.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=e.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(f.prototype)}),ace.define(\"ace/mouse/dragdrop\",[\"require\",\"exports\",\"module\",\"ace/lib/event\"],function(a,b,c){var d=a(\"../lib/event\"),e=function(a){var b=a.editor,c,e,f,g,h,i,j,k=0,l=b.container;d.addListener(l,\"dragenter\",function(a){k++;if(!c){h=b.getSelectionRange(),i=b.selection.isBackwards();var e=b.getSelectionStyle();c=b.session.addMarker(h,\"ace_selection\",e),b.clearSelection(),clearInterval(g),g=setInterval(m,20)}return d.preventDefault(a)}),d.addListener(l,\"dragover\",function(a){return e=a.clientX,f=a.clientY,d.preventDefault(a)});var m=function(){j=b.renderer.screenToTextCoordinates(e,f),b.moveCursorToPosition(j),b.renderer.scrollCursorIntoView()};d.addListener(l,\"dragleave\",function(a){k--;if(k>0)return;return console.log(a.type,k,a.target),clearInterval(g),b.session.removeMarker(c),c=null,b.selection.setSelectionRange(h,i),d.preventDefault(a)}),d.addListener(l,\"drop\",function(a){return console.log(a.type,k,a.target),k=0,clearInterval(g),b.session.removeMarker(c),c=null,h.end=b.session.insert(j,a.dataTransfer.getData(\"Text\")),h.start=j,b.focus(),b.selection.setSelectionRange(h),d.preventDefault(a)})};b.DragdropHandler=e}),ace.define(\"ace/mouse/fold_handler\",[\"require\",\"exports\",\"module\"],function(a,b,c){function d(a){a.on(\"click\",function(b){var c=b.getDocumentPosition(),d=a.session,e=d.getFoldAt(c.row,c.column,1);e&&(b.getAccelKey()?d.removeFold(e):d.expandFold(e),b.stop())}),a.on(\"gutterclick\",function(b){var c=a.renderer.$gutterLayer.getRegion(b);if(c==\"foldWidgets\"){var d=b.getDocumentPosition().row,e=a.session;e.foldWidgets&&e.foldWidgets[d]&&a.session.onFoldWidgetClick(d,b),b.stop()}})}b.FoldHandler=d}),ace.define(\"ace/keyboard/keybinding\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/event\"],function(a,b,c){var d=a(\"../lib/keys\"),e=a(\"../lib/event\"),f=function(a){this.$editor=a,this.$data={},this.$handlers=[],this.setDefaultHandler(a.commands)};(function(){this.setDefaultHandler=function(a){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=a,this.addKeyboardHandler(a,0),this.$data={editor:this.$editor}},this.setKeyboardHandler=function(a){if(this.$handlers[this.$handlers.length-1]==a)return;while(this.$handlers[1])this.removeKeyboardHandler(this.$handlers[1]);this.addKeyboardHandler(a,1)},this.addKeyboardHandler=function(a,b){if(!a)return;var c=this.$handlers.indexOf(a);c!=-1&&this.$handlers.splice(c,1),b==undefined?this.$handlers.push(a):this.$handlers.splice(b,0,a),c==-1&&a.attach&&a.attach(this.$editor)},this.removeKeyboardHandler=function(a){var b=this.$handlers.indexOf(a);return b==-1?!1:(this.$handlers.splice(b,1),a.detach&&a.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.$callKeyboardHandlers=function(a,b,c,d){var f;for(var g=this.$handlers.length;g--;){f=this.$handlers[g].handleKeyboard(this.$data,a,b,c,d);if(f&&f.command)break}if(!f||!f.command)return!1;var h=!1,i=this.$editor.commands;return f.command!=\"null\"?h=i.exec(f.command,this.$editor,f.args,d):h=f.passEvent!=1,h&&d&&a!=-1&&e.stopEvent(d),h},this.onCommandKey=function(a,b,c){var e=d.keyCodeToString(c);this.$callKeyboardHandlers(b,e,c,a)},this.onTextInput=function(a){var b=this.$callKeyboardHandlers(-1,a);b||this.$editor.commands.exec(\"insertstring\",this.$editor,a)}}).call(f.prototype),b.KeyBinding=f}),ace.define(\"ace/edit_session\",[\"require\",\"exports\",\"module\",\"ace/config\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/net\",\"ace/lib/event_emitter\",\"ace/selection\",\"ace/mode/text\",\"ace/range\",\"ace/document\",\"ace/background_tokenizer\",\"ace/search_highlight\",\"ace/edit_session/folding\",\"ace/edit_session/bracket_match\"],function(a,b,c){var d=a(\"./config\"),e=a(\"./lib/oop\"),f=a(\"./lib/lang\"),g=a(\"./lib/net\"),h=a(\"./lib/event_emitter\").EventEmitter,i=a(\"./selection\").Selection,j=a(\"./mode/text\").Mode,k=a(\"./range\").Range,l=a(\"./document\").Document,m=a(\"./background_tokenizer\").BackgroundTokenizer,n=a(\"./search_highlight\").SearchHighlight,o=function(a,b){this.$modified=!0,this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$resetRowCache(0),this.$wrapData=[],this.$foldData=[],this.$rowLengthCache=[],this.$undoSelect=!0,this.$foldData.toString=function(){var a=\"\";return this.forEach(function(b){a+=\"\\n\"+b.toString()}),a},typeof a==\"object\"&&a.getLine?this.setDocument(a):this.setDocument(new l(a)),this.selection=new i(this),this.setMode(b)};(function(){function s(a){return a<4352?!1:a>=4352&&a<=4447||a>=4515&&a<=4519||a>=4602&&a<=4607||a>=9001&&a<=9002||a>=11904&&a<=11929||a>=11931&&a<=12019||a>=12032&&a<=12245||a>=12272&&a<=12283||a>=12288&&a<=12350||a>=12353&&a<=12438||a>=12441&&a<=12543||a>=12549&&a<=12589||a>=12593&&a<=12686||a>=12688&&a<=12730||a>=12736&&a<=12771||a>=12784&&a<=12830||a>=12832&&a<=12871||a>=12880&&a<=13054||a>=13056&&a<=19903||a>=19968&&a<=42124||a>=42128&&a<=42182||a>=43360&&a<=43388||a>=44032&&a<=55203||a>=55216&&a<=55238||a>=55243&&a<=55291||a>=63744&&a<=64255||a>=65040&&a<=65049||a>=65072&&a<=65106||a>=65108&&a<=65126||a>=65128&&a<=65131||a>=65281&&a<=65376||a>=65504&&a<=65510}e.implement(this,h),this.setDocument=function(a){if(this.doc)throw new Error(\"Document is already set\");this.doc=a,a.on(\"change\",this.onChange.bind(this)),this.on(\"changeFold\",this.onChangeFold.bind(this)),this.bgTokenizer&&(this.bgTokenizer.setDocument(this.getDocument()),this.bgTokenizer.start(0))},this.getDocument=function(){return this.doc},this.$resetRowCache=function(a){if(!a){this.$docRowCache=[],this.$screenRowCache=[];return}var b=this.$getRowCacheIndex(this.$docRowCache,a)+1,c=this.$docRowCache.length;this.$docRowCache.splice(b,c),this.$screenRowCache.splice(b,c)},this.$getRowCacheIndex=function(a,b){var c=0,d=a.length-1;while(c<=d){var e=c+d>>1,f=a[e];if(b>f)c=e+1;else{if(!(b<f))return e;d=e-1}}return c&&c-1},this.onChangeFold=function(a){var b=a.data;this.$resetRowCache(b.start.row)},this.onChange=function(a){var b=a.data;this.$modified=!0,this.$resetRowCache(b.range.start.row);var c=this.$updateInternalDataOnChange(a);!this.$fromUndo&&this.$undoManager&&!b.ignore&&(this.$deltasDoc.push(b),c&&c.length!=0&&this.$deltasFold.push({action:\"removeFolds\",folds:c}),this.$informUndoManager.schedule()),this.bgTokenizer.$updateOnChange(b),this._emit(\"change\",a)},this.setValue=function(a){this.doc.setValue(a),this.selection.moveCursorTo(0,0),this.selection.clearSelection(),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(a){return this.bgTokenizer.getState(a)},this.getTokens=function(a){return this.bgTokenizer.getTokens(a)},this.getTokenAt=function(a,b){var c=this.bgTokenizer.getTokens(a),d,e=0;if(b==null)f=c.length-1,e=this.getLine(a).length;else for(var f=0;f<c.length;f++){e+=c[f].value.length;if(e>=b)break}return d=c[f],d?(d.index=f,d.start=e-d.value.length,d):null},this.highlight=function(a){if(!this.$searchHighlight){var b=new n(null,\"ace_selected_word\",\"text\");this.$searchHighlight=this.addDynamicMarker(b)}this.$searchHighlight.setRegexp(a)},this.setUndoManager=function(a){this.$undoManager=a,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(a){var b=this;this.$syncInformUndoManager=function(){b.$informUndoManager.cancel(),b.$deltasFold.length&&(b.$deltas.push({group:\"fold\",deltas:b.$deltasFold}),b.$deltasFold=[]),b.$deltasDoc.length&&(b.$deltas.push({group:\"doc\",deltas:b.$deltasDoc}),b.$deltasDoc=[]),b.$deltas.length>0&&a.execute({action:\"aceupdate\",args:[b.$deltas,b]}),b.$deltas=[]},this.$informUndoManager=f.deferredCall(this.$syncInformUndoManager)}},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?f.stringRepeat(\" \",this.getTabSize()):\"\t\"},this.$useSoftTabs=!0,this.setUseSoftTabs=function(a){if(this.$useSoftTabs===a)return;this.$useSoftTabs=a},this.getUseSoftTabs=function(){return this.$useSoftTabs},this.$tabSize=4,this.setTabSize=function(a){if(isNaN(a)||this.$tabSize===a)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=a,this._emit(\"changeTabSize\")},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(a){return this.$useSoftTabs&&a.column%this.$tabSize==0},this.$overwrite=!1,this.setOverwrite=function(a){if(this.$overwrite==a)return;this.$overwrite=a,this._emit(\"changeOverwrite\")},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(a,b){this.$decorations[a]||(this.$decorations[a]=\"\"),this.$decorations[a]+=\" \"+b,this._emit(\"changeBreakpoint\",{})},this.removeGutterDecoration=function(a,b){this.$decorations[a]=(this.$decorations[a]||\"\").replace(\" \"+b,\"\"),this._emit(\"changeBreakpoint\",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(a){this.$breakpoints=[];for(var b=0;b<a.length;b++)this.$breakpoints[a[b]]=\"ace_breakpoint\";this._emit(\"changeBreakpoint\",{})},this.clearBreakpoints=function(){this.$breakpoints=[],this._emit(\"changeBreakpoint\",{})},this.setBreakpoint=function(a,b){b===undefined&&(b=\"ace_breakpoint\"),b?this.$breakpoints[a]=b:delete this.$breakpoints[a],this._emit(\"changeBreakpoint\",{})},this.clearBreakpoint=function(a){delete this.$breakpoints[a],this._emit(\"changeBreakpoint\",{})},this.addMarker=function(a,b,c,d){var e=this.$markerId++,f={range:a,type:c||\"line\",renderer:typeof c==\"function\"?c:null,clazz:b,inFront:!!d,id:e};return d?(this.$frontMarkers[e]=f,this._emit(\"changeFrontMarker\")):(this.$backMarkers[e]=f,this._emit(\"changeBackMarker\")),e},this.addDynamicMarker=function(a,b){if(!a.update)return;var c=this.$markerId++;return a.id=c,a.inFront=!!b,b?(this.$frontMarkers[c]=a,this._emit(\"changeFrontMarker\")):(this.$backMarkers[c]=a,this._emit(\"changeBackMarker\")),a},this.removeMarker=function(a){var b=this.$frontMarkers[a]||this.$backMarkers[a];if(!b)return;var c=b.inFront?this.$frontMarkers:this.$backMarkers;b&&(delete c[a],this._emit(b.inFront?\"changeFrontMarker\":\"changeBackMarker\"))},this.getMarkers=function(a){return a?this.$frontMarkers:this.$backMarkers},this.setAnnotations=function(a){this.$annotations={};for(var b=0;b<a.length;b++){var c=a[b],d=c.row;this.$annotations[d]?this.$annotations[d].push(c):this.$annotations[d]=[c]}this._emit(\"changeAnnotation\",{})},this.getAnnotations=function(){return this.$annotations||{}},this.clearAnnotations=function(){this.$annotations={},this._emit(\"changeAnnotation\",{})},this.$detectNewLine=function(a){var b=a.match(/^.*?(\\r?\\n)/m);b?this.$autoNewLine=b[1]:this.$autoNewLine=\"\\n\"},this.getWordRange=function(a,b){var c=this.getLine(a),d=!1;b>0&&(d=!!c.charAt(b-1).match(this.tokenRe)),d||(d=!!c.charAt(b).match(this.tokenRe));if(d)var e=this.tokenRe;else if(/^\\s+$/.test(c.slice(b-1,b+1)))var e=/\\s/;else var e=this.nonTokenRe;var f=b;if(f>0){do f--;while(f>=0&&c.charAt(f).match(e));f++}var g=b;while(g<c.length&&c.charAt(g).match(e))g++;return new k(a,f,a,g)},this.getAWordRange=function(a,b){var c=this.getWordRange(a,b),d=this.getLine(c.end.row);while(d.charAt(c.end.column).match(/[ \\t]/))c.end.column+=1;return c},this.setNewLineMode=function(a){this.doc.setNewLineMode(a)},this.getNewLineMode=function(){return this.doc.getNewLineMode()},this.$useWorker=!0,this.setUseWorker=function(a){if(this.$useWorker==a)return;this.$useWorker=a,this.$stopWorker(),a&&this.$startWorker()},this.getUseWorker=function(){return this.$useWorker},this.onReloadTokenizer=function(a){var b=a.data;this.bgTokenizer.start(b.first),this._emit(\"tokenizerUpdate\",a)},this.$modes={},this._loadMode=function(b,c){function i(a){if(e.$modes[b])return c(e.$modes[b]);e.$modes[b]=new a.Mode,e.$modes[b].$id=b,e._emit(\"loadmode\",{name:b,mode:e.$modes[b]}),c(e.$modes[b])}function k(a,b){if(!d.get(\"packaged\"))return b();g.loadScript(d.moduleUrl(a,\"mode\"),b)}this.$modes[\"null\"]||(this.$modes[\"null\"]=this.$modes[\"ace/mode/text\"]=new j);if(this.$modes[b])return c(this.$modes[b]);var e=this,f;try{f=a(b)}catch(h){}if(f&&f.Mode)return i(f);this.$mode||this.$setModePlaceholder(),k(b,function(){a([b],i)})},this.$setModePlaceholder=function(){this.$mode=this.$modes[\"null\"];var a=this.$mode.getTokenizer();if(!this.bgTokenizer){this.bgTokenizer=new m(a);var b=this;this.bgTokenizer.addEventListener(\"update\",function(a){b._emit(\"tokenizerUpdate\",a)})}else this.bgTokenizer.setTokenizer(a);this.bgTokenizer.setDocument(this.getDocument()),this.tokenRe=this.$mode.tokenRe,this.nonTokenRe=this.$mode.nonTokenRe},this.$mode=null,this.$modeId=null,this.setMode=function(a){a=a||\"null\";if(typeof a==\"string\"){if(this.$modeId==a)return;this.$modeId=a;var b=this;this._loadMode(a,function(c){if(b.$modeId!==a)return;b.setMode(c)});return}if(this.$mode===a)return;this.$mode=a,this.$modeId=a.$id,this.$stopWorker(),this.$useWorker&&this.$startWorker();var c=a.getTokenizer();if(c.addEventListener!==undefined){var d=this.onReloadTokenizer.bind(this);c.addEventListener(\"update\",d)}if(!this.bgTokenizer){this.bgTokenizer=new m(c);var b=this;this.bgTokenizer.addEventListener(\"update\",function(a){b._emit(\"tokenizerUpdate\",a)})}else this.bgTokenizer.setTokenizer(c);this.bgTokenizer.setDocument(this.getDocument()),this.bgTokenizer.start(0),this.tokenRe=a.tokenRe,this.nonTokenRe=a.nonTokenRe,this.$setFolding(a.foldingRules),this._emit(\"changeMode\")},this.$stopWorker=function(){this.$worker&&this.$worker.terminate(),this.$worker=null},this.$startWorker=function(){if(typeof Worker!=\"undefined\"&&!a.noWorker)try{this.$worker=this.$mode.createWorker(this)}catch(b){console.log(\"Could not load worker\"),console.log(b),this.$worker=null}else this.$worker=null},this.getMode=function(){return this.$mode},this.$scrollTop=0,this.setScrollTop=function(a){a=Math.round(Math.max(0,a));if(this.$scrollTop===a)return;this.$scrollTop=a,this._emit(\"changeScrollTop\",a)},this.getScrollTop=function(){return this.$scrollTop},this.$scrollLeft=0,this.setScrollLeft=function(a){a=Math.round(Math.max(0,a));if(this.$scrollLeft===a)return;this.$scrollLeft=a,this._emit(\"changeScrollLeft\",a)},this.getScrollLeft=function(){return this.$scrollLeft},this.getScreenWidth=function(){return this.$computeWidth(),this.screenWidth},this.$computeWidth=function(a){if(this.$modified||a){this.$modified=!1;if(this.$useWrapMode)return this.screenWidth=this.$wrapLimit;var b=this.doc.getAllLines(),c=this.$rowLengthCache,d=0,e=0,f=this.$foldData[e],g=f?f.start.row:Infinity,h=b.length;for(var i=0;i<h;i++){if(i>g){i=f.end.row+1;if(i>=h)break;f=this.$foldData[e++],g=f?f.start.row:Infinity}c[i]==null&&(c[i]=this.$getStringScreenWidth(b[i])[0]),c[i]>d&&(d=c[i])}this.screenWidth=d}},this.getLine=function(a){return this.doc.getLine(a)},this.getLines=function(a,b){return this.doc.getLines(a,b)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(a){return this.doc.getTextRange(a||this.selection.getRange())},this.insert=function(a,b){return this.doc.insert(a,b)},this.remove=function(a){return this.doc.remove(a)},this.undoChanges=function(a,b){if(!a.length)return;this.$fromUndo=!0;var c=null;for(var d=a.length-1;d!=-1;d--){var e=a[d];e.group==\"doc\"?(this.doc.revertDeltas(e.deltas),c=this.$getUndoSelection(e.deltas,!0,c)):e.deltas.forEach(function(a){this.addFolds(a.folds)},this)}return this.$fromUndo=!1,c&&this.$undoSelect&&!b&&this.selection.setSelectionRange(c),c},this.redoChanges=function(a,b){if(!a.length)return;this.$fromUndo=!0;var c=null;for(var d=0;d<a.length;d++){var e=a[d];e.group==\"doc\"&&(this.doc.applyDeltas(e.deltas),c=this.$getUndoSelection(e.deltas,!1,c))}return this.$fromUndo=!1,c&&this.$undoSelect&&!b&&this.selection.setSelectionRange(c),c},this.setUndoSelect=function(a){this.$undoSelect=a},this.$getUndoSelection=function(a,b,c){function d(a){var c=a.action==\"insertText\"||a.action==\"insertLines\";return b?!c:c}var e=a[0],f,g,h=!1;d(e)?(f=e.range.clone(),h=!0):(f=k.fromPoints(e.range.start,e.range.start),h=!1);for(var i=1;i<a.length;i++)e=a[i],d(e)?(g=e.range.start,f.compare(g.row,g.column)==-1&&f.setStart(e.range.start),g=e.range.end,f.compare(g.row,g.column)==1&&f.setEnd(e.range.end),h=!0):(g=e.range.start,f.compare(g.row,g.column)==-1&&(f=k.fromPoints(e.range.start,e.range.start)),h=!1);if(c!=null){var j=c.compareRange(f);j==1?f.setStart(c.start):j==-1&&f.setEnd(c.end)}return f},this.replace=function(a,b){return this.doc.replace(a,b)},this.moveText=function(a,b){var c=this.getTextRange(a);this.remove(a);var d=b.row,e=b.column;!a.isMultiLine()&&a.start.row==d&&a.end.column<e&&(e-=c.length);if(a.isMultiLine()&&a.end.row<d){var f=this.doc.$split(c);d-=f.length-1}var g=d+a.end.row-a.start.row,h=a.isMultiLine()?a.end.column:e+a.end.column-a.start.column,i=new k(d,e,g,h);return this.insert(i.start,c),i},this.indentRows=function(a,b,c){c=c.replace(/\\t/g,this.getTabString());for(var d=a;d<=b;d++)this.insert({row:d,column:0},c)},this.outdentRows=function(a){var b=a.collapseRows(),c=new k(0,0,0,0),d=this.getTabSize();for(var e=b.start.row;e<=b.end.row;++e){var f=this.getLine(e);c.start.row=e,c.end.row=e;for(var g=0;g<d;++g)if(f.charAt(g)!=\" \")break;g<d&&f.charAt(g)==\"\t\"?(c.start.column=g,c.end.column=g+1):(c.start.column=0,c.end.column=g),this.remove(c)}},this.moveLinesUp=function(a,b){if(a<=0)return 0;var c=this.doc.removeLines(a,b);return this.doc.insertLines(a-1,c),-1},this.moveLinesDown=function(a,b){if(b>=this.doc.getLength()-1)return 0;var c=this.doc.removeLines(a,b);return this.doc.insertLines(a+1,c),1},this.duplicateLines=function(a,b){var a=this.$clipRowToDocument(a),b=this.$clipRowToDocument(b),c=this.getLines(a,b);this.doc.insertLines(a,c);var d=b-a+1;return d},this.$clipRowToDocument=function(a){return Math.max(0,Math.min(a,this.doc.getLength()-1))},this.$clipColumnToRow=function(a,b){return b<0?0:Math.min(this.doc.getLine(a).length,b)},this.$clipPositionToDocument=function(a,b){b=Math.max(0,b);if(a<0)a=0,b=0;else{var c=this.doc.getLength();a>=c?(a=c-1,b=this.doc.getLine(c-1).length):b=Math.min(this.doc.getLine(a).length,b)}return{row:a,column:b}},this.$clipRangeToDocument=function(a){a.start.row<0?(a.start.row=0,a.start.column=0):a.start.column=this.$clipColumnToRow(a.start.row,a.start.column);var b=this.doc.getLength()-1;return a.end.row>b?(a.end.row=b,a.end.column=this.doc.getLine(b).length):a.end.column=this.$clipColumnToRow(a.end.row,a.end.column),a},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(a){if(a!=this.$useWrapMode){this.$useWrapMode=a,this.$modified=!0,this.$resetRowCache(0);if(a){var b=this.getLength();this.$wrapData=[];for(var c=0;c<b;c++)this.$wrapData.push([]);this.$updateWrapData(0,b-1)}this._emit(\"changeWrapMode\")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(a,b){if(this.$wrapLimitRange.min!==a||this.$wrapLimitRange.max!==b)this.$wrapLimitRange.min=a,this.$wrapLimitRange.max=b,this.$modified=!0,this._emit(\"changeWrapMode\")},this.adjustWrapLimit=function(a){var b=this.$constrainWrapLimit(a);return b!=this.$wrapLimit&&b>0?(this.$wrapLimit=b,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._emit(\"changeWrapLimit\")),!0):!1},this.$constrainWrapLimit=function(a){var b=this.$wrapLimitRange.min;b&&(a=Math.max(b,a));var c=this.$wrapLimitRange.max;return c&&(a=Math.min(c,a)),Math.max(1,a)},this.getWrapLimit=function(){return this.$wrapLimit},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(a){var b=this.$useWrapMode,c,d=a.data.action,e=a.data.range.start.row,f=a.data.range.end.row,g=a.data.range.start,h=a.data.range.end,i=null;d.indexOf(\"Lines\")!=-1?(d==\"insertLines\"?f=e+a.data.lines.length:f=e,c=a.data.lines?a.data.lines.length:f-e):c=f-e;if(c!=0)if(d.indexOf(\"remove\")!=-1){this[b?\"$wrapData\":\"$rowLengthCache\"].splice(e,c);var j=this.$foldData;i=this.getFoldsInRange(a.data.range),this.removeFolds(i);var k=this.getFoldLine(h.row),l=0;if(k){k.addRemoveChars(h.row,h.column,g.column-h.column),k.shiftRow(-c);var m=this.getFoldLine(e);m&&m!==k&&(m.merge(k),k=m),l=j.indexOf(k)+1}for(l;l<j.length;l++){var k=j[l];k.start.row>=h.row&&k.shiftRow(-c)}f=e}else{var n;if(b){n=[e,0];for(var o=0;o<c;o++)n.push([]);this.$wrapData.splice.apply(this.$wrapData,n)}else n=Array(c),n.unshift(e,0),this.$rowLengthCache.splice.apply(this.$rowLengthCache,n);var j=this.$foldData,k=this.getFoldLine(e),l=0;if(k){var p=k.range.compareInside(g.row,g.column);p==0?(k=k.split(g.row,g.column),k.shiftRow(c),k.addRemoveChars(f,0,h.column-g.column)):p==-1&&(k.addRemoveChars(e,0,h.column-g.column),k.shiftRow(c)),l=j.indexOf(k)+1}for(l;l<j.length;l++){var k=j[l];k.start.row>=e&&k.shiftRow(c)}}else{c=Math.abs(a.data.range.start.column-a.data.range.end.column),d.indexOf(\"remove\")!=-1&&(i=this.getFoldsInRange(a.data.range),this.removeFolds(i),c=-c);var k=this.getFoldLine(e);k&&k.addRemoveChars(e,g.column,c)}return b&&this.$wrapData.length!=this.doc.getLength()&&console.error(\"doc.getLength() and $wrapData.length have to be the same!\"),b?this.$updateWrapData(e,f):this.$updateRowLengthCache(e,f),i},this.$updateRowLengthCache=function(a,b,c){this.$rowLengthCache[a]=null,this.$rowLengthCache[b]=null},this.$updateWrapData=function(a,b){var c=this.doc.getAllLines(),d=this.getTabSize(),e=this.$wrapData,g=this.$wrapLimit,h,j,k=a;b=Math.min(b,c.length-1);while(k<=b){j=this.getFoldLine(k,j);if(!j)h=this.$getDisplayTokens(f.stringTrimRight(c[k])),e[k]=this.$computeWrapSplits(h,g,d),k++;else{h=[],j.walk(function(a,b,d,e){var f;if(a){f=this.$getDisplayTokens(a,h.length),f[0]=i;for(var g=1;g<f.length;g++)f[g]=l}else f=this.$getDisplayTokens(c[b].substring(e,d),h.length);h=h.concat(f)}.bind(this),j.end.row,c[j.end.row].length+1);while(h.length!=0&&h[h.length-1]>=p)h.pop();e[j.start.row]=this.$computeWrapSplits(h,g,d),k=j.end.row+1}}};var b=1,c=2,i=3,l=4,o=9,p=10,q=11,r=12;this.$computeWrapSplits=function(a,b){function g(b){var d=a.slice(e,b),g=d.length;d.join(\"\").replace(/12/g,function(){g-=1}).replace(/2/g,function(){g-=1}),f+=g,c.push(f),e=b}if(a.length==0)return[];var c=[],d=a.length,e=0,f=0;while(d-e>b){var h=e+b;if(a[h]>=p){while(a[h]>=p)h++;g(h);continue}if(a[h]==i||a[h]==l){for(h;h!=e-1;h--)if(a[h]==i)break;if(h>e){g(h);continue}h=e+b;for(h;h<a.length;h++)if(a[h]!=l)break;if(h==a.length)break;g(h);continue}var j=Math.max(h-10,e-1);while(h>j&&a[h]<i)h--;while(h>j&&a[h]==o)h--;if(h>j){g(++h);continue}h=e+b,g(h)}return c},this.$getDisplayTokens=function(a,d){var e=[],f;d=d||0;for(var g=0;g<a.length;g++){var h=a.charCodeAt(g);if(h==9){f=this.getScreenTabSize(e.length+d),e.push(q);for(var i=1;i<f;i++)e.push(r)}else h==32?e.push(p):h>39&&h<48||h>57&&h<64?e.push(o):h>=4352&&s(h)?e.push(b,c):e.push(b)}return e},this.$getStringScreenWidth=function(a,b,c){if(b==0)return[0,0];b==null&&(b=Infinity),c=c||0;var d,e;for(e=0;e<a.length;e++){d=a.charCodeAt(e),d==9?c+=this.getScreenTabSize(c):d>=4352&&s(d)?c+=2:c+=1;if(c>b)break}return[c,e]},this.getRowLength=function(a){return!this.$useWrapMode||!this.$wrapData[a]?1:this.$wrapData[a].length+1},this.getScreenLastRowColumn=function(a){var b=this.screenToDocumentPosition(a,Number.MAX_VALUE);return this.documentToScreenColumn(b.row,b.column)},this.getDocumentLastRowColumn=function(a,b){var c=this.documentToScreenRow(a,b);return this.getScreenLastRowColumn(c)},this.getDocumentLastRowColumnPosition=function(a,b){var c=this.documentToScreenRow(a,b);return this.screenToDocumentPosition(c,Number.MAX_VALUE/10)},this.getRowSplitData=function(a){return this.$useWrapMode?this.$wrapData[a]:undefined},this.getScreenTabSize=function(a){return this.$tabSize-a%this.$tabSize},this.screenToDocumentRow=function(a,b){return this.screenToDocumentPosition(a,b).row},this.screenToDocumentColumn=function(a,b){return this.screenToDocumentPosition(a,b).column},this.screenToDocumentPosition=function(a,b){if(a<0)return{row:0,column:0};var c,d=0,e=0,f,g=0,h=0,i=this.$screenRowCache,j=this.$getRowCacheIndex(i,a);if(0<j&&j<i.length)var g=i[j],d=this.$docRowCache[j],k=a>g||a==g&&j==i.length-1;else var k=!0;var l=this.getLength()-1,m=this.getNextFoldLine(d),n=m?m.start.row:Infinity;while(g<=a){h=this.getRowLength(d);if(g+h-1>=a||d>=l)break;g+=h,d++,d>n&&(d=m.end.row+1,m=this.getNextFoldLine(d,m),n=m?m.start.row:Infinity),k&&(this.$docRowCache.push(d),this.$screenRowCache.push(g))}if(m&&m.start.row<=d)c=this.getFoldDisplayLine(m),d=m.start.row;else{if(g+h<=a||d>l)return{row:l,column:this.getLine(l).length};c=this.getLine(d),m=null}if(this.$useWrapMode){var o=this.$wrapData[d];o&&(f=o[a-g],a>g&&o.length&&(e=o[a-g-1]||o[o.length-1],c=c.substring(e)))}return e+=this.$getStringScreenWidth(c,b)[1],this.$useWrapMode&&e>=f&&(e=f-1),m?m.idxToPosition(e):{row:d,column:e}},this.documentToScreenPosition=function(a,b){if(typeof b==\"undefined\")var c=this.$clipPositionToDocument(a.row,a.column);else c=this.$clipPositionToDocument(a,b);a=c.row,b=c.column;var d=0,e=null,f=null;f=this.getFoldAt(a,b,1),f&&(a=f.start.row,b=f.start.column);var g,h=0,i=this.$docRowCache,j=this.$getRowCacheIndex(i,a);if(0<j&&j<i.length)var h=i[j],d=this.$screenRowCache[j],k=a>h||a==h&&j==i.length-1;else var k=!0;var l=this.getNextFoldLine(h),m=l?l.start.row:Infinity;while(h<a){if(h>=m){g=l.end.row+1;if(g>a)break;l=this.getNextFoldLine(g,l),m=l?l.start.row:Infinity}else g=h+1;d+=this.getRowLength(h),h=g,k&&(this.$docRowCache.push(h),this.$screenRowCache.push(d))}var n=\"\";l&&h>=m?(n=this.getFoldDisplayLine(l,a,b),e=l.start.row):(n=this.getLine(a).substring(0,b),e=a);if(this.$useWrapMode){var o=this.$wrapData[e],p=0;while(n.length>=o[p])d++,p++;n=n.substring(o[p-1]||0,n.length)}return{row:d,column:this.$getStringScreenWidth(n)[0]}},this.documentToScreenColumn=function(a,b){return this.documentToScreenPosition(a,b).column},this.documentToScreenRow=function(a,b){return this.documentToScreenPosition(a,b).row},this.getScreenLength=function(){var a=0,b=null;if(!this.$useWrapMode){a=this.getLength();var c=this.$foldData;for(var d=0;d<c.length;d++)b=c[d],a-=b.end.row-b.start.row}else{var e=this.$wrapData.length,f=0,d=0,b=this.$foldData[d++],g=b?b.start.row:Infinity;while(f<e)a+=this.$wrapData[f].length+1,f++,f>g&&(f=b.end.row+1,b=this.$foldData[d++],g=b?b.start.row:Infinity)}return a}}).call(o.prototype),a(\"./edit_session/folding\").Folding.call(o.prototype),a(\"./edit_session/bracket_match\").BracketMatch.call(o.prototype),b.EditSession=o}),ace.define(\"ace/config\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\"],function(a,b,c){function g(a){return a.replace(/-(.)/g,function(a,b){return b.toUpperCase()})}\"no use strict\";var d=a(\"./lib/lang\"),e=function(){return this}(),f={packaged:!1,workerPath:\"\",modePath:\"\",themePath:\"\",suffix:\".js\",$moduleUrls:{}};b.get=function(a){if(!f.hasOwnProperty(a))throw new Error(\"Unknown config key: \"+a);return f[a]},b.set=function(a,b){if(!f.hasOwnProperty(a))throw new Error(\"Unknown config key: \"+a);f[a]=b},b.all=function(){return d.copyObject(f)},b.moduleUrl=function(a,b){if(f.$moduleUrls[a])return f.$moduleUrls[a];var c=a.split(\"/\");b=b||c[c.length-2]||\"\";var d=c[c.length-1].replace(b,\"\").replace(/(^[\\-_])|([\\-_]$)/,\"\");return!d&&c.length>1&&(d=c[c.length-2]),this.get(b+\"Path\")+\"/\"+b+\"-\"+d+this.get(\"suffix\")},b.setModuleUrl=function(a,b){return f.$moduleUrls[a]=b},b.init=function(){f.packaged=a.packaged||c.packaged||e.define&&define.packaged;if(!e.document)return\"\";var d={},h=\"\",i=document.getElementsByTagName(\"script\");for(var j=0;j<i.length;j++){var k=i[j],l=k.src||k.getAttribute(\"src\");if(!l)continue;var m=k.attributes;for(var n=0,o=m.length;n<o;n++){var p=m[n];p.name.indexOf(\"data-ace-\")===0&&(d[g(p.name.replace(/^data-ace-/,\"\"))]=p.value)}var q=l.match(/^(.*)\\/ace(\\-\\w+)?\\.js(\\?|$)/);q&&(h=q[1])}h&&(d.base=d.base||h,d.packaged=!0),d.workerPath=d.workerPath||d.base,d.modePath=d.modePath||d.base,d.themePath=d.themePath||d.base,delete d.base;for(var r in d)typeof d[r]!=\"undefined\"&&b.set(r,d[r])}}),ace.define(\"ace/lib/net\",[\"require\",\"exports\",\"module\",\"ace/lib/useragent\"],function(a,b,c){var d=a(\"./useragent\");b.get=function(a,c){var d=b.createXhr();d.open(\"GET\",a,!0),d.onreadystatechange=function(a){d.readyState===4&&c(d.responseText)},d.send(null)};var e=[\"Msxml2.XMLHTTP\",\"Microsoft.XMLHTTP\",\"Msxml2.XMLHTTP.4.0\"];b.createXhr=function(){var a,b,c;if(typeof XMLHttpRequest!=\"undefined\")return new XMLHttpRequest;for(b=0;b<3;b++){c=e[b];try{a=new ActiveXObject(c)}catch(d){}if(a){e=[c];break}}if(!a)throw new Error(\"createXhr(): XMLHttpRequest not available\");return a},b.loadScript=function(a,b){var c=document.getElementsByTagName(\"head\")[0],e=document.createElement(\"script\");e.src=a,c.appendChild(e),d.isOldIE?e.onreadystatechange=function(){this.readyState==\"loaded\"&&b()}:e.onload=b}}),ace.define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d={};d._emit=d._dispatchEvent=function(a,b){this._eventRegistry=this._eventRegistry||{},this._defaultHandlers=this._defaultHandlers||{};var c=this._eventRegistry[a]||[],d=this._defaultHandlers[a];if(!c.length&&!d)return;b=b||{},b.type||(b.type=a),b.stopPropagation||(b.stopPropagation=function(){this.propagationStopped=!0}),b.preventDefault||(b.preventDefault=function(){this.defaultPrevented=!0});for(var e=0;e<c.length;e++){c[e](b);if(b.propagationStopped)break}if(d&&!b.defaultPrevented)return d(b)},d.setDefaultHandler=function(a,b){this._defaultHandlers=this._defaultHandlers||{};if(this._defaultHandlers[a])throw new Error(\"The default handler for '\"+a+\"' is already set\");this._defaultHandlers[a]=b},d.on=d.addEventListener=function(a,b){this._eventRegistry=this._eventRegistry||{};var c=this._eventRegistry[a];c||(c=this._eventRegistry[a]=[]),c.indexOf(b)==-1&&c.push(b)},d.removeListener=d.removeEventListener=function(a,b){this._eventRegistry=this._eventRegistry||{};var c=this._eventRegistry[a];if(!c)return;var d=c.indexOf(b);d!==-1&&c.splice(d,1)},d.removeAllListeners=function(a){this._eventRegistry&&(this._eventRegistry[a]=[])},b.EventEmitter=d}),ace.define(\"ace/selection\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\",\"ace/range\"],function(a,b,c){var d=a(\"./lib/oop\"),e=a(\"./lib/lang\"),f=a(\"./lib/event_emitter\").EventEmitter,g=a(\"./range\").Range,h=function(a){this.session=a,this.doc=a.getDocument(),this.clearSelection(),this.lead=this.selectionLead=this.doc.createAnchor(0,0),this.anchor=this.selectionAnchor=this.doc.createAnchor(0,0);var b=this;this.lead.on(\"change\",function(a){b._emit(\"changeCursor\"),b.$isEmpty||b._emit(\"changeSelection\"),!b.$keepDesiredColumnOnChange&&a.old.column!=a.value.column&&(b.$desiredColumn=null)}),this.selectionAnchor.on(\"change\",function(){b.$isEmpty||b._emit(\"changeSelection\")})};(function(){d.implement(this,f),this.isEmpty=function(){return this.$isEmpty||this.anchor.row==this.lead.row&&this.anchor.column==this.lead.column},this.isMultiLine=function(){return this.isEmpty()?!1:this.getRange().isMultiLine()},this.getCursor=function(){return this.lead.getPosition()},this.setSelectionAnchor=function(a,b){this.anchor.setPosition(a,b),this.$isEmpty&&(this.$isEmpty=!1,this._emit(\"changeSelection\"))},this.getSelectionAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.anchor.getPosition()},this.getSelectionLead=function(){return this.lead.getPosition()},this.shiftSelection=function(a){if(this.$isEmpty){this.moveCursorTo(this.lead.row,this.lead.column+a);return}var b=this.getSelectionAnchor(),c=this.getSelectionLead(),d=this.isBackwards();(!d||b.column!==0)&&this.setSelectionAnchor(b.row,b.column+a),(d||c.column!==0)&&this.$moveSelection(function(){this.moveCursorTo(c.row,c.column+a)})},this.isBackwards=function(){var a=this.anchor,b=this.lead;return a.row>b.row||a.row==b.row&&a.column>b.column},this.getRange=function(){var a=this.anchor,b=this.lead;return this.isEmpty()?g.fromPoints(b,b):this.isBackwards()?g.fromPoints(b,a):g.fromPoints(a,b)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit(\"changeSelection\"))},this.selectAll=function(){var a=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(a,this.doc.getLine(a).length)},this.setRange=this.setSelectionRange=function(a,b){b?(this.setSelectionAnchor(a.end.row,a.end.column),this.selectTo(a.start.row,a.start.column)):(this.setSelectionAnchor(a.start.row,a.start.column),this.selectTo(a.end.row,a.end.column)),this.$desiredColumn=null},this.$moveSelection=function(a){var b=this.lead;this.$isEmpty&&this.setSelectionAnchor(b.row,b.column),a.call(this)},this.selectTo=function(a,b){this.$moveSelection(function(){this.moveCursorTo(a,b)})},this.selectToPosition=function(a){this.$moveSelection(function(){this.moveCursorToPosition(a)})},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(a,b){if(typeof b==\"undefined\"){var c=a||this.lead;a=c.row,b=c.column}return this.session.getWordRange(a,b)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var a=this.getCursor(),b=this.session.getAWordRange(a.row,a.column);this.setSelectionRange(b)},this.getLineRange=function(a,b){var c=typeof a==\"number\"?a:this.lead.row,d,e=this.session.getFoldLine(c);return e?(c=e.start.row,d=e.end.row):d=c,b?new g(c,0,d,this.session.getLine(d).length):new g(c,0,d+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var a=this.lead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,-1))this.moveCursorTo(b.start.row,b.start.column);else if(a.column==0)a.row>0&&this.moveCursorTo(a.row-1,this.doc.getLine(a.row-1).length);else{var c=this.session.getTabSize();this.session.isTabStop(a)&&this.doc.getLine(a.row).slice(a.column-c,a.column).split(\" \").length-1==c?this.moveCursorBy(0,-c):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var a=this.lead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,1))this.moveCursorTo(b.end.row,b.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row<this.doc.getLength()-1&&this.moveCursorTo(this.lead.row+1,0);else{var c=this.session.getTabSize(),a=this.lead;this.session.isTabStop(a)&&this.doc.getLine(a.row).slice(a.column,a.column+c).split(\" \").length-1==c?this.moveCursorBy(0,c):this.moveCursorBy(0,1)}},this.moveCursorLineStart=function(){var a=this.lead.row,b=this.lead.column,c=this.session.documentToScreenRow(a,b),d=this.session.screenToDocumentPosition(c,0),e=this.session.getDisplayLine(a,null,d.row,d.column),f=e.match(/^\\s*/);f[0].length==b?this.moveCursorTo(d.row,d.column):this.moveCursorTo(d.row,d.column+f[0].length)},this.moveCursorLineEnd=function(){var a=this.lead,b=this.session.getDocumentLastRowColumnPosition(a.row,a.column);if(this.lead.column==b.column){var c=this.session.getLine(b.row);if(b.column==c.length){var d=c.search(/\\s+$/);d>0&&(b.column=d)}}this.moveCursorTo(b.row,b.column)},this.moveCursorFileEnd=function(){var a=this.doc.getLength()-1,b=this.doc.getLine(a).length;this.moveCursorTo(a,b)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var a=this.lead.row,b=this.lead.column,c=this.doc.getLine(a),d=c.substring(b),e;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var f=this.session.getFoldAt(a,b,1);if(f){this.moveCursorTo(f.end.row,f.end.column);return}if(e=this.session.nonTokenRe.exec(d))b+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,d=c.substring(b);if(b>=c.length){this.moveCursorTo(a,c.length),this.moveCursorRight(),a<this.doc.getLength()-1&&this.moveCursorWordRight();return}if(e=this.session.tokenRe.exec(d))b+=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(a,b)},this.moveCursorLongWordLeft=function(){var a=this.lead.row,b=this.lead.column,c;if(c=this.session.getFoldAt(a,b,-1)){this.moveCursorTo(c.start.row,c.start.column);return}var d=this.session.getFoldStringAt(a,b,-1);d==null&&(d=this.doc.getLine(a).substring(0,b));var f=e.stringReverse(d),g;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;if(g=this.session.nonTokenRe.exec(f))b-=this.session.nonTokenRe.lastIndex,f=f.slice(this.session.nonTokenRe.lastIndex),this.session.nonTokenRe.lastIndex=0;if(b<=0){this.moveCursorTo(a,0),this.moveCursorLeft(),a>0&&this.moveCursorWordLeft();return}if(g=this.session.tokenRe.exec(f))b-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(a,b)},this.$shortWordEndIndex=function(a){var b,c=0,d,e=/\\s/,f=this.session.tokenRe;f.lastIndex=0;if(b=this.session.tokenRe.exec(a))c=this.session.tokenRe.lastIndex;else{while((d=a[c])&&e.test(d))c++;if(c<=1){f.lastIndex=0;while((d=a[c])&&!f.test(d)){f.lastIndex=0,c++;if(e.test(d)){if(c>2){c--;break}while((d=a[c])&&e.test(d))c++;if(c>2)break}}}}return f.lastIndex=0,c},this.moveCursorShortWordRight=function(){var a=this.lead.row,b=this.lead.column,c=this.doc.getLine(a),d=c.substring(b),e=this.session.getFoldAt(a,b,1);if(e)return this.moveCursorTo(e.end.row,e.end.column);if(b==c.length){var f=this.doc.getLength();do a++,d=this.doc.getLine(a);while(a<f&&/^\\s*$/.test(d));/^\\s+/.test(d)||(d=\"\"),b=0}var g=this.$shortWordEndIndex(d);this.moveCursorTo(a,b+g)},this.moveCursorShortWordLeft=function(){var a=this.lead.row,b=this.lead.column,c;if(c=this.session.getFoldAt(a,b,-1))return this.moveCursorTo(c.start.row,c.start.column);var d=this.session.getLine(a).substring(0,b);if(b==0){do a--,d=this.doc.getLine(a);while(a>0&&/^\\s*$/.test(d));b=d.length,/\\s+$/.test(d)||(d=\"\")}var f=e.stringReverse(d),g=this.$shortWordEndIndex(f);return this.moveCursorTo(a,b-g)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(a,b){var c=this.session.documentToScreenPosition(this.lead.row,this.lead.column);b===0&&(this.$desiredColumn?c.column=this.$desiredColumn:this.$desiredColumn=c.column);var d=this.session.screenToDocumentPosition(c.row+a,c.column);this.moveCursorTo(d.row,d.column+b,b===0)},this.moveCursorToPosition=function(a){this.moveCursorTo(a.row,a.column)},this.moveCursorTo=function(a,b,c){var d=this.session.getFoldAt(a,b,1);d&&(a=d.start.row,b=d.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(a,b),this.$keepDesiredColumnOnChange=!1,c||(this.$desiredColumn=null)},this.moveCursorToScreen=function(a,b,c){var d=this.session.screenToDocumentPosition(a,b);this.moveCursorTo(d.row,d.column,c)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(a){this.setSelectionRange(a,a.cursor==a.start),this.$desiredColumn=a.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(a){var b=this.getRange();return a?(a.start.column=b.start.column,a.start.row=b.start.row,a.end.column=b.end.column,a.end.row=b.end.row):a=b,a.cursor=this.isBackwards()?a.start:a.end,a.desiredColumn=this.$desiredColumn,a}}).call(h.prototype),b.Selection=h}),ace.define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=function(a,b,c,d){this.start={row:a,column:b},this.end={row:c,column:d}};(function(){this.isEqual=function(a){return this.start.row==a.start.row&&this.end.row==a.end.row&&this.start.column==a.start.column&&this.end.column==a.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(a,b){return this.compare(a,b)==0},this.compareRange=function(a){var b,c=a.end,d=a.start;return b=this.compare(c.row,c.column),b==1?(b=this.compare(d.row,d.column),b==1?2:b==0?1:0):b==-1?-2:(b=this.compare(d.row,d.column),b==-1?-1:b==1?42:0)},this.comparePoint=function(a){return this.compare(a.row,a.column)},this.containsRange=function(a){return this.comparePoint(a.start)==0&&this.comparePoint(a.end)==0},this.intersects=function(a){var b=this.compareRange(a);return b==-1||b==0||b==1},this.isEnd=function(a,b){return this.end.row==a&&this.end.column==b},this.isStart=function(a,b){return this.start.row==a&&this.start.column==b},this.setStart=function(a,b){typeof a==\"object\"?(this.start.column=a.column,this.start.row=a.row):(this.start.row=a,this.start.column=b)},this.setEnd=function(a,b){typeof a==\"object\"?(this.end.column=a.column,this.end.row=a.row):(this.end.row=a,this.end.column=b)},this.inside=function(a,b){return this.compare(a,b)==0?this.isEnd(a,b)||this.isStart(a,b)?!1:!0:!1},this.insideStart=function(a,b){return this.compare(a,b)==0?this.isEnd(a,b)?!1:!0:!1},this.insideEnd=function(a,b){return this.compare(a,b)==0?this.isStart(a,b)?!1:!0:!1},this.compare=function(a,b){return!this.isMultiLine()&&a===this.start.row?b<this.start.column?-1:b>this.end.column?1:0:a<this.start.row?-1:a>this.end.row?1:this.start.row===a?b>=this.start.column?0:-1:this.end.row===a?b<=this.end.column?0:1:0},this.compareStart=function(a,b){return this.start.row==a&&this.start.column==b?-1:this.compare(a,b)},this.compareEnd=function(a,b){return this.end.row==a&&this.end.column==b?1:this.compare(a,b)},this.compareInside=function(a,b){return this.end.row==a&&this.end.column==b?1:this.start.row==a&&this.start.column==b?-1:this.compare(a,b)},this.clipRows=function(a,b){if(this.end.row>b)var c={row:b+1,column:0};if(this.start.row>b)var e={row:b+1,column:0};if(this.start.row<a)var e={row:a,column:0};if(this.end.row<a)var c={row:a,column:0};return d.fromPoints(e||this.start,c||this.end)},this.extend=function(a,b){var c=this.compare(a,b);if(c==0)return this;if(c==-1)var e={row:a,column:b};else var f={row:a,column:b};return d.fromPoints(e||this.start,f||this.end)},this.isEmpty=function(){return this.start.row==this.end.row&&this.start.column==this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return d.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new d(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new d(this.start.row,0,this.end.row,0)},this.toScreenRange=function(a){var b=a.documentToScreenPosition(this.start),c=a.documentToScreenPosition(this.end);return new d(b.row,b.column,c.row,c.column)}}).call(d.prototype),d.fromPoints=function(a,b){return new d(a.row,a.column,b.row,b.column)},b.Range=d}),ace.define(\"ace/mode/text\",[\"require\",\"exports\",\"module\",\"ace/tokenizer\",\"ace/mode/text_highlight_rules\",\"ace/mode/behaviour\",\"ace/unicode\"],function(a,b,c){var d=a(\"../tokenizer\").Tokenizer,e=a(\"./text_highlight_rules\").TextHighlightRules,f=a(\"./behaviour\").Behaviour,g=a(\"../unicode\"),h=function(){this.$tokenizer=new d((new e).getRules()),this.$behaviour=new f};(function(){this.tokenRe=new RegExp(\"^[\"+g.packages.L+g.packages.Mn+g.packages.Mc+g.packages.Nd+g.packages.Pc+\"\\\\$_]+\",\"g\"),this.nonTokenRe=new RegExp(\"^(?:[^\"+g.packages.L+g.packages.Mn+g.packages.Mc+g.packages.Nd+g.packages.Pc+\"\\\\$_]|s])+\",\"g\"),this.getTokenizer=function(){return this.$tokenizer},this.toggleCommentLines=function(a,b,c,d){},this.getNextLineIndent=function(a,b,c){return\"\"},this.checkOutdent=function(a,b,c){return!1},this.autoOutdent=function(a,b,c){},this.$getIndent=function(a){var b=a.match(/^(\\s+)/);return b?b[1]:\"\"},this.createWorker=function(a){return null},this.createModeDelegates=function(a){if(!this.$embeds)return;this.$modes={};for(var b=0;b<this.$embeds.length;b++)a[this.$embeds[b]]&&(this.$modes[this.$embeds[b]]=new a[this.$embeds[b]]);var c=[\"toggleCommentLines\",\"getNextLineIndent\",\"checkOutdent\",\"autoOutdent\",\"transformAction\"];for(var b=0;b<c.length;b++)(function(a){var d=c[b],e=a[d];a[c[b]]=function(){return this.$delegator(d,arguments,e)}})(this)},this.$delegator=function(a,b,c){var d=b[0];for(var e=0;e<this.$embeds.length;e++){if(!this.$modes[this.$embeds[e]])continue;var f=d.split(this.$embeds[e]);if(!f[0]&&f[1]){b[0]=f[1];var g=this.$modes[this.$embeds[e]];return g[a].apply(g,b)}}var h=c.apply(this,b);return c?h:undefined},this.transformAction=function(a,b,c,d,e){if(this.$behaviour){var f=this.$behaviour.getBehaviours();for(var g in f)if(f[g][b]){var h=f[g][b].apply(this,arguments);if(h)return h}}}}).call(h.prototype),b.Mode=h}),ace.define(\"ace/tokenizer\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=function(a,b){b=b?\"g\"+b:\"g\",this.rules=a,this.regExps={},this.matchMappings={};for(var c in this.rules){var d=this.rules[c],e=d,f=[],g=0,h=this.matchMappings[c]={};for(var i=0;i<e.length;i++){e[i].regex instanceof RegExp&&(e[i].regex=e[i].regex.toString().slice(1,-1));var j=(new RegExp(\"(?:(\"+e[i].regex+\")|(.))\")).exec(\"a\").length-2,k=e[i].regex.replace(/\\\\([0-9]+)/g,function(a,b){return\"\\\\\"+(parseInt(b,10)+g+1)});if(j>1&&e[i].token.length!==j-1)throw new Error(\"Matching groups and length of the token array don't match in rule #\"+i+\" of state \"+c);h[g]={rule:i,len:j},g+=j,f.push(k)}this.regExps[c]=new RegExp(\"(?:(\"+f.join(\")|(\")+\")|(.))\",b)}};(function(){this.getLineTokens=function(a,b){var c=b||\"start\",d=this.rules[c],e=this.matchMappings[c],f=this.regExps[c];f.lastIndex=0;var g,h=[],i=0,j={type:null,value:\"\"};while(g=f.exec(a)){var k=\"text\",l=null,m=[g[0]];for(var n=0;n<g.length-2;n++){if(g[n+1]===undefined)continue;l=d[e[n].rule],e[n].len>1&&(m=g.slice(n+2,n+1+e[n].len)),typeof l.token==\"function\"?k=l.token.apply(this,m):k=l.token,l.next&&(c=l.next,d=this.rules[c],e=this.matchMappings[c],i=f.lastIndex,f=this.regExps[c],f.lastIndex=i);break}if(m[0]){typeof k==\"string\"&&(m=[m.join(\"\")],k=[k]);for(var n=0;n<m.length;n++){if(!m[n])continue;(!l||l.merge||k[n]===\"text\")&&j.type===k[n]?j.value+=m[n]:(j.type&&h.push(j),j={type:k[n],value:m[n]})}}if(i==a.length)break;i=f.lastIndex}return j.type&&h.push(j),{tokens:h,state:c}}}).call(d.prototype),b.Tokenizer=d}),ace.define(\"ace/mode/text_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\"],function(a,b,c){var d=a(\"../lib/lang\"),e=function(){this.$rules={start:[{token:\"empty_line\",regex:\"^$\"},{token:\"text\",regex:\".+\"}]}};(function(){this.addRules=function(a,b){for(var c in a){var d=a[c];for(var e=0;e<d.length;e++){var f=d[e];f.next&&(f.next=b+f.next)}this.$rules[b+c]=d}},this.getRules=function(){return this.$rules},this.embedRules=function(a,b,c,e){var f=(new a).getRules();if(e)for(var g=0;g<e.length;g++)e[g]=b+e[g];else{e=[];for(var h in f)e.push(b+h)}this.addRules(f,b);for(var g=0;g<e.length;g++)Array.prototype.unshift.apply(this.$rules[e[g]],d.deepCopy(c));this.$embeds||(this.$embeds=[]),this.$embeds.push(b)},this.getEmbeds=function(){return this.$embeds}}).call(e.prototype),b.TextHighlightRules=e}),ace.define(\"ace/mode/behaviour\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=function(){this.$behaviours={}};(function(){this.add=function(a,b,c){switch(undefined){case this.$behaviours:this.$behaviours={};case this.$behaviours[a]:this.$behaviours[a]={}}this.$behaviours[a][b]=c},this.addBehaviours=function(a){for(var b in a)for(var c in a[b])this.add(b,c,a[b][c])},this.remove=function(a){this.$behaviours&&this.$behaviours[a]&&delete this.$behaviours[a]},this.inherit=function(a,b){if(typeof a==\"function\")var c=(new a).getBehaviours(b);else var c=a.getBehaviours(b);this.addBehaviours(c)},this.getBehaviours=function(a){if(!a)return this.$behaviours;var b={};for(var c=0;c<a.length;c++)this.$behaviours[a[c]]&&(b[a[c]]=this.$behaviours[a[c]]);return b}}).call(d.prototype),b.Behaviour=d}),ace.define(\"ace/unicode\",[\"require\",\"exports\",\"module\"],function(a,b,c){function d(a){var c=/\\w{4}/g;for(var d in a)b.packages[d]=a[d].replace(c,\"\\\\u$&\")}b.packages={},d({L:\"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",Ll:\"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A\",Lu:\"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A\",Lt:\"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC\",Lm:\"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F\",Lo:\"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",M:\"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26\",Mn:\"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26\",Mc:\"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC\",Me:\"0488048906DE20DD-20E020E2-20E4A670-A672\",N:\"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",Nd:\"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",Nl:\"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF\",No:\"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835\",P:\"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65\",Pd:\"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D\",Ps:\"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62\",Pe:\"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63\",Pi:\"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20\",Pf:\"00BB2019201D203A2E032E052E0A2E0D2E1D2E21\",Pc:\"005F203F20402054FE33FE34FE4D-FE4FFF3F\",Po:\"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65\",S:\"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD\",Sm:\"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC\",Sc:\"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6\",Sk:\"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3\",So:\"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD\",Z:\"002000A01680180E2000-200A20282029202F205F3000\",Zs:\"002000A01680180E2000-200A202F205F3000\",Zl:\"2028\",Zp:\"2029\",C:\"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF\",Cc:\"0000-001F007F-009F\",Cf:\"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB\",Co:\"E000-F8FF\",Cs:\"D800-DFFF\",Cn:\"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF\"})}),ace.define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(a,b,c){var d=a(\"./lib/oop\"),e=a(\"./lib/event_emitter\").EventEmitter,f=a(\"./range\").Range,g=a(\"./anchor\").Anchor,h=function(a){this.$lines=[],a.length==0?this.$lines=[\"\"]:Array.isArray(a)?this.insertLines(0,a):this.insert({row:0,column:0},a)};(function(){d.implement(this,e),this.setValue=function(a){var b=this.getLength();this.remove(new f(0,0,b,this.getLine(b-1).length)),this.insert({row:0,column:0},a)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(a,b){return new g(this,a,b)},\"aaa\".split(/a/).length==0?this.$split=function(a){return a.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:this.$split=function(a){return a.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(a){var b=a.match(/^.*?(\\r\\n|\\r|\\n)/m);b?this.$autoNewLine=b[1]:this.$autoNewLine=\"\\n\"},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";case\"auto\":return this.$autoNewLine}},this.$autoNewLine=\"\\n\",this.$newLineMode=\"auto\",this.setNewLineMode=function(a){if(this.$newLineMode===a)return;this.$newLineMode=a},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(a){return a==\"\\r\\n\"||a==\"\\r\"||a==\"\\n\"},this.getLine=function(a){return this.$lines[a]||\"\"},this.getLines=function(a,b){return this.$lines.slice(a,b+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(a){if(a.start.row==a.end.row)return this.$lines[a.start.row].substring(a.start.column,a.end.column);var b=this.getLines(a.start.row+1,a.end.row-1);return b.unshift((this.$lines[a.start.row]||\"\").substring(a.start.column)),b.push((this.$lines[a.end.row]||\"\").substring(0,a.end.column)),b.join(this.getNewLineCharacter())},this.$clipPosition=function(a){var b=this.getLength();return a.row>=b&&(a.row=Math.max(0,b-1),a.column=this.getLine(b-1).length),a},this.insert=function(a,b){if(!b||b.length===0)return a;a=this.$clipPosition(a),this.getLength()<=1&&this.$detectNewLine(b);var c=this.$split(b),d=c.splice(0,1)[0],e=c.length==0?null:c.splice(c.length-1,1)[0];return a=this.insertInLine(a,d),e!==null&&(a=this.insertNewLine(a),a=this.insertLines(a.row,c),a=this.insertInLine(a,e||\"\")),a},this.insertLines=function(a,b){if(b.length==0)return{row:a,column:0};if(b.length>65535){var c=this.insertLines(a,b.slice(65535));b=b.slice(0,65535)}var d=[a,0];d.push.apply(d,b),this.$lines.splice.apply(this.$lines,d);var e=new f(a,0,a+b.length,0),g={action:\"insertLines\",range:e,lines:b};return this._emit(\"change\",{data:g}),c||e.end},this.insertNewLine=function(a){a=this.$clipPosition(a);var b=this.$lines[a.row]||\"\";this.$lines[a.row]=b.substring(0,a.column),this.$lines.splice(a.row+1,0,b.substring(a.column,b.length));var c={row:a.row+1,column:0},d={action:\"insertText\",range:f.fromPoints(a,c),text:this.getNewLineCharacter()};return this._emit(\"change\",{data:d}),c},this.insertInLine=function(a,b){if(b.length==0)return a;var c=this.$lines[a.row]||\"\";this.$lines[a.row]=c.substring(0,a.column)+b+c.substring(a.column);var d={row:a.row,column:a.column+b.length},e={action:\"insertText\",range:f.fromPoints(a,d),text:b};return this._emit(\"change\",{data:e}),d},this.remove=function(a){a.start=this.$clipPosition(a.start),a.end=this.$clipPosition(a.end);if(a.isEmpty())return a.start;var b=a.start.row,c=a.end.row;if(a.isMultiLine()){var d=a.start.column==0?b:b+1,e=c-1;a.end.column>0&&this.removeInLine(c,0,a.end.column),e>=d&&this.removeLines(d,e),d!=b&&(this.removeInLine(b,a.start.column,this.getLine(b).length),this.removeNewLine(a.start.row))}else this.removeInLine(b,a.start.column,a.end.column);return a.start},this.removeInLine=function(a,b,c){if(b==c)return;var d=new f(a,b,a,c),e=this.getLine(a),g=e.substring(b,c),h=e.substring(0,b)+e.substring(c,e.length);this.$lines.splice(a,1,h);var i={action:\"removeText\",range:d,text:g};return this._emit(\"change\",{data:i}),d.start},this.removeLines=function(a,b){var c=new f(a,0,b+1,0),d=this.$lines.splice(a,b-a+1),e={action:\"removeLines\",range:c,nl:this.getNewLineCharacter(),lines:d};return this._emit(\"change\",{data:e}),d},this.removeNewLine=function(a){var b=this.getLine(a),c=this.getLine(a+1),d=new f(a,b.length,a+1,0),e=b+c;this.$lines.splice(a,2,e);var g={action:\"removeText\",range:d,text:this.getNewLineCharacter()};this._emit(\"change\",{data:g})},this.replace=function(a,b){if(b.length==0&&a.isEmpty())return a.start;if(b==this.getTextRange(a))return a.end;this.remove(a);if(b)var c=this.insert(a.start,b);else c=a.start;return c},this.applyDeltas=function(a){for(var b=0;b<a.length;b++){var c=a[b],d=f.fromPoints(c.range.start,c.range.end);c.action==\"insertLines\"?this.insertLines(d.start.row,c.lines):c.action==\"insertText\"?this.insert(d.start,c.text):c.action==\"removeLines\"?this.removeLines(d.start.row,d.end.row-1):c.action==\"removeText\"&&this.remove(d)}},this.revertDeltas=function(a){for(var b=a.length-1;b>=0;b--){var c=a[b],d=f.fromPoints(c.range.start,c.range.end);c.action==\"insertLines\"?this.removeLines(d.start.row,d.end.row-1):c.action==\"insertText\"?this.remove(d):c.action==\"removeLines\"?this.insertLines(d.start.row,c.lines):c.action==\"removeText\"&&this.insert(d.start,c.text)}}}).call(h.prototype),b.Document=h}),ace.define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(a,b,c){var d=a(\"./lib/oop\"),e=a(\"./lib/event_emitter\").EventEmitter,f=b.Anchor=function(a,b,c){this.document=a,typeof c==\"undefined\"?this.setPosition(b.row,b.column):this.setPosition(b,c),this.$onChange=this.onChange.bind(this),a.on(\"change\",this.$onChange)};(function(){d.implement(this,e),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.onChange=function(a){var b=a.data,c=b.range;if(c.start.row==c.end.row&&c.start.row!=this.row)return;if(c.start.row>this.row)return;if(c.start.row==this.row&&c.start.column>this.column)return;var d=this.row,e=this.column;b.action===\"insertText\"?c.start.row===d&&c.start.column<=e?c.start.row===c.end.row?e+=c.end.column-c.start.column:(e-=c.start.column,d+=c.end.row-c.start.row):c.start.row!==c.end.row&&c.start.row<d&&(d+=c.end.row-c.start.row):b.action===\"insertLines\"?c.start.row<=d&&(d+=c.end.row-c.start.row):b.action==\"removeText\"?c.start.row==d&&c.start.column<e?c.end.column>=e?e=c.start.column:e=Math.max(0,e-(c.end.column-c.start.column)):c.start.row!==c.end.row&&c.start.row<d?(c.end.row==d&&(e=Math.max(0,e-c.end.column)+c.start.column),d-=c.end.row-c.start.row):c.end.row==d&&(d-=c.end.row-c.start.row,e=Math.max(0,e-c.end.column)+c.start.column):b.action==\"removeLines\"&&c.start.row<=d&&(c.end.row<=d?d-=c.end.row-c.start.row:(d=c.start.row,e=0)),this.setPosition(d,e,!0)},this.setPosition=function(a,b,c){var d;c?d={row:a,column:b}:d=this.$clipPositionToDocument(a,b);if(this.row==d.row&&this.column==d.column)return;var e={row:this.row,column:this.column};this.row=d.row,this.column=d.column,this._emit(\"change\",{old:e,value:d})},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.$clipPositionToDocument=function(a,b){var c={};return a>=this.document.getLength()?(c.row=Math.max(0,this.document.getLength()-1),c.column=this.document.getLine(c.row).length):a<0?(c.row=0,c.column=0):(c.row=a,c.column=Math.min(this.document.getLine(c.row).length,Math.max(0,b))),b<0&&(c.column=0),c}}).call(f.prototype)}),ace.define(\"ace/background_tokenizer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(a,b,c){var d=a(\"./lib/oop\"),e=a(\"./lib/event_emitter\").EventEmitter,f=5e3,g=function(a,b){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=a;var c=this;this.$worker=function(){if(!c.running)return;var a=new Date,b=c.currentLine,d=c.doc,e=0,f=d.getLength();while(c.currentLine<f){c.$tokenizeRow(c.currentLine);while(c.lines[c.currentLine])c.currentLine++;e++;if(e%5==0&&new Date-a>20){c.fireUpdateEvent(b,c.currentLine-1),c.running=setTimeout(c.$worker,20);return}}c.running=!1,c.fireUpdateEvent(b,f-1)}};(function(){d.implement(this,e),this.setTokenizer=function(a){this.tokenizer=a,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(a){this.doc=a,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(a,b){var c={first:a,last:b};this._emit(\"update\",{data:c})},this.start=function(a){this.currentLine=Math.min(a||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.$updateOnChange=function(a){var b=a.range,c=b.start.row,d=b.end.row-c;if(d===0)this.lines[c]=null;else if(a.action==\"removeText\"||a.action==\"removeLines\")this.lines.splice(c,d+1,null),this.states.splice(c,d+1,null);else{var e=Array(d+1);e.unshift(c,1),this.lines.splice.apply(this.lines,e),this.states.splice.apply(this.states,e)}this.currentLine=Math.min(c,this.currentLine,this.doc.getLength()),this.stop(),this.running=setTimeout(this.$worker,700)},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(a){return this.lines[a]||this.$tokenizeRow(a)},this.getState=function(a){return this.currentLine==a&&this.$tokenizeRow(a),this.states[a]||\"start\"},this.$tokenizeRow=function(a){var b=this.doc.getLine(a),c=this.states[a-1];if(b.length>f){var d={value:b.substr(f),type:\"text\"};b=b.slice(0,f)}var e=this.tokenizer.getLineTokens(b,c);return d&&(e.tokens.push(d),e.state=\"start\"),this.states[a]!==e.state?(this.states[a]=e.state,this.lines[a+1]=null,this.currentLine>a+1&&(this.currentLine=a+1)):this.currentLine==a&&(this.currentLine=a+1),this.lines[a]=e.tokens}}).call(g.prototype),b.BackgroundTokenizer=g}),ace.define(\"ace/search_highlight\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"],function(a,b,c){var d=a(\"./lib/lang\"),e=a(\"./lib/oop\"),f=a(\"./range\").Range,g=function(a,b,c){this.setRegexp(a),this.clazz=b,this.type=c||\"text\"};(function(){this.setRegexp=function(a){if(this.regExp+\"\"==a+\"\")return;this.regExp=a,this.cache=[]},this.update=function(a,b,c,e){if(!this.regExp)return;var g=e.firstRow,h=e.lastRow;for(var i=g;i<=h;i++){var j=this.cache[i];j==null&&(j=d.getMatchOffsets(c.getLine(i),this.regExp),j=j.map(function(a){return new f(i,a.offset,i,a.offset+a.length)}),this.cache[i]=j.length?j:\"\");for(var k=j.length;k--;)b.drawSingleLineMarker(a,j[k].toScreenRange(c),this.clazz,e,null,this.type)}}}).call(g.prototype),b.SearchHighlight=g}),ace.define(\"ace/edit_session/folding\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/edit_session/fold_line\",\"ace/edit_session/fold\",\"ace/token_iterator\"],function(a,b,c){function h(){this.getFoldAt=function(a,b,c){var d=this.getFoldLine(a);if(!d)return null;var e=d.folds;for(var f=0;f<e.length;f++){var g=e[f];if(g.range.contains(a,b)){if(c==1&&g.range.isEnd(a,b))continue;if(c==-1&&g.range.isStart(a,b))continue;return g}}},this.getFoldsInRange=function(a){a=a.clone();var b=a.start,c=a.end,d=this.$foldData,e=[];b.column+=1,c.column-=1;for(var f=0;f<d.length;f++){var g=d[f].range.compareRange(a);if(g==2)continue;if(g==-2)break;var h=d[f].folds;for(var i=0;i<h.length;i++){var j=h[i];g=j.range.compareRange(a);if(g==-2)break;if(g==2)continue;if(g==42)break;e.push(j)}}return e},this.getAllFolds=function(){function c(b){a.push(b);if(!b.subFolds)return;for(var d=0;d<b.subFolds.length;d++)c(b.subFolds[d])}var a=[],b=this.$foldData;for(var d=0;d<b.length;d++)for(var e=0;e<b[d].folds.length;e++)c(b[d].folds[e]);return a},this.getFoldStringAt=function(a,b,c,d){d=d||this.getFoldLine(a);if(!d)return null;var e={end:{column:0}},f,g;for(var h=0;h<d.folds.length;h++){g=d.folds[h];var i=g.range.compareEnd(a,b);if(i==-1){f=this.getLine(g.start.row).substring(e.end.column,g.start.column);break}if(i===0)return null;e=g}return f||(f=this.getLine(g.start.row).substring(e.end.column)),c==-1?f.substring(0,b-e.end.column):c==1?f.substring(b-e.end.column):f},this.getFoldLine=function(a,b){var c=this.$foldData,d=0;b&&(d=c.indexOf(b)),d==-1&&(d=0);for(d;d<c.length;d++){var e=c[d];if(e.start.row<=a&&e.end.row>=a)return e;if(e.end.row>a)return null}return null},this.getNextFoldLine=function(a,b){var c=this.$foldData,d=0;b&&(d=c.indexOf(b)),d==-1&&(d=0);for(d;d<c.length;d++){var e=c[d];if(e.end.row>=a)return e}return null},this.getFoldedRowCount=function(a,b){var c=this.$foldData,d=b-a+1;for(var e=0;e<c.length;e++){var f=c[e],g=f.end.row,h=f.start.row;if(g>=b){h<b&&(h>=a?d-=b-h:d=0);break}g>=a&&(h>=a?d-=g-h:d-=g-a+1)}return d},this.$addFoldLine=function(a){return this.$foldData.push(a),this.$foldData.sort(function(a,b){return a.start.row-b.start.row}),a},this.addFold=function(a,b){var c=this.$foldData,d=!1,g;a instanceof f?g=a:g=new f(b,a),this.$clipRangeToDocument(g.range);var h=g.start.row,i=g.start.column,j=g.end.row,k=g.end.column;if(g.placeholder.length<2)throw\"Placeholder has to be at least 2 characters\";if(h==j&&k-i<2)throw\"The range has to be at least 2 characters width\";var l=this.getFoldAt(h,i,1),m=this.getFoldAt(j,k,-1);if(l&&m==l)return l.addSubFold(g);if(l&&!l.range.isStart(h,i)||m&&!m.range.isEnd(j,k))throw\"A fold can't intersect already existing fold\"+g.range+l.range;var n=this.getFoldsInRange(g.range);n.length>0&&(this.removeFolds(n),g.subFolds=n);for(var o=0;o<c.length;o++){var p=c[o];if(j==p.start.row){p.addFold(g),d=!0;break}if(h==p.end.row){p.addFold(g),d=!0;if(!g.sameRow){var q=c[o+1];if(q&&q.start.row==j){p.merge(q);break}}break}if(j<=p.start.row)break}return d||(p=this.$addFoldLine(new e(this.$foldData,g))),this.$useWrapMode?this.$updateWrapData(p.start.row,p.start.row):this.$updateRowLengthCache(p.start.row,p.start.row),this.$modified=!0,this._emit(\"changeFold\",{data:g}),g},this.addFolds=function(a){a.forEach(function(a){this.addFold(a)},this)},this.removeFold=function(a){var b=a.foldLine,c=b.start.row,d=b.end.row,e=this.$foldData,f=b.folds;if(f.length==1)e.splice(e.indexOf(b),1);else if(b.range.isEnd(a.end.row,a.end.column))f.pop(),b.end.row=f[f.length-1].end.row,b.end.column=f[f.length-1].end.column;else if(b.range.isStart(a.start.row,a.start.column))f.shift(),b.start.row=f[0].start.row,b.start.column=f[0].start.column;else if(a.sameRow)f.splice(f.indexOf(a),1);else{var g=b.split(a.start.row,a.start.column);f=g.folds,f.shift(),g.start.row=f[0].start.row,g.start.column=f[0].start.column}this.$useWrapMode?this.$updateWrapData(c,d):this.$updateRowLengthCache(c,d),this.$modified=!0,this._emit(\"changeFold\",{data:a})},this.removeFolds=function(a){var b=[];for(var c=0;c<a.length;c++)b.push(a[c]);b.forEach(function(a){this.removeFold(a)},this),this.$modified=!0},this.expandFold=function(a){this.removeFold(a),a.subFolds.forEach(function(a){this.addFold(a)},this),a.subFolds=[]},this.expandFolds=function(a){a.forEach(function(a){this.expandFold(a)},this)},this.unfold=function(a,b){var c,e;a==null?c=new d(0,0,this.getLength(),0):typeof a==\"number\"?c=new d(a,0,a,this.getLine(a).length):\"row\"in a?c=d.fromPoints(a,a):c=a,e=this.getFoldsInRange(c);if(b)this.removeFolds(e);else while(e.length)this.expandFolds(e),e=this.getFoldsInRange(c)},this.isRowFolded=function(a,b){return!!this.getFoldLine(a,b)},this.getRowFoldEnd=function(a,b){var c=this.getFoldLine(a,b);return c?c.end.row:a},this.getFoldDisplayLine=function(a,b,c,d,e){d==null&&(d=a.start.row,e=0),b==null&&(b=a.end.row,c=this.getLine(b).length);var f=this.doc,g=\"\";return a.walk(function(a,b,c,h){if(b<d)return;if(b==d){if(c<e)return;h=Math.max(e,h)}a?g+=a:g+=f.getLine(b).substring(h,c)}.bind(this),b,c),g},this.getDisplayLine=function(a,b,c,d){var e=this.getFoldLine(a);if(!e){var f;return f=this.doc.getLine(a),f.substring(d||0,b||f.length)}return this.getFoldDisplayLine(e,a,b,c,d)},this.$cloneFoldData=function(){var a=[];return a=this.$foldData.map(function(b){var c=b.folds.map(function(a){return a.clone()});return new e(a,c)}),a},this.toggleFold=function(a){var b=this.selection,c=b.getRange(),d,e;if(c.isEmpty()){var f=c.start;d=this.getFoldAt(f.row,f.column);if(d){this.expandFold(d);return}(e=this.findMatchingBracket(f))?c.comparePoint(e)==1?c.end=e:(c.start=e,c.start.column++,c.end.column--):(e=this.findMatchingBracket({row:f.row,column:f.column+1}))?(c.comparePoint(e)==1?c.end=e:c.start=e,c.start.column++):c=this.getCommentFoldRange(f.row,f.column)||c}else{var g=this.getFoldsInRange(c);if(a&&g.length){this.expandFolds(g);return}g.length==1&&(d=g[0])}d||(d=this.getFoldAt(c.start.row,c.start.column));if(d&&d.range.toString()==c.toString()){this.expandFold(d);return}var h=\"...\";if(!c.isMultiLine()){h=this.getTextRange(c);if(h.length<4)return;h=h.trim().substring(0,2)+\"..\"}this.addFold(h,c)},this.getCommentFoldRange=function(a,b){var c=new g(this,a,b),e=c.getCurrentToken();if(e&&/^comment|string/.test(e.type)){var f=new d,h=new RegExp(e.type.replace(/\\..*/,\"\\\\.\"));do e=c.stepBackward();while(e&&h.test(e.type));c.stepForward(),f.start.row=c.getCurrentTokenRow(),f.start.column=c.getCurrentTokenColumn()+2,c=new g(this,a,b);do e=c.stepForward();while(e&&h.test(e.type));return e=c.stepBackward(),f.end.row=c.getCurrentTokenRow(),f.end.column=c.getCurrentTokenColumn()+e.value.length,f}},this.foldAll=function(a,b){var c=this.foldWidgets;b=b||this.getLength();for(var d=a||0;d<b;d++){c[d]==null&&(c[d]=this.getFoldWidget(d));if(c[d]!=\"start\")continue;var e=this.getFoldWidgetRange(d);if(e&&e.end.row<b)try{this.addFold(\"...\",e)}catch(f){}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle=\"markbegin\",this.setFoldStyle=function(a){if(!this.$foldStyles[a])throw new Error(\"invalid fold style: \"+a+\"[\"+Object.keys(this.$foldStyles).join(\", \")+\"]\");if(this.$foldStyle==a)return;this.$foldStyle=a,a==\"manual\"&&this.unfold();var b=this.$foldMode;this.$setFolding(null),this.$setFolding(b)},this.$setFolding=function(a){if(this.$foldMode==a)return;this.$foldMode=a,this.removeListener(\"change\",this.$updateFoldWidgets),this._emit(\"changeAnnotation\");if(!a||this.$foldStyle==\"manual\"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=a.getFoldWidget.bind(a,this,this.$foldStyle),this.getFoldWidgetRange=a.getFoldWidgetRange.bind(a,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.on(\"change\",this.$updateFoldWidgets)},this.onFoldWidgetClick=function(a,b){var c=this.getFoldWidget(a),d=this.getLine(a),e=b.shiftKey,f=e||b.ctrlKey||b.altKey||b.metaKey,g;c==\"end\"?g=this.getFoldAt(a,0,-1):g=this.getFoldAt(a,d.length,1);if(g){f?this.removeFold(g):this.expandFold(g);return}var h=this.getFoldWidgetRange(a);if(h){if(!h.isMultiLine()){g=this.getFoldAt(h.start.row,h.start.column,1);if(g&&h.isEqual(g.range)){this.removeFold(g);return}}e||this.addFold(\"...\",h),f&&this.foldAll(h.start.row+1,h.end.row)}else f&&this.foldAll(a+1,this.getLength()),(b.target||b.srcElement).className+=\" invalid\"},this.updateFoldWidgets=function(a){var b=a.data,c=b.range,d=c.start.row,e=c.end.row-d;if(e===0)this.foldWidgets[d]=null;else if(b.action==\"removeText\"||b.action==\"removeLines\")this.foldWidgets.splice(d,e+1,null);else{var f=Array(e+1);f.unshift(d,1),this.foldWidgets.splice.apply(this.foldWidgets,f)}}}var d=a(\"../range\").Range,e=a(\"./fold_line\").FoldLine,f=a(\"./fold\").Fold,g=a(\"../token_iterator\").TokenIterator;b.Folding=h}),ace.define(\"ace/edit_session/fold_line\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(a,b,c){function e(a,b){this.foldData=a,Array.isArray(b)?this.folds=b:b=this.folds=[b];var c=b[b.length-1];this.range=new d(b[0].start.row,b[0].start.column,c.end.row,c.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(a){a.setFoldLine(this)},this)}var d=a(\"../range\").Range;(function(){this.shiftRow=function(a){this.start.row+=a,this.end.row+=a,this.folds.forEach(function(b){b.start.row+=a,b.end.row+=a})},this.addFold=function(a){if(a.sameRow){if(a.start.row<this.startRow||a.endRow>this.endRow)throw\"Can't add a fold to this FoldLine as it has no connection\";this.folds.push(a),this.folds.sort(function(a,b){return-a.range.compareEnd(b.start.row,b.start.column)}),this.range.compareEnd(a.start.row,a.start.column)>0?(this.end.row=a.end.row,this.end.column=a.end.column):this.range.compareStart(a.end.row,a.end.column)<0&&(this.start.row=a.start.row,this.start.column=a.start.column)}else if(a.start.row==this.end.row)this.folds.push(a),this.end.row=a.end.row,this.end.column=a.end.column;else{if(a.end.row!=this.start.row)throw\"Trying to add fold to FoldRow that doesn't have a matching row\";this.folds.unshift(a),this.start.row=a.start.row,this.start.column=a.start.column}a.foldLine=this},this.containsRow=function(a){return a>=this.start.row&&a<=this.end.row},this.walk=function(a,b,c){var d=0,e=this.folds,f,g,h,i=!0;b==null&&(b=this.end.row,c=this.end.column);for(var j=0;j<e.length;j++){f=e[j],g=f.range.compareStart(b,c);if(g==-1){a(null,b,c,d,i);return}h=a(null,f.start.row,f.start.column,d,i),h=!h&&a(f.placeholder,f.start.row,f.start.column,d);if(h||g==0)return;i=!f.sameRow,d=f.end.column}a(null,b,c,d,i)},this.getNextFoldTo=function(a,b){var c,d;for(var e=0;e<this.folds.length;e++){c=this.folds[e],d=c.range.compareEnd(a,b);if(d==-1)return{fold:c,kind:\"after\"};if(d==0)return{fold:c,kind:\"inside\"}}return null},this.addRemoveChars=function(a,b,c){var d=this.getNextFoldTo(a,b),e,f;if(d){e=d.fold;if(d.kind==\"inside\"&&e.start.column!=b&&e.start.row!=a)window.console&&window.console.log(a,b,e);else if(e.start.row==a){f=this.folds;var g=f.indexOf(e);g==0&&(this.start.column+=c);for(g;g<f.length;g++){e=f[g],e.start.column+=c;if(!e.sameRow)return;e.end.column+=c}this.end.column+=c}}},this.split=function(a,b){var c=this.getNextFoldTo(a,b).fold,d=this.folds,f=this.foldData;if(!c)return null;var g=d.indexOf(c),h=d[g-1];this.end.row=h.end.row,this.end.column=h.end.column,d=d.splice(g,d.length-g);var i=new e(f,d);return f.splice(f.indexOf(this)+1,0,i),i},this.merge=function(a){var b=a.folds;for(var c=0;c<b.length;c++)this.addFold(b[c]);var d=this.foldData;d.splice(d.indexOf(a),1)},this.toString=function(){var a=[this.range.toString()+\": [\"];return this.folds.forEach(function(b){a.push(\"  \"+b.toString())}),a.push(\"]\"),a.join(\"\\n\")},this.idxToPosition=function(a){var b=0,c;for(var d=0;d<this.folds.length;d++){var c=this.folds[d];a-=c.start.column-b;if(a<0)return{row:c.start.row,column:c.start.column+a};a-=c.placeholder.length;if(a<0)return c.start;b=c.end.column}return{row:this.end.row,column:this.end.column+a}}}).call(e.prototype),b.FoldLine=e}),ace.define(\"ace/edit_session/fold\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=b.Fold=function(a,b){this.foldLine=null,this.placeholder=b,this.range=a,this.start=a.start,this.end=a.end,this.sameRow=a.start.row==a.end.row,this.subFolds=[]};(function(){this.toString=function(){return'\"'+this.placeholder+'\" '+this.range.toString()},this.setFoldLine=function(a){this.foldLine=a,this.subFolds.forEach(function(b){b.setFoldLine(a)})},this.clone=function(){var a=this.range.clone(),b=new d(a,this.placeholder);return this.subFolds.forEach(function(a){b.subFolds.push(a.clone())}),b},this.addSubFold=function(a){if(this.range.isEqual(a))return this;if(!this.range.containsRange(a))throw\"A fold can't intersect already existing fold\"+a.range+this.range;var b=a.range.start.row,c=a.range.start.column;for(var d=0,e=-1;d<this.subFolds.length;d++){e=this.subFolds[d].range.compare(b,c);if(e!=1)break}var f=this.subFolds[d];if(e==0)return f.addSubFold(a);var b=a.range.end.row,c=a.range.end.column;for(var g=d,e=-1;g<this.subFolds.length;g++){e=this.subFolds[g].range.compare(b,c);if(e!=1)break}var h=this.subFolds[g];if(e==0)throw\"A fold can't intersect already existing fold\"+a.range+this.range;var i=this.subFolds.splice(d,g-d,a);return a.setFoldLine(this.foldLine),a}}).call(d.prototype)}),ace.define(\"ace/token_iterator\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=function(a,b,c){this.$session=a,this.$row=b,this.$rowTokens=a.getTokens(b);var d=a.getTokenAt(b,c);this.$tokenIndex=d?d.index:-1};(function(){this.stepBackward=function(){this.$tokenIndex-=1;while(this.$tokenIndex<0){this.$row-=1;if(this.$row<0)return this.$row=0,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=this.$rowTokens.length-1}return this.$rowTokens[this.$tokenIndex]},this.stepForward=function(){var a=this.$session.getLength();this.$tokenIndex+=1;while(this.$tokenIndex>=this.$rowTokens.length){this.$row+=1;if(this.$row>=a)return this.$row=a-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var a=this.$rowTokens,b=this.$tokenIndex,c=a[b].start;if(c!==undefined)return c;c=0;while(b>0)b-=1,c+=a[b].value.length;return c}}).call(d.prototype),b.TokenIterator=d}),ace.define(\"ace/edit_session/bracket_match\",[\"require\",\"exports\",\"module\",\"ace/token_iterator\",\"ace/range\"],function(a,b,c){function f(){this.findMatchingBracket=function(a){if(a.column==0)return null;var b=this.getLine(a.row).charAt(a.column-1);if(b==\"\")return null;var c=b.match(/([\\(\\[\\{])|([\\)\\]\\}])/);return c?c[1]?this.$findClosingBracket(c[1],a):this.$findOpeningBracket(c[2],a):null},this.getBracketRange=function(a){var b=this.getLine(a.row),c=!0,d,f=b.charAt(a.column-1),g=f&&f.match(/([\\(\\[\\{])|([\\)\\]\\}])/);g||(f=b.charAt(a.column),a={row:a.row,column:a.column+1},g=f&&f.match(/([\\(\\[\\{])|([\\)\\]\\}])/),c=!1);if(!g)return null;if(g[1]){var h=this.$findClosingBracket(g[1],a);if(!h)return null;d=e.fromPoints(a,h),c||(d.end.column++,d.start.column--),d.cursor=d.end}else{var h=this.$findOpeningBracket(g[2],a);if(!h)return null;d=e.fromPoints(h,a),c||(d.start.column++,d.end.column--),d.cursor=d.start}return d},this.$brackets={\")\":\"(\",\"(\":\")\",\"]\":\"[\",\"[\":\"]\",\"{\":\"}\",\"}\":\"{\"},this.$findOpeningBracket=function(a,b,c){var e=this.$brackets[a],f=1,g=new d(this,b.row,b.column),h=g.getCurrentToken();h||(h=g.stepForward());if(!h)return;c||(c=new RegExp(\"(\\\\.?\"+h.type.replace(\".\",\"\\\\.\").replace(\"rparen\",\".paren\")+\")+\"));var i=b.column-g.getCurrentTokenColumn()-2,j=h.value;for(;;){while(i>=0){var k=j.charAt(i);if(k==e){f-=1;if(f==0)return{row:g.getCurrentTokenRow(),column:i+g.getCurrentTokenColumn()}}else k==a&&(f+=1);i-=1}do h=g.stepBackward();while(h&&!c.test(h.type));if(h==null)break;j=h.value,i=j.length-1}return null},this.$findClosingBracket=function(a,b,c){var e=this.$brackets[a],f=1,g=new d(this,b.row,b.column),h=g.getCurrentToken();h||(h=g.stepForward());if(!h)return;c||(c=new RegExp(\"(\\\\.?\"+h.type.replace(\".\",\"\\\\.\").replace(\"lparen\",\".paren\")+\")+\"));var i=b.column-g.getCurrentTokenColumn();for(;;){var j=h.value,k=j.length;while(i<k){var l=j.charAt(i);if(l==e){f-=1;if(f==0)return{row:g.getCurrentTokenRow(),column:i+g.getCurrentTokenColumn()}}else l==a&&(f+=1);i+=1}do h=g.stepForward();while(h&&!c.test(h.type));if(h==null)break;i=0}return null}}var d=a(\"../token_iterator\").TokenIterator,e=a(\"../range\").Range;b.BracketMatch=f}),ace.define(\"ace/search\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"],function(a,b,c){var d=a(\"./lib/lang\"),e=a(\"./lib/oop\"),f=a(\"./range\").Range,g=function(){this.$options={}};(function(){this.set=function(a){return e.mixin(this.$options,a),this},this.getOptions=function(){return d.copyObject(this.$options)},this.setOptions=function(a){this.$options=a},this.find=function(a){var b=this.$matchIterator(a,this.$options);if(!b)return!1;var c=null;return b.forEach(function(a,b,d){if(!a.start){var e=a.offset+(d||0);c=new f(b,e,b,e+a.length)}else c=a;return!0}),c},this.findAll=function(a){var b=this.$options;if(!b.needle)return[];this.$assembleRegExp(b);var c=b.range,e=c?a.getLines(c.start.row,c.end.row):a.doc.getAllLines(),g=[],h=b.re;if(b.$isMultiLine){var i=h.length,j=e.length-i;for(var k=h.offset||0;k<=j;k++){for(var l=0;l<i;l++)if(e[k+l].search(h[l])==-1)break;var m=e[k],n=e[k+i-1],o=m.match(h[0])[0].length,p=n.match(h[i-1])[0].length;g.push(new f(k,m.length-o,k+i-1,p))}}else for(var q=0;q<e.length;q++){var r=d.getMatchOffsets(e[q],h);for(var l=0;l<r.length;l++){var s=r[l];g.push(new f(q,s.offset,q,s.offset+s.length))}}if(c){var t=c.start.column,u=c.start.column,q=0,l=g.length-1;while(q<l&&g[q].start.column<t&&g[q].start.row==c.start.row)q++;while(q<l&&g[l].end.column>u&&g[l].end.row==c.end.row)l--;return g.slice(q,l+1)}return g},this.replace=function(a,b){var c=this.$options,d=this.$assembleRegExp(c);if(c.$isMultiLine)return b;if(!d)return;var e=d.exec(a);if(!e||e[0].length!=a.length)return null;b=a.replace(d,b);if(c.preserveCase){b=b.split(\"\");for(var f=Math.min(a.length,a.length);f--;){var g=a[f];g&&g.toLowerCase()!=g?b[f]=b[f].toUpperCase():b[f]=b[f].toLowerCase()}b=b.join(\"\")}return b},this.$matchIterator=function(a,b){var c=this.$assembleRegExp(b);if(!c)return!1;var e=this,g,h=b.backwards;if(b.$isMultiLine)var i=c.length,j=function(b,d,e){var h=b.search(c[0]);if(h==-1)return;for(var j=1;j<i;j++){b=a.getLine(d+j);if(b.search(c[j])==-1)return}var k=b.match(c[i-1])[0].length,l=new f(d,h,d+i-1,k);c.offset==1?(l.start.row--,l.start.column=Number.MAX_VALUE):e&&(l.start.column+=e);if(g(l))return!0};else if(h)var j=function(a,b,e){var f=d.getMatchOffsets(a,c);for(var h=f.length-1;h>=0;h--)if(g(f[h],b,e))return!0};else var j=function(a,b,e){var f=d.getMatchOffsets(a,c);for(var h=0;h<f.length;h++)if(g(f[h],b,e))return!0};return{forEach:function(c){g=c,e.$lineIterator(a,b).forEach(j)}}},this.$assembleRegExp=function(a){if(a.needle instanceof RegExp)return a.re=a.needle;var b=a.needle;if(!a.needle)return a.re=!1;a.regExp||(b=d.escapeRegExp(b)),a.wholeWord&&(b=\"\\\\b\"+b+\"\\\\b\");var c=a.caseSensitive?\"g\":\"gi\";a.$isMultiLine=/[\\n\\r]/.test(b);if(a.$isMultiLine)return a.re=this.$assembleMultilineRegExp(b,c);try{var e=new RegExp(b,c)}catch(f){e=!1}return a.re=e},this.$assembleMultilineRegExp=function(a,b){var c=a.replace(/\\r\\n|\\r|\\n/g,\"$\\n^\").split(\"\\n\"),d=[];for(var e=0;e<c.length;e++)try{d.push(new RegExp(c[e],b))}catch(f){return!1}return c[0]==\"\"?(d.shift(),d.offset=1):d.offset=0,d},this.$lineIterator=function(a,b){var c=b.backwards==1,d=b.skipCurrent!=0,e=b.range,f=b.start;f||(f=e?e[c?\"end\":\"start\"]:a.selection.getRange()),f.start&&(f=f[d!=c?\"end\":\"start\"]);var g=e?e.start.row:0,h=e?e.end.row:a.getLength()-1,i=c?function(c){var d=f.row,e=a.getLine(d).substring(0,f.column);if(c(e,d))return;for(d--;d>=g;d--)if(c(a.getLine(d),d))return;if(b.wrap==0)return;for(d=h,g=f.row;d>=g;d--)if(c(a.getLine(d),d))return}:function(c){var d=f.row,e=a.getLine(d).substr(f.column);if(c(e,d,f.column))return;for(d+=1;d<=h;d++)if(c(a.getLine(d),d))return;if(b.wrap==0)return;for(d=g,h=f.row;d<=h;d++)if(c(a.getLine(d),d))return};return{forEach:i}}}).call(g.prototype),b.Search=g}),ace.define(\"ace/commands/command_manager\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/keyboard/hash_handler\",\"ace/lib/event_emitter\"],function(a,b,c){var d=a(\"../lib/oop\"),e=a(\"../keyboard/hash_handler\").HashHandler,f=a(\"../lib/event_emitter\").EventEmitter,g=function(a,b){this.platform=a,this.commands={},this.commmandKeyBinding={},this.addCommands(b),this.setDefaultHandler(\"exec\",function(a){return a.command.exec(a.editor,a.args||{})})};d.inherits(g,e),function(){d.implement(this,f),this.exec=function(a,b,c){typeof a==\"string\"&&(a=this.commands[a]);if(!a)return!1;if(b&&b.$readOnly&&!a.readOnly)return!1;var d=this._emit(\"exec\",{editor:b,command:a,args:c});return d===!1?!1:!0},this.toggleRecording=function(a){if(this.$inReplay)return;return a&&a._emit(\"changeStatus\"),this.recording?(this.macro.pop(),this.removeEventListener(\"exec\",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(a){this.macro.push([a.command,a.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on(\"exec\",this.$addCommandToMacro),this.recording=!0)},this.replay=function(a){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(a);try{this.$inReplay=!0,this.macro.forEach(function(b){typeof b==\"string\"?this.exec(b,a):this.exec(b[0],a,b[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(a){return a.map(function(a){return typeof a[0]!=\"string\"&&(a[0]=a[0].name),a[1]||(a=a[0]),a})}}.call(g.prototype),b.CommandManager=g}),ace.define(\"ace/keyboard/hash_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\"],function(a,b,c){function e(a,b){this.platform=b,this.commands={},this.commmandKeyBinding={},this.addCommands(a)}var d=a(\"../lib/keys\");(function(){this.addCommand=function(a){this.commands[a.name]&&this.removeCommand(a),this.commands[a.name]=a,a.bindKey&&this._buildKeyHash(a)},this.removeCommand=function(a){var b=typeof a==\"string\"?a:a.name;a=this.commands[b],delete this.commands[b];var c=this.commmandKeyBinding;for(var d in c)for(var e in c[d])c[d][e]==a&&delete c[d][e]},this.bindKey=function(a,b){if(!a)return;if(typeof b==\"function\"){this.addCommand({exec:b,bindKey:a,name:a});return}var c=this.commmandKeyBinding;a.split(\"|\").forEach(function(a){var d=this.parseKeys(a,b),e=d.hashId;(c[e]||(c[e]={}))[d.key]=b},this)},this.addCommands=function(a){a&&Object.keys(a).forEach(function(b){var c=a[b];if(typeof c==\"string\")return this.bindKey(c,b);typeof c==\"function\"&&(c={exec:c}),c.name||(c.name=b),this.addCommand(c)},this)},this.removeCommands=function(a){Object.keys(a).forEach(function(b){this.removeCommand(a[b])},this)},this.bindKeys=function(a){Object.keys(a).forEach(function(b){this.bindKey(b,a[b])},this)},this._buildKeyHash=function(a){var b=a.bindKey;if(!b)return;var c=typeof b==\"string\"?b:b[this.platform];this.bindKey(c,a)},this.parseKeys=function(a){var b,c=0,e=a.toLowerCase().trim().split(/\\s*\\-\\s*/);for(var f=0,g=e.length;f<g;f++)d.KEY_MODS[e[f]]?c|=d.KEY_MODS[e[f]]:b=e[f]||\"-\";return e[0]==\"text\"&&e.length==2&&(c=-1,b=e[1]),{key:b,hashId:c}},this.findKeyCommand=function(b,c){var d=this.commmandKeyBinding;return d[b]&&d[b][c.toLowerCase()]},this.handleKeyboard=function(a,b,c,d){return{command:this.findKeyCommand(b,c)}}}).call(e.prototype),b.HashHandler=e}),ace.define(\"ace/commands/default_commands\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\"],function(a,b,c){function e(a,b){return{win:a,mac:b}}var d=a(\"../lib/lang\");b.commands=[{name:\"selectall\",bindKey:e(\"Ctrl-A\",\"Command-A\"),exec:function(a){a.selectAll()},readOnly:!0},{name:\"centerselection\",bindKey:e(null,\"Ctrl-L\"),exec:function(a){a.centerSelection()},readOnly:!0},{name:\"gotoline\",bindKey:e(\"Ctrl-L\",\"Command-L\"),exec:function(a){var b=parseInt(prompt(\"Enter line number:\"),10);isNaN(b)||a.gotoLine(b)},readOnly:!0},{name:\"fold\",bindKey:e(\"Alt-L|Ctrl-F1\",\"Command-Alt-L|Command-F1\"),exec:function(a){a.session.toggleFold(!1)},readOnly:!0},{name:\"unfold\",bindKey:e(\"Alt-Shift-L|Ctrl-Shift-F1\",\"Command-Alt-Shift-L|Command-Shift-F1\"),exec:function(a){a.session.toggleFold(!0)},readOnly:!0},{name:\"foldall\",bindKey:e(\"Alt-0\",\"Command-Option-0\"),exec:function(a){a.session.foldAll()},readOnly:!0},{name:\"unfoldall\",bindKey:e(\"Alt-Shift-0\",\"Command-Option-Shift-0\"),exec:function(a){a.session.unfold()},readOnly:!0},{name:\"findnext\",bindKey:e(\"Ctrl-K\",\"Command-G\"),exec:function(a){a.findNext()},readOnly:!0},{name:\"findprevious\",bindKey:e(\"Ctrl-Shift-K\",\"Command-Shift-G\"),exec:function(a){a.findPrevious()},readOnly:!0},{name:\"find\",bindKey:e(\"Ctrl-F\",\"Command-F\"),exec:function(a){var b=prompt(\"Find:\",a.getCopyText());a.find(b)},readOnly:!0},{name:\"overwrite\",bindKey:\"Insert\",exec:function(a){a.toggleOverwrite()},readOnly:!0},{name:\"selecttostart\",bindKey:e(\"Ctrl-Shift-Home\",\"Command-Shift-Up\"),exec:function(a){a.getSelection().selectFileStart()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"gotostart\",bindKey:e(\"Ctrl-Home\",\"Command-Home|Command-Up\"),exec:function(a){a.navigateFileStart()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selectup\",bindKey:e(\"Shift-Up\",\"Shift-Up\"),exec:function(a){a.getSelection().selectUp()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"golineup\",bindKey:e(\"Up\",\"Up|Ctrl-P\"),exec:function(a,b){a.navigateUp(b.times)},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selecttoend\",bindKey:e(\"Ctrl-Shift-End\",\"Command-Shift-Down\"),exec:function(a){a.getSelection().selectFileEnd()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"gotoend\",bindKey:e(\"Ctrl-End\",\"Command-End|Command-Down\"),exec:function(a){a.navigateFileEnd()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selectdown\",bindKey:e(\"Shift-Down\",\"Shift-Down\"),exec:function(a){a.getSelection().selectDown()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"golinedown\",bindKey:e(\"Down\",\"Down|Ctrl-N\"),exec:function(a,b){a.navigateDown(b.times)},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selectwordleft\",bindKey:e(\"Ctrl-Shift-Left\",\"Option-Shift-Left\"),exec:function(a){a.getSelection().selectWordLeft()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"gotowordleft\",bindKey:e(\"Ctrl-Left\",\"Option-Left\"),exec:function(a){a.navigateWordLeft()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selecttolinestart\",bindKey:e(\"Alt-Shift-Left\",\"Command-Shift-Left\"),exec:function(a){a.getSelection().selectLineStart()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"gotolinestart\",bindKey:e(\"Alt-Left|Home\",\"Command-Left|Home|Ctrl-A\"),exec:function(a){a.navigateLineStart()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selectleft\",bindKey:e(\"Shift-Left\",\"Shift-Left\"),exec:function(a){a.getSelection().selectLeft()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"gotoleft\",bindKey:e(\"Left\",\"Left|Ctrl-B\"),exec:function(a,b){a.navigateLeft(b.times)},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selectwordright\",bindKey:e(\"Ctrl-Shift-Right\",\"Option-Shift-Right\"),exec:function(a){a.getSelection().selectWordRight()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"gotowordright\",bindKey:e(\"Ctrl-Right\",\"Option-Right\"),exec:function(a){a.navigateWordRight()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selecttolineend\",bindKey:e(\"Alt-Shift-Right\",\"Command-Shift-Right\"),exec:function(a){a.getSelection().selectLineEnd()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"gotolineend\",bindKey:e(\"Alt-Right|End\",\"Command-Right|End|Ctrl-E\"),exec:function(a){a.navigateLineEnd()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selectright\",bindKey:e(\"Shift-Right\",\"Shift-Right\"),exec:function(a){a.getSelection().selectRight()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"gotoright\",bindKey:e(\"Right\",\"Right|Ctrl-F\"),exec:function(a,b){a.navigateRight(b.times)},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selectpagedown\",bindKey:\"Shift-PageDown\",exec:function(a){a.selectPageDown()},readOnly:!0},{name:\"pagedown\",bindKey:e(null,\"Option-PageDown\"),exec:function(a){a.scrollPageDown()},readOnly:!0},{name:\"gotopagedown\",bindKey:e(\"PageDown\",\"PageDown|Ctrl-V\"),exec:function(a){a.gotoPageDown()},readOnly:!0},{name:\"selectpageup\",bindKey:\"Shift-PageUp\",exec:function(a){a.selectPageUp()},readOnly:!0},{name:\"pageup\",bindKey:e(null,\"Option-PageUp\"),exec:function(a){a.scrollPageUp()},readOnly:!0},{name:\"gotopageup\",bindKey:\"PageUp\",exec:function(a){a.gotoPageUp()},readOnly:!0},{name:\"scrollup\",bindKey:e(\"Ctrl-Up\",null),exec:function(a){a.renderer.scrollBy(0,-2*a.renderer.layerConfig.lineHeight)},readOnly:!0},{name:\"scrolldown\",bindKey:e(\"Ctrl-Down\",null),exec:function(a){a.renderer.scrollBy(0,2*a.renderer.layerConfig.lineHeight)},readOnly:!0},{name:\"selectlinestart\",bindKey:\"Shift-Home\",exec:function(a){a.getSelection().selectLineStart()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selectlineend\",bindKey:\"Shift-End\",exec:function(a){a.getSelection().selectLineEnd()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"togglerecording\",bindKey:e(\"Ctrl-Alt-E\",\"Command-Option-E\"),exec:function(a){a.commands.toggleRecording(a)},readOnly:!0},{name:\"replaymacro\",bindKey:e(\"Ctrl-Shift-E\",\"Command-Shift-E\"),exec:function(a){a.commands.replay(a)},readOnly:!0},{name:\"jumptomatching\",bindKey:e(\"Ctrl-P\",\"Ctrl-Shift-P\"),exec:function(a){a.jumpToMatching()},multiSelectAction:\"forEach\",readOnly:!0},{name:\"selecttomatching\",bindKey:e(\"Ctrl-Shift-P\",null),exec:function(a){a.jumpToMatching(!0)},readOnly:!0},{name:\"cut\",exec:function(a){var b=a.getSelectionRange();a._emit(\"cut\",b),a.selection.isEmpty()||(a.session.remove(b),a.clearSelection())},multiSelectAction:\"forEach\"},{name:\"removeline\",bindKey:e(\"Ctrl-D\",\"Command-D\"),exec:function(a){a.removeLines()},multiSelectAction:\"forEach\"},{name:\"duplicateSelection\",bindKey:e(\"Ctrl-Shift-D\",\"Command-Shift-D\"),exec:function(a){a.duplicateSelection()},multiSelectAction:\"forEach\"},{name:\"togglecomment\",bindKey:e(\"Ctrl-/\",\"Command-/\"),exec:function(a){a.toggleCommentLines()},multiSelectAction:\"forEach\"},{name:\"replace\",bindKey:e(\"Ctrl-R\",\"Command-Option-F\"),exec:function(a){var b=prompt(\"Find:\",a.getCopyText());if(!b)return;var c=prompt(\"Replacement:\");if(!c)return;a.replace(c,{needle:b})}},{name:\"replaceall\",bindKey:e(\"Ctrl-Shift-R\",\"Command-Shift-Option-F\"),exec:function(a){var b=prompt(\"Find:\");if(!b)return;var c=prompt(\"Replacement:\");if(!c)return;a.replaceAll(c,{needle:b})}},{name:\"undo\",bindKey:e(\"Ctrl-Z\",\"Command-Z\"),exec:function(a){a.undo()}},{name:\"redo\",bindKey:e(\"Ctrl-Shift-Z|Ctrl-Y\",\"Command-Shift-Z|Command-Y\"),exec:function(a){a.redo()}},{name:\"copylinesup\",bindKey:e(\"Alt-Shift-Up\",\"Command-Option-Up\"),exec:function(a){a.copyLinesUp()}},{name:\"movelinesup\",bindKey:e(\"Alt-Up\",\"Option-Up\"),exec:function(a){a.moveLinesUp()}},{name:\"copylinesdown\",bindKey:e(\"Alt-Shift-Down\",\"Command-Option-Down\"),exec:function(a){a.copyLinesDown()}},{name:\"movelinesdown\",bindKey:e(\"Alt-Down\",\"Option-Down\"),exec:function(a){a.moveLinesDown()}},{name:\"del\",bindKey:e(\"Delete\",\"Delete|Ctrl-D\"),exec:function(a){a.remove(\"right\")},multiSelectAction:\"forEach\"},{name:\"backspace\",bindKey:e(\"Command-Backspace|Option-Backspace|Shift-Backspace|Backspace\",\"Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H\"),exec:function(a){a.remove(\"left\")},multiSelectAction:\"forEach\"},{name:\"removetolinestart\",bindKey:e(\"Alt-Backspace\",\"Command-Backspace\"),exec:function(a){a.removeToLineStart()},multiSelectAction:\"forEach\"},{name:\"removetolineend\",bindKey:e(\"Alt-Delete\",\"Ctrl-K\"),exec:function(a){a.removeToLineEnd()},multiSelectAction:\"forEach\"},{name:\"removewordleft\",bindKey:e(\"Ctrl-Backspace\",\"Alt-Backspace|Ctrl-Alt-Backspace\"),exec:function(a){a.removeWordLeft()},multiSelectAction:\"forEach\"},{name:\"removewordright\",bindKey:e(\"Ctrl-Delete\",\"Alt-Delete\"),exec:function(a){a.removeWordRight()},multiSelectAction:\"forEach\"},{name:\"outdent\",bindKey:e(\"Shift-Tab\",\"Shift-Tab\"),exec:function(a){a.blockOutdent()},multiSelectAction:\"forEach\"},{name:\"indent\",bindKey:e(\"Tab\",\"Tab\"),exec:function(a){a.indent()},multiSelectAction:\"forEach\"},{name:\"insertstring\",exec:function(a,b){a.insert(b)},multiSelectAction:\"forEach\"},{name:\"inserttext\",exec:function(a,b){a.insert(d.stringRepeat(b.text||\"\",b.times||1))},multiSelectAction:\"forEach\"},{name:\"splitline\",bindKey:e(null,\"Ctrl-O\"),exec:function(a){a.splitLine()},multiSelectAction:\"forEach\"},{name:\"transposeletters\",bindKey:e(\"Ctrl-T\",\"Ctrl-T\"),exec:function(a){a.transposeLetters()},multiSelectAction:function(a){a.transposeSelections(1)}},{name:\"touppercase\",bindKey:e(\"Ctrl-U\",\"Ctrl-U\"),exec:function(a){a.toUpperCase()},multiSelectAction:\"forEach\"},{name:\"tolowercase\",bindKey:e(\"Ctrl-Shift-U\",\"Ctrl-Shift-U\"),exec:function(a){a.toLowerCase()},multiSelectAction:\"forEach\"}]}),ace.define(\"ace/undomanager\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=function(){this.reset()};(function(){this.execute=function(a){var b=a.args[0];this.$doc=a.args[1],this.$undoStack.push(b),this.$redoStack=[]},this.undo=function(a){var b=this.$undoStack.pop(),c=null;return b&&(c=this.$doc.undoChanges(b,a),this.$redoStack.push(b)),c},this.redo=function(a){var b=this.$redoStack.pop(),c=null;return b&&(c=this.$doc.redoChanges(b,a),this.$undoStack.push(b)),c},this.reset=function(){this.$undoStack=[],this.$redoStack=[]},this.hasUndo=function(){return this.$undoStack.length>0},this.hasRedo=function(){return this.$redoStack.length>0}}).call(d.prototype),b.UndoManager=d}),ace.define(\"ace/virtual_renderer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/config\",\"ace/lib/net\",\"ace/layer/gutter\",\"ace/layer/marker\",\"ace/layer/text\",\"ace/layer/cursor\",\"ace/scrollbar\",\"ace/renderloop\",\"ace/lib/event_emitter\",\"ace/requirejs/text!ace/css/editor.css\"],function(a,b,c){var d=a(\"./lib/oop\"),e=a(\"./lib/dom\"),f=a(\"./lib/event\"),g=a(\"./lib/useragent\"),h=a(\"./config\"),i=a(\"./lib/net\"),j=a(\"./layer/gutter\").Gutter,k=a(\"./layer/marker\").Marker,l=a(\"./layer/text\").Text,m=a(\"./layer/cursor\").Cursor,n=a(\"./scrollbar\").ScrollBar,o=a(\"./renderloop\").RenderLoop,p=a(\"./lib/event_emitter\").EventEmitter,q=a(\"ace/requirejs/text!./css/editor.css\");e.importCssString(q,\"ace_editor\");var r=function(a,b){var c=this;this.container=a,this.$keepTextAreaAtCursor=!g.isIE,e.addCssClass(a,\"ace_editor\"),this.setTheme(b),this.$gutter=e.createElement(\"div\"),this.$gutter.className=\"ace_gutter\",this.container.appendChild(this.$gutter),this.scroller=e.createElement(\"div\"),this.scroller.className=\"ace_scroller\",this.container.appendChild(this.scroller),this.content=e.createElement(\"div\"),this.content.className=\"ace_content\",this.scroller.appendChild(this.content),this.setHighlightGutterLine(!0),this.$gutterLayer=new j(this.$gutter),this.$gutterLayer.on(\"changeGutterWidth\",this.onResize.bind(this,!0)),this.$markerBack=new k(this.content);var d=this.$textLayer=new l(this.content);this.canvas=d.element,this.$markerFront=new k(this.content),this.characterWidth=d.getCharacterWidth(),this.lineHeight=d.getLineHeight(),this.$cursorLayer=new m(this.content),this.$cursorPadding=8,this.$horizScroll=!1,this.$horizScrollAlwaysVisible=!1,this.$animatedScroll=!1,this.scrollBar=new n(a),this.scrollBar.addEventListener(\"scroll\",function(a){c.$inScrollAnimation||c.session.setScrollTop(a.data)}),this.scrollTop=0,this.scrollLeft=0,f.addListener(this.scroller,\"scroll\",function(){var a=c.scroller.scrollLeft;c.scrollLeft=a,c.session.setScrollLeft(a)}),this.cursorPos={row:0,column:0},this.$textLayer.addEventListener(\"changeCharacterSize\",function(){c.characterWidth=d.getCharacterWidth(),c.lineHeight=d.getLineHeight(),c.$updatePrintMargin(),c.onResize(!0),c.$loop.schedule(c.CHANGE_FULL)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:1,characterWidth:1,minHeight:1,maxHeight:1,offset:0,height:1},this.$loop=new o(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.setPadding(4),this.$updatePrintMargin()};(function(){this.showGutter=!0,this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,d.implement(this,p),this.setSession=function(a){this.session=a,this.scroller.className=\"ace_scroller\",this.$cursorLayer.setSession(a),this.$markerBack.setSession(a),this.$markerFront.setSession(a),this.$gutterLayer.setSession(a),this.$textLayer.setSession(a),this.$loop.schedule(this.CHANGE_FULL)},this.updateLines=function(a,b){b===undefined&&(b=Infinity),this.$changedLines?(this.$changedLines.firstRow>a&&(this.$changedLines.firstRow=a),this.$changedLines.lastRow<b&&(this.$changedLines.lastRow=b)):this.$changedLines={firstRow:a,lastRow:b},this.$loop.schedule(this.CHANGE_LINES)},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(a){a?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.onResize=function(a,b,c,d){var f=this.CHANGE_SIZE,g=this.$size;if(this.resizing>2)return;this.resizing>1?this.resizing++:this.resizing=a?1:0,d||(d=e.getInnerHeight(this.container));if(a||g.height!=d)g.height=d,this.scroller.style.height=d+\"px\",g.scrollerHeight=this.scroller.clientHeight,this.scrollBar.setHeight(g.scrollerHeight),this.session&&(this.session.setScrollTop(this.getScrollTop()),f|=this.CHANGE_FULL);c||(c=e.getInnerWidth(this.container));if(a||this.resizing>1||g.width!=c){g.width=c;var b=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=b+\"px\",g.scrollerWidth=Math.max(0,c-b-this.scrollBar.getWidth()),this.scroller.style.right=this.scrollBar.getWidth()+\"px\";if(this.session.getUseWrapMode()&&this.adjustWrapLimit()||a)f|=this.CHANGE_FULL}a?this.$renderChanges(f,!0):this.$loop.schedule(f),a&&delete this.resizing},this.adjustWrapLimit=function(){var a=this.$size.scrollerWidth-this.$padding*2,b=Math.floor(a/this.characterWidth);return this.session.adjustWrapLimit(b)},this.setAnimatedScroll=function(a){this.$animatedScroll=a},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(a){this.$textLayer.setShowInvisibles(a)&&this.$loop.schedule(this.CHANGE_TEXT)},this.getShowInvisibles=function(){return this.$textLayer.showInvisibles},this.getDisplayIndentGuides=function(){return this.$textLayer.displayIndentGuides},this.setDisplayIndentGuides=function(a){this.$textLayer.setDisplayIndentGuides(a)&&this.$loop.schedule(this.CHANGE_TEXT)},this.$showPrintMargin=!0,this.setShowPrintMargin=function(a){this.$showPrintMargin=a,this.$updatePrintMargin()},this.getShowPrintMargin=function(){return this.$showPrintMargin},this.$printMarginColumn=80,this.setPrintMarginColumn=function(a){this.$printMarginColumn=a,this.$updatePrintMargin()},this.getPrintMarginColumn=function(){return this.$printMarginColumn},this.getShowGutter=function(){return this.showGutter},this.setShowGutter=function(a){if(this.showGutter===a)return;this.$gutter.style.display=a?\"block\":\"none\",this.showGutter=a,this.onResize(!0)},this.getFadeFoldWidgets=function(){return e.hasCssClass(this.$gutter,\"ace_fade-fold-widgets\")},this.setFadeFoldWidgets=function(a){a?e.addCssClass(this.$gutter,\"ace_fade-fold-widgets\"):e.removeCssClass(this.$gutter,\"ace_fade-fold-widgets\")},this.$highlightGutterLine=!1,this.setHighlightGutterLine=function(a){if(this.$highlightGutterLine==a)return;this.$highlightGutterLine=a;if(!this.$gutterLineHighlight){this.$gutterLineHighlight=e.createElement(\"div\"),this.$gutterLineHighlight.className=\"ace_gutter_active_line\",this.$gutter.appendChild(this.$gutterLineHighlight);return}this.$gutterLineHighlight.style.display=a?\"\":\"none\",this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight()},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$updateGutterLineHighlight=function(){this.$gutterLineHighlight.style.top=this.$cursorLayer.$pixelPos.top-this.layerConfig.offset+\"px\",this.$gutterLineHighlight.style.height=this.layerConfig.lineHeight+\"px\"},this.$updatePrintMargin=function(){var a;if(!this.$showPrintMargin&&!this.$printMarginEl)return;this.$printMarginEl||(a=e.createElement(\"div\"),a.className=\"ace_print_margin_layer\",this.$printMarginEl=e.createElement(\"div\"),this.$printMarginEl.className=\"ace_print_margin\",a.appendChild(this.$printMarginEl),this.content.insertBefore(a,this.$textLayer.element));var b=this.$printMarginEl.style;b.left=this.characterWidth*this.$printMarginColumn+this.$padding+\"px\",b.visibility=this.$showPrintMargin?\"visible\":\"hidden\"},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.content},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(!this.$keepTextAreaAtCursor)return;var a=this.$cursorLayer.$pixelPos.top,b=this.$cursorLayer.$pixelPos.left;a-=this.layerConfig.offset;if(a<0||a>this.layerConfig.height-this.lineHeight)return;var c=this.characterWidth;this.$composition&&(c+=this.textarea.scrollWidth),b-=this.scrollLeft,b>this.$size.scrollerWidth-c&&(b=this.$size.scrollerWidth-c),this.showGutter&&(b+=this.$gutterLayer.gutterWidth),this.textarea.style.height=this.lineHeight+\"px\",this.textarea.style.width=c+\"px\",this.textarea.style.left=b+\"px\",this.textarea.style.top=a-1+\"px\"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var a=Math.floor((this.layerConfig.height+this.layerConfig.offset)/this.layerConfig.lineHeight);return this.layerConfig.firstRow-1+a},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(a){this.$padding=a,this.$textLayer.setPadding(a),this.$cursorLayer.setPadding(a),this.$markerFront.setPadding(a),this.$markerBack.setPadding(a),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.getHScrollBarAlwaysVisible=function(){return this.$horizScrollAlwaysVisible},this.setHScrollBarAlwaysVisible=function(a){this.$horizScrollAlwaysVisible!=a&&(this.$horizScrollAlwaysVisible=a,(!this.$horizScrollAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL))},this.$updateScrollBar=function(){this.scrollBar.setInnerHeight(this.layerConfig.maxHeight),this.scrollBar.setScrollTop(this.scrollTop)},this.$renderChanges=function(a,b){if(!b&&(!a||!this.session||!this.container.offsetWidth))return;(a&this.CHANGE_FULL||a&this.CHANGE_SIZE||a&this.CHANGE_TEXT||a&this.CHANGE_LINES||a&this.CHANGE_SCROLL)&&this.$computeLayerConfig();if(a&this.CHANGE_H_SCROLL){this.scroller.scrollLeft=this.scrollLeft;var c=this.scroller.scrollLeft;this.scrollLeft=c,this.session.setScrollLeft(c),this.scroller.className=this.scrollLeft==0?\"ace_scroller\":\"ace_scroller horscroll\"}if(a&this.CHANGE_FULL){this.$textLayer.checkForSizeChanges(),this.$updateScrollBar(),this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight();return}if(a&this.CHANGE_SCROLL){this.$updateScrollBar(),a&this.CHANGE_TEXT||a&this.CHANGE_LINES?this.$textLayer.update(this.layerConfig):this.$textLayer.scrollLines(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight();return}a&this.CHANGE_TEXT?(this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig)):a&this.CHANGE_LINES?(this.$updateLines()||a&this.CHANGE_GUTTER&&this.showGutter)&&this.$gutterLayer.update(this.layerConfig):(a&this.CHANGE_TEXT||a&this.CHANGE_GUTTER)&&this.showGutter&&this.$gutterLayer.update(this.layerConfig),a&this.CHANGE_CURSOR&&(this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),a&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(this.layerConfig),a&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(this.layerConfig),a&this.CHANGE_SIZE&&this.$updateScrollBar()},this.$computeLayerConfig=function(){var a=this.session,b=this.scrollTop%this.lineHeight,c=this.$size.scrollerHeight+this.lineHeight,d=this.$getLongestLine(),e=this.$horizScrollAlwaysVisible||this.$size.scrollerWidth-d<0,f=this.$horizScroll!==e;this.$horizScroll=e,f&&(this.scroller.style.overflowX=e?\"scroll\":\"hidden\",e||this.session.setScrollLeft(0));var g=this.session.getScreenLength()*this.lineHeight;this.session.setScrollTop(Math.max(0,Math.min(this.scrollTop,g-this.$size.scrollerHeight)));var h=Math.ceil(c/this.lineHeight)-1,i=Math.max(0,Math.round((this.scrollTop-b)/this.lineHeight)),j=i+h,k,l,m=this.lineHeight;i=a.screenToDocumentRow(i,0);var n=a.getFoldLine(i);n&&(i=n.start.row),k=a.documentToScreenRow(i,0),l=a.getRowLength(i)*m,j=Math.min(a.screenToDocumentRow(j,0),a.getLength()-1),c=this.$size.scrollerHeight+a.getRowLength(j)*m+l,b=this.scrollTop-k*m,this.layerConfig={width:d,padding:this.$padding,firstRow:i,firstRowScreen:k,lastRow:j,lineHeight:m,characterWidth:this.characterWidth,minHeight:c,maxHeight:g,offset:b,height:this.$size.scrollerHeight},this.$gutterLayer.element.style.marginTop=-b+\"px\",this.content.style.marginTop=-b+\"px\",this.content.style.width=d+2*this.$padding+\"px\",this.content.style.height=c+\"px\",f&&this.onResize(!0)},this.$updateLines=function(){var a=this.$changedLines.firstRow,b=this.$changedLines.lastRow;this.$changedLines=null;var c=this.layerConfig;if(a>c.lastRow+1)return;if(b<c.firstRow)return;if(b===Infinity){this.showGutter&&this.$gutterLayer.update(c),this.$textLayer.update(c);return}return this.$textLayer.updateLines(c,a,b),!0},this.$getLongestLine=function(){var a=this.session.getScreenWidth();return this.$textLayer.showInvisibles&&(a+=1),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(a*this.characterWidth))},this.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},this.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},this.addGutterDecoration=function(a,b){this.$gutterLayer.addGutterDecoration(a,b)},this.removeGutterDecoration=function(a,b){this.$gutterLayer.removeGutterDecoration(a,b)},this.updateBreakpoints=function(a){this.$loop.schedule(this.CHANGE_GUTTER)},this.setAnnotations=function(a){this.$gutterLayer.setAnnotations(a),this.$loop.schedule(this.CHANGE_GUTTER)},this.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},this.hideCursor=function(){this.$cursorLayer.hideCursor()},this.showCursor=function(){this.$cursorLayer.showCursor()},this.scrollSelectionIntoView=function(a,b,c){this.scrollCursorIntoView(a,c),this.scrollCursorIntoView(b,c)},this.scrollCursorIntoView=function(a,b){if(this.$size.scrollerHeight===0)return;var c=this.$cursorLayer.getPixelPosition(a),d=c.left,e=c.top;this.scrollTop>e?(b&&(e-=b*this.$size.scrollerHeight),this.session.setScrollTop(e)):this.scrollTop+this.$size.scrollerHeight<e+this.lineHeight&&(b&&(e+=b*this.$size.scrollerHeight),this.session.setScrollTop(e+this.lineHeight-this.$size.scrollerHeight));var f=this.scrollLeft;f>d?(d<this.$padding+2*this.layerConfig.characterWidth&&(d=0),this.session.setScrollLeft(d)):f+this.$size.scrollerWidth<d+this.characterWidth&&this.session.setScrollLeft(Math.round(d+this.characterWidth-this.$size.scrollerWidth))},this.getScrollTop=function(){return this.session.getScrollTop()},this.getScrollLeft=function(){return this.session.getScrollLeft()},this.getScrollTopRow=function(){return this.scrollTop/this.lineHeight},this.getScrollBottomRow=function(){return Math.max(0,Math.floor((this.scrollTop+this.$size.scrollerHeight)/this.lineHeight)-1)},this.scrollToRow=function(a){this.session.setScrollTop(a*this.lineHeight)},this.alignCursor=function(a,b){typeof a==\"number\"&&(a={row:a,column:0});var c=this.$cursorLayer.getPixelPosition(a),d=c.top-this.$size.scrollerHeight*(b||0);this.session.setScrollTop(d)},this.STEPS=8,this.$calcSteps=function(a,b){var c=0,d=this.STEPS,e=[],f=function(a,b,c){return c*(Math.pow(a-1,3)+1)+b};for(c=0;c<d;++c)e.push(f(c/this.STEPS,a,b-a));return e},this.scrollToLine=function(a,b,c,d){var e=this.$cursorLayer.getPixelPosition({row:a,column:0}),f=e.top;b&&(f-=this.$size.scrollerHeight/2);var g=this.scrollTop;this.session.setScrollTop(f),c!==!1&&this.animateScrolling(g,d)},this.animateScrolling=function(a,b){var c=this.scrollTop;if(this.$animatedScroll&&Math.abs(a-c)<1e5){var d=this,e=d.$calcSteps(a,c);this.$inScrollAnimation=!0,clearInterval(this.$timer),d.session.setScrollTop(e.shift()),this.$timer=setInterval(function(){e.length?(d.session.setScrollTop(e.shift()),d.session.$scrollTop=c):c!=null?(d.session.$scrollTop=-1,d.session.setScrollTop(c),c=null):(d.$timer=clearInterval(d.$timer),d.$inScrollAnimation=!1,b&&b())},10)}},this.scrollToY=function(a){this.scrollTop!==a&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=a)},this.scrollToX=function(a){a<0&&(a=0),this.scrollLeft!==a&&(this.scrollLeft=a),this.$loop.schedule(this.CHANGE_H_SCROLL)},this.scrollBy=function(a,b){b&&this.session.setScrollTop(this.session.getScrollTop()+b),a&&this.session.setScrollLeft(this.session.getScrollLeft()+a)},this.isScrollableBy=function(a,b){if(b<0&&this.session.getScrollTop()>0)return!0;if(b>0&&this.session.getScrollTop()+this.$size.scrollerHeight<this.layerConfig.maxHeight)return!0},this.pixelToScreenCoordinates=function(a,b){var c=this.scroller.getBoundingClientRect(),d=(a+this.scrollLeft-c.left-this.$padding)/this.characterWidth,e=Math.floor((b+this.scrollTop-c.top)/this.lineHeight),f=Math.round(d);return{row:e,column:f,side:d-f>0?1:-1}},this.screenToTextCoordinates=function(a,b){var c=this.scroller.getBoundingClientRect(),d=Math.round((a+this.scrollLeft-c.left-this.$padding)/this.characterWidth),e=Math.floor((b+this.scrollTop-c.top)/this.lineHeight);return this.session.screenToDocumentPosition(e,Math.max(d,0))},this.textToScreenCoordinates=function(a,b){var c=this.scroller.getBoundingClientRect(),d=this.session.documentToScreenPosition(a,b),e=this.$padding+Math.round(d.column*this.characterWidth),f=d.row*this.lineHeight;return{pageX:c.left+e-this.scrollLeft,pageY:c.top+f-this.scrollTop}},this.visualizeFocus=function(){e.addCssClass(this.container,\"ace_focus\")},this.visualizeBlur=function(){e.removeCssClass(this.container,\"ace_focus\")},this.showComposition=function(a){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,e.addCssClass(this.textarea,\"ace_composition\"),this.textarea.style.cssText=\"\",this.$moveTextAreaToCursor()},this.setCompositionText=function(a){this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;e.removeCssClass(this.textarea,\"ace_composition\"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null},this._loadTheme=function(a,b){if(!h.get(\"packaged\"))return b();i.loadScript(h.moduleUrl(a,\"theme\"),b)},this.setTheme=function(b){function h(a){e.importCssString(a.cssText,a.cssClass,c.container.ownerDocument),c.$theme&&e.removeCssClass(c.container,c.$theme),c.$theme=a?a.cssClass:null,c.$theme&&e.addCssClass(c.container,c.$theme),a&&a.isDark?e.addCssClass(c.container,\"ace_dark\"):e.removeCssClass(c.container,\"ace_dark\"),c.$size&&(c.$size.width=0,c.onResize())}var c=this;this.$themeValue=b;if(!b||typeof b==\"string\"){var d=b||\"ace/theme/textmate\",f;try{f=a(d)}catch(g){}if(f)return h(f);c._loadTheme(d,function(){a([d],function(a){if(c.$themeValue!==b)return;h(a)})})}else h(b)},this.getTheme=function(){return this.$themeValue},this.setStyle=function(b){e.addCssClass(this.container,b)},this.unsetStyle=function(b){e.removeCssClass(this.container,b)},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(r.prototype),b.VirtualRenderer=r}),ace.define(\"ace/layer/gutter\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(a,b,c){var d=a(\"../lib/dom\"),e=a(\"../lib/oop\"),f=a(\"../lib/event_emitter\").EventEmitter,g=function(a){this.element=d.createElement(\"div\"),this.element.className=\"ace_layer ace_gutter-layer\",a.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[]};(function(){e.implement(this,f),this.setSession=function(a){this.session=a},this.addGutterDecoration=function(a,b){window.console&&console.warn&&console.warn(\"deprecated use session.addGutterDecoration\"),this.session.addGutterDecoration(a,b)},this.removeGutterDecoration=function(a,b){window.console&&console.warn&&console.warn(\"deprecated use session.removeGutterDecoration\"),this.session.removeGutterDecoration(a,b)},this.setAnnotations=function(a){this.$annotations=[];for(var b in a)if(a.hasOwnProperty(b)){var c=a[b];if(!c)continue;var d=this.$annotations[b]={text:[]};for(var e=0;e<c.length;e++){var f=c[e],g=f.text.replace(/\"/g,\"&quot;\").replace(/'/g,\"&#8217;\").replace(/</,\"&lt;\");d.text.indexOf(g)===-1&&d.text.push(g);var h=f.type;h==\"error\"?d.className=\" ace_error\":h==\"warning\"&&d.className!=\" ace_error\"?d.className=\" ace_warning\":h==\"info\"&&!d.className&&(d.className=\" ace_info\")}}},this.update=function(a){var b={className:\"\"},c=[],e=a.firstRow,f=a.lastRow,g=this.session.getNextFoldLine(e),h=g?g.start.row:Infinity,i=this.$showFoldWidgets&&this.session.foldWidgets,j=this.session.$breakpoints,k=this.session.$decorations,l=0;for(;;){e>h&&(e=g.end.row+1,g=this.session.getNextFoldLine(e,g),h=g?g.start.row:Infinity);if(e>f)break;var m=this.$annotations[e]||b;c.push(\"<div class='ace_gutter-cell \",j[e]||\"\",k[e]||\"\",m.className,\"' style='height:\",this.session.getRowLength(e)*a.lineHeight,\"px;'>\",l=e+1);if(i){var n=i[e];n==null&&(n=i[e]=this.session.getFoldWidget(e)),n&&c.push(\"<span class='ace_fold-widget \",n,n==\"start\"&&e==h&&e<g.end.row?\" closed\":\" open\",\"'></span>\")}c.push(\"</div>\"),e++}this.element=d.setInnerHtml(this.element,c.join(\"\")),this.element.style.height=a.minHeight+\"px\",this.session.$useWrapMode&&(l=this.session.getLength());var o=(\"\"+l).length*a.characterWidth,p=this.$padding||this.$computePadding();o+=p.left+p.right,o!==this.gutterWidth&&(this.gutterWidth=o,this.element.style.width=Math.ceil(this.gutterWidth)+\"px\",this._emit(\"changeGutterWidth\",o))},this.$showFoldWidgets=!0,this.setShowFoldWidgets=function(a){a?d.addCssClass(this.element,\"ace_folding-enabled\"):d.removeCssClass(this.element,\"ace_folding-enabled\"),this.$showFoldWidgets=a,this.$padding=null},this.getShowFoldWidgets=function(){return this.$showFoldWidgets},this.$computePadding=function(){if(!this.element.firstChild)return{left:0,right:0};var a=d.computedStyle(this.element.firstChild);return this.$padding={},this.$padding.left=parseInt(a.paddingLeft)+1,this.$padding.right=parseInt(a.paddingRight),this.$padding},this.getRegion=function(a){var b=this.$padding||this.$computePadding(),c=this.element.getBoundingClientRect();if(a.x<b.left+c.left)return\"markers\";if(this.$showFoldWidgets&&a.x>c.right-b.right)return\"foldWidgets\"}}).call(g.prototype),b.Gutter=g}),ace.define(\"ace/layer/marker\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/dom\"],function(a,b,c){var d=a(\"../range\").Range,e=a(\"../lib/dom\"),f=function(a){this.element=e.createElement(\"div\"),this.element.className=\"ace_layer ace_marker-layer\",a.appendChild(this.element)};(function(){this.$padding=0,this.setPadding=function(a){this.$padding=a},this.setSession=function(a){this.session=a},this.setMarkers=function(a){this.markers=a},this.update=function(a){var a=a||this.config;if(!a)return;this.config=a;var b=[];for(var c in this.markers){var d=this.markers[c];if(!d.range){d.update(b,this,this.session,a);continue}var f=d.range.clipRows(a.firstRow,a.lastRow);if(f.isEmpty())continue;f=f.toScreenRange(this.session);if(d.renderer){var g=this.$getTop(f.start.row,a),h=Math.round(this.$padding+f.start.column*a.characterWidth);d.renderer(b,f,h,g,a)}else f.isMultiLine()?d.type==\"text\"?this.drawTextMarker(b,f,d.clazz,a):this.drawMultiLineMarker(b,f,d.clazz,a,d.type):this.drawSingleLineMarker(b,f,d.clazz+\" start\",a,null,d.type)}this.element=e.setInnerHtml(this.element,b.join(\"\"))},this.$getTop=function(a,b){return(a-b.firstRowScreen)*b.lineHeight},this.drawTextMarker=function(a,b,c,e){var f=b.start.row,g=new d(f,b.start.column,f,this.session.getScreenLastRowColumn(f));this.drawSingleLineMarker(a,g,c+\" start\",e,1,\"text\"),f=b.end.row,g=new d(f,0,f,b.end.column),this.drawSingleLineMarker(a,g,c,e,0,\"text\");for(f=b.start.row+1;f<b.end.row;f++)g.start.row=f,g.end.row=f,g.end.column=this.session.getScreenLastRowColumn(f),this.drawSingleLineMarker(a,g,c,e,1,\"text\")},this.drawMultiLineMarker=function(a,b,c,d,e){var f=e===\"background\"?0:this.$padding,g=d.lineHeight,h=this.$getTop(b.start.row,d),i=Math.round(f+b.start.column*d.characterWidth);a.push(\"<div class='\",c,\" start' style='\",\"height:\",g,\"px;\",\"right:0;\",\"top:\",h,\"px;\",\"left:\",i,\"px;'></div>\"),h=this.$getTop(b.end.row,d);var j=Math.round(b.end.column*d.characterWidth);a.push(\"<div class='\",c,\"' style='\",\"height:\",g,\"px;\",\"width:\",j,\"px;\",\"top:\",h,\"px;\",\"left:\",f,\"px;'></div>\"),g=(b.end.row-b.start.row-1)*d.lineHeight;if(g<0)return;h=this.$getTop(b.start.row+1,d),a.push(\"<div class='\",c,\"' style='\",\"height:\",g,\"px;\",\"right:0;\",\"top:\",h,\"px;\",\"left:\",f,\"px;'></div>\")},this.drawSingleLineMarker=function(a,b,c,d,e,f){var g=f===\"background\"?0:this.$padding,h=d.lineHeight;if(f===\"background\")var i=d.width;else i=Math.round((b.end.column+(e||0)-b.start.column)*d.characterWidth);var j=this.$getTop(b.start.row,d),k=Math.round(g+b.start.column*d.characterWidth);a.push(\"<div class='\",c,\"' style='\",\"height:\",h,\"px;\",\"width:\",i,\"px;\",\"top:\",j,\"px;\",\"left:\",k,\"px;'></div>\")}}).call(f.prototype),b.Marker=f}),ace.define(\"ace/layer/text\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/lib/event_emitter\"],function(a,b,c){var d=a(\"../lib/oop\"),e=a(\"../lib/dom\"),f=a(\"../lib/lang\"),g=a(\"../lib/useragent\"),h=a(\"../lib/event_emitter\").EventEmitter,i=function(a){this.element=e.createElement(\"div\"),this.element.className=\"ace_layer ace_text-layer\",a.appendChild(this.element),this.$characterSize=this.$measureSizes()||{width:0,height:0},this.$pollSizeChanges()};(function(){d.implement(this,h),this.EOF_CHAR=\"¶\",this.EOL_CHAR=\"¬\",this.TAB_CHAR=\"→\",this.SPACE_CHAR=\"·\",this.$padding=0,this.setPadding=function(a){this.$padding=a,this.element.style.padding=\"0 \"+a+\"px\"},this.getLineHeight=function(){return this.$characterSize.height||1},this.getCharacterWidth=function(){return this.$characterSize.width||1},this.checkForSizeChanges=function(){var a=this.$measureSizes();a&&(this.$characterSize.width!==a.width||this.$characterSize.height!==a.height)&&(this.$characterSize=a,this._emit(\"changeCharacterSize\",{data:a}))},this.$pollSizeChanges=function(){var a=this;this.$pollSizeChangesTimer=setInterval(function(){a.checkForSizeChanges()},500)},this.$fontStyles={fontFamily:1,fontSize:1,fontWeight:1,fontStyle:1,lineHeight:1},this.$measureSizes=g.isIE||g.isOldGecko?function(){var a=1e3;if(!this.$measureNode){var b=this.$measureNode=e.createElement(\"div\"),c=b.style;c.width=c.height=\"auto\",c.left=c.top=-a*40+\"px\",c.visibility=\"hidden\",c.position=\"fixed\",c.overflow=\"visible\",c.whiteSpace=\"nowrap\",b.innerHTML=f.stringRepeat(\"Xy\",a);if(this.element.ownerDocument.body)this.element.ownerDocument.body.appendChild(b);else{var d=this.element.parentNode;while(!e.hasCssClass(d,\"ace_editor\"))d=d.parentNode;d.appendChild(b)}}if(!this.element.offsetWidth)return null;var c=this.$measureNode.style,g=e.computedStyle(this.element);for(var h in this.$fontStyles)c[h]=g[h];var i={height:this.$measureNode.offsetHeight,width:this.$measureNode.offsetWidth/(a*2)};return i.width==0||i.height==0?null:i}:function(){if(!this.$measureNode){var a=this.$measureNode=e.createElement(\"div\"),b=a.style;b.width=b.height=\"auto\",b.left=b.top=\"-100px\",b.visibility=\"hidden\",b.position=\"fixed\",b.overflow=\"visible\",b.whiteSpace=\"nowrap\",a.innerHTML=\"X\";var c=this.element.parentNode;while(c&&!e.hasCssClass(c,\"ace_editor\"))c=c.parentNode;if(!c)return this.$measureNode=null;c.appendChild(a)}var d=this.$measureNode.getBoundingClientRect(),f={height:d.height,width:d.width};return f.width==0||f.height==0?null:f},this.setSession=function(a){this.session=a,this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(a){return this.showInvisibles==a?!1:(this.showInvisibles=a,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(a){return this.displayIndentGuides==a?!1:(this.displayIndentGuides=a,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var a=this.session.getTabSize();this.tabSize=a;var b=this.$tabStrings=[0];for(var c=1;c<a+1;c++)this.showInvisibles?b.push(\"<span class='ace_invisible'>\"+this.TAB_CHAR+Array(c).join(\"&#160;\")+\"</span>\"):b.push((new Array(c+1)).join(\"&#160;\"));if(this.displayIndentGuides){this.$indentGuideRe=/\\s\\S| \\t|\\t |\\s$/;var d=\"ace_indent-guide\",e=Array(this.tabSize+1).join(\"&#160;\"),f=e;this.showInvisibles&&(d+=\" ace_invisible\",f=this.TAB_CHAR+e.substr(6)),this.$tabStrings[\" \"]=\"<span class='\"+d+\"'>\"+e+\"</span>\",this.$tabStrings[\"\t\"]=\"<span class='\"+d+\"'>\"+f+\"</span>\"}},this.updateLines=function(a,b,c){(this.config.lastRow!=a.lastRow||this.config.firstRow!=a.firstRow)&&this.scrollLines(a),this.config=a;var d=Math.max(b,a.firstRow),f=Math.min(c,a.lastRow),g=this.element.childNodes,h=0;for(var i=a.firstRow;i<d;i++){var j=this.session.getFoldLine(i);if(j){if(j.containsRow(d)){d=j.start.row;break}i=j.end.row}h++}var i=d,j=this.session.getNextFoldLine(i),k=j?j.start.row:Infinity;for(;;){i>k&&(i=j.end.row+1,j=this.session.getNextFoldLine(i,j),k=j?j.start.row:Infinity);if(i>f)break;var l=g[h++];if(l){var m=[];this.$renderLine(m,i,!this.$useLineGroups(),i==k?j:!1),e.setInnerHtml(l,m.join(\"\"))}i++}},this.scrollLines=function(a){var b=this.config;this.config=a;if(!b||b.lastRow<a.firstRow)return this.update(a);if(a.lastRow<b.firstRow)return this.update(a);var c=this.element;if(b.firstRow<a.firstRow)for(var d=this.session.getFoldedRowCount(b.firstRow,a.firstRow-1);d>0;d--)c.removeChild(c.firstChild);if(b.lastRow>a.lastRow)for(var d=this.session.getFoldedRowCount(a.lastRow+1,b.lastRow);d>0;d--)c.removeChild(c.lastChild);if(a.firstRow<b.firstRow){var e=this.$renderLinesFragment(a,a.firstRow,b.firstRow-1);c.firstChild?c.insertBefore(e,c.firstChild):c.appendChild(e)}if(a.lastRow>b.lastRow){var e=this.$renderLinesFragment(a,b.lastRow+1,a.lastRow);c.appendChild(e)}},this.$renderLinesFragment=function(a,b,c){var d=this.element.ownerDocument.createDocumentFragment(),f=b,g=this.session.getNextFoldLine(f),h=g?g.start.row:Infinity;for(;;){f>h&&(f=g.end.row+1,g=this.session.getNextFoldLine(f,g),h=g?g.start.row:Infinity);if(f>c)break;var i=e.createElement(\"div\"),j=[];this.$renderLine(j,f,!1,f==h?g:!1),i.innerHTML=j.join(\"\");if(this.$useLineGroups())i.className=\"ace_line_group\",d.appendChild(i);else{var k=i.childNodes;while(k.length)d.appendChild(k[0])}f++}return d},this.update=function(a){this.config=a;var b=[],c=a.firstRow,d=a.lastRow,f=c,g=this.session.getNextFoldLine(f),h=g?g.start.row:Infinity;for(;;){f>h&&(f=g.end.row+1,g=this.session.getNextFoldLine(f,g),h=g?g.start.row:Infinity);if(f>d)break;this.$useLineGroups()&&b.push(\"<div class='ace_line_group'>\"),this.$renderLine(b,f,!1,f==h?g:!1),this.$useLineGroups()&&b.push(\"</div>\"),f++}this.element=e.setInnerHtml(this.element,b.join(\"\"))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(a,b,c,d){var e=this,f=/\\t|&|<|( +)|([\\x00-\\x1f\\x80-\\xa0\\u1680\\u180E\\u2000-\\u200f\\u2028\\u2029\\u202F\\u205F\\u3000\\uFEFF])|[\\u1100-\\u115F\\u11A3-\\u11A7\\u11FA-\\u11FF\\u2329-\\u232A\\u2E80-\\u2E99\\u2E9B-\\u2EF3\\u2F00-\\u2FD5\\u2FF0-\\u2FFB\\u3000-\\u303E\\u3041-\\u3096\\u3099-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u3190-\\u31BA\\u31C0-\\u31E3\\u31F0-\\u321E\\u3220-\\u3247\\u3250-\\u32FE\\u3300-\\u4DBF\\u4E00-\\uA48C\\uA490-\\uA4C6\\uA960-\\uA97C\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFAFF\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE66\\uFE68-\\uFE6B\\uFF01-\\uFF60\\uFFE0-\\uFFE6]/g,g=function(a,c,d,f,g){if(c)return(new Array(a.length+1)).join(\"&#160;\");if(a==\"&\")return\"&#38;\";if(a==\"<\")return\"&#60;\";if(a==\"\t\"){var h=e.session.getScreenTabSize(b+f);return b+=h-1,e.$tabStrings[h]}if(a==\"　\"){var i=e.showInvisibles?\"ace_cjk ace_invisible\":\"ace_cjk\",j=e.showInvisibles?e.SPACE_CHAR:\"\";return b+=1,\"<span class='\"+i+\"' style='width:\"+e.config.characterWidth*2+\"px'>\"+j+\"</span>\"}return d?\"<span class='ace_invisible ace_invalid'>\"+e.SPACE_CHAR+\"</span>\":(b+=1,\"<span class='ace_cjk' style='width:\"+e.config.characterWidth*2+\"px'>\"+a+\"</span>\")},h=d.replace(f,g);if(!this.$textToken[c.type]){var i=\"ace_\"+c.type.replace(/\\./g,\" ace_\"),j=\"\";c.type==\"fold\"&&(j=\" style='width:\"+c.value.length*this.config.characterWidth+\"px;' \"),a.push(\"<span class='\",i,\"'\",j,\">\",h,\"</span>\")}else a.push(h);return b+d.length},this.renderIndentGuide=function(a,b){var c=b.search(this.$indentGuideRe);return c<=0?b:b[0]==\" \"?(c-=c%this.tabSize,a.push(Array(c/this.tabSize+1).join(this.$tabStrings[\" \"])),b.substr(c)):b[0]==\"\t\"?(a.push(Array(c+1).join(this.$tabStrings[\"\t\"])),b.substr(c)):b},this.$renderWrappedLine=function(a,b,c,d){var e=0,f=0,g=c[0],h=0;for(var i=0;i<b.length;i++){var j=b[i],k=j.value;if(i==0&&this.displayIndentGuides){e=k.length,k=this.renderIndentGuide(a,k);if(!k)continue;e-=k.length}if(e+k.length<g)h=this.$renderToken(a,h,j,k),e+=k.length;else{while(e+k.length>=g)h=this.$renderToken(a,h,j,k.substring(0,g-e)),k=k.substring(g-e),e=g,d||a.push(\"</div>\",\"<div class='ace_line' style='height:\",this.config.lineHeight,\"px'>\"),f++,h=0,g=c[f]||Number.MAX_VALUE;k.length!=0&&(e+=k.length,h=this.$renderToken(a,h,j,k))}}},this.$renderSimpleLine=function(a,b){var c=0,d=b[0],e=d.value;this.displayIndentGuides&&(e=this.renderIndentGuide(a,e)),e&&(c=this.$renderToken(a,c,d,e));for(var f=1;f<b.length;f++)d=b[f],e=d.value,c=this.$renderToken(a,c,d,e)},this.$renderLine=function(a,b,c,d){!d&&d!=0&&(d=this.session.getFoldLine(b));if(d)var e=this.$getFoldLineTokens(b,d);else var e=this.session.getTokens(b);c||a.push(\"<div class='ace_line' style='height:\",this.config.lineHeight,\"px'>\");if(e.length){var f=this.session.getRowSplitData(b);f&&f.length?this.$renderWrappedLine(a,e,f,c):this.$renderSimpleLine(a,e)}this.showInvisibles&&(d&&(b=d.end.row),a.push(\"<span class='ace_invisible'>\",b==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,\"</span>\")),c||a.push(\"</div>\")},this.$getFoldLineTokens=function(a,b){function e(a,b,c){var e=0,f=0;while(f+a[e].value.length<b){f+=a[e].value.length,e++;if(e==a.length)return}if(f!=b){var g=a[e].value.substring(b-f);g.length>c-b&&(g=g.substring(0,c-b)),d.push({type:a[e].type,value:g}),f=b+g.length,e+=1}while(f<c&&e<a.length){var g=a[e].value;g.length+f>c?d.push({type:a[e].type,value:g.substring(0,c-f)}):d.push(a[e]),f+=g.length,e+=1}}var c=this.session,d=[],f=c.getTokens(a);return b.walk(function(a,b,g,h,i){a?d.push({type:\"fold\",value:a}):(i&&(f=c.getTokens(b)),f.length&&e(f,h,g))},b.end.row,this.session.getLine(b.end.row).length),d},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(i.prototype),b.Text=i}),ace.define(\"ace/layer/cursor\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(a,b,c){var d=a(\"../lib/dom\"),e=function(a){this.element=d.createElement(\"div\"),this.element.className=\"ace_layer ace_cursor-layer\",a.appendChild(this.element),this.isVisible=!1,this.cursors=[],this.cursor=this.addCursor()};(function(){this.$padding=0,this.setPadding=function(a){this.$padding=a},this.setSession=function(a){this.session=a},this.addCursor=function(){var a=d.createElement(\"div\"),b=\"ace_cursor\";return this.isVisible||(b+=\" ace_hidden\"),this.overwrite&&(b+=\" ace_overwrite\"),a.className=b,this.element.appendChild(a),this.cursors.push(a),a},this.removeCursor=function(){if(this.cursors.length>1){var a=this.cursors.pop();return a.parentNode.removeChild(a),a}},this.hideCursor=function(){this.isVisible=!1;for(var a=this.cursors.length;a--;)d.addCssClass(this.cursors[a],\"ace_hidden\");clearInterval(this.blinkId)},this.showCursor=function(){this.isVisible=!0;for(var a=this.cursors.length;a--;)d.removeCssClass(this.cursors[a],\"ace_hidden\");this.element.style.visibility=\"\",this.restartTimer()},this.restartTimer=function(){clearInterval(this.blinkId);if(!this.isVisible)return;var a=this.cursors.length==1?this.cursor:this.element;this.blinkId=setInterval(function(){a.style.visibility=\"hidden\",setTimeout(function(){a.style.visibility=\"\"},400)},1e3)},this.getPixelPosition=function(a,b){if(!this.config||!this.session)return{left:0,top:0};a||(a=this.session.selection.getCursor());var c=this.session.documentToScreenPosition(a),d=Math.round(this.$padding+c.column*this.config.characterWidth),e=(c.row-(b?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:d,top:e}},this.update=function(a){this.config=a;if(this.session.selectionMarkerCount>0){var b=this.session.$selectionMarkers,c=0,d,e=0;for(var c=b.length;c--;){d=b[c];var f=this.getPixelPosition(d.cursor,!0),g=(this.cursors[e++]||this.addCursor()).style;g.left=f.left+\"px\",g.top=f.top+\"px\",g.width=a.characterWidth+\"px\",g.height=a.lineHeight+\"px\"}if(e>1)while(this.cursors.length>e)this.removeCursor()}else{var f=this.getPixelPosition(null,!0),g=this.cursor.style;g.left=f.left+\"px\",g.top=f.top+\"px\",g.width=a.characterWidth+\"px\",g.height=a.lineHeight+\"px\";while(this.cursors.length>1)this.removeCursor()}var h=this.session.getOverwrite();h!=this.overwrite&&this.$setOverite(h),this.$pixelPos=f,this.restartTimer()},this.$setOverite=function(a){this.overwrite=a;for(var b=this.cursors.length;b--;)a?d.addCssClass(this.cursors[b],\"ace_overwrite\"):d.removeCssClass(this.cursors[b],\"ace_overwrite\")},this.destroy=function(){clearInterval(this.blinkId)}}).call(e.prototype),b.Cursor=e}),ace.define(\"ace/scrollbar\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/event_emitter\"],function(a,b,c){var d=a(\"./lib/oop\"),e=a(\"./lib/dom\"),f=a(\"./lib/event\"),g=a(\"./lib/event_emitter\").EventEmitter,h=function(a){this.element=e.createElement(\"div\"),this.element.className=\"ace_sb\",this.inner=e.createElement(\"div\"),this.element.appendChild(this.inner),a.appendChild(this.element),this.width=e.scrollbarWidth(a.ownerDocument),this.element.style.width=(this.width||15)+5+\"px\",f.addListener(this.element,\"scroll\",this.onScroll.bind(this))};(function(){d.implement(this,g),this.onScroll=function(){this._emit(\"scroll\",{data:this.element.scrollTop})},this.getWidth=function(){return this.width},this.setHeight=function(a){this.element.style.height=a+\"px\"},this.setInnerHeight=function(a){this.inner.style.height=a+\"px\"},this.setScrollTop=function(a){this.element.scrollTop=a}}).call(h.prototype),b.ScrollBar=h}),ace.define(\"ace/renderloop\",[\"require\",\"exports\",\"module\",\"ace/lib/event\"],function(a,b,c){var d=a(\"./lib/event\"),e=function(a,b){this.onRender=a,this.pending=!1,this.changes=0,this.window=b||window};(function(){this.schedule=function(a){this.changes=this.changes|a;if(!this.pending){this.pending=!0;var b=this;d.nextTick(function(){b.pending=!1;var a;while(a=b.changes)b.changes=0,b.onRender(a)},this.window)}}}).call(e.prototype),b.RenderLoop=e}),ace.define(\"ace/requirejs/text!ace/css/editor.css\",[],\".ace_editor {\\n    position: absolute;\\n    overflow: hidden;\\n    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Droid Sans Mono', 'Consolas', monospace;\\n    font-size: 12px;\\n}\\n\\n.ace_scroller {\\n    position: absolute;\\n    overflow: hidden;\\n}\\n\\n.ace_content {\\n    position: absolute;\\n    box-sizing: border-box;\\n    -moz-box-sizing: border-box;\\n    -webkit-box-sizing: border-box;\\n    cursor: text;\\n}\\n\\n.ace_gutter {\\n    position: absolute;\\n    overflow : hidden;\\n    height: 100%;\\n    width: auto;\\n    cursor: default;\\n    z-index: 4;\\n}\\n\\n.ace_gutter_active_line {\\n    position: absolute;\\n    left: 0;\\n    right: 0;\\n}\\n\\n.ace_scroller.horscroll {\\n    box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\\n}\\n\\n.ace_gutter-cell {\\n    padding-left: 19px;\\n    padding-right: 6px;\\n    background-repeat: no-repeat;\\n}\\n\\n.ace_gutter-cell.ace_error {\\n    background-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTQ4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTU4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBMjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBMzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkgXxbAAAAJbSURBVHjapFNNaBNBFH4zs5vdZLP5sQmNpT82QY209heh1ioWisaDRcSKF0WKJ0GQnrzrxasHsR6EnlrwD0TagxJabaVEpFYxLWlLSS822tr87m66ccfd2GKyVhA6MMybgfe97/vmPUQphd0sZjto9XIn9OOsvlu2nkqRzVU+6vvlzPf8W6bk8dxQ0NPbxAALgCgg2JkaQuhzQau/El0zbmUA7U0Es8v2CiYmKQJHGO1QICCLoqilMhkmurDAyapKgqItezi/USRdJqEYY4D5jCy03ht2yMkkvL91jTTX10qzyyu2hruPRN7jgbH+EOsXcMLgYiThEgAMhABW85oqy1DXdRIdvP1AHJ2acQXvDIrVHcdQNrEKNYSVMSZGMjEzIIAwDXIo+6G/FxcGnzkC3T2oMhLjre49sBB+RRcHLqdafK6sYdE/GGBwU1VpFNj0aN8pJbe+BkZyevUrvLl6Xmm0W9IuTc0DxrDNAJd5oEvI/KRsNC3bQyNjPO9yQ1YHcfj2QvfQc/5TUhJTBc2iM0U7AWDQtc1nJHvD/cfO2s7jaGkiTEfa/Ep8coLu7zmNmh8+dc5lZDuUeFAGUNA/OY6JVaypQ0vjr7XYjUvJM37vt+j1vuTK5DgVfVUoTjVe+y3/LxMxY2GgU+CSLy4cpfsYorRXuXIOi0Vt40h67uZFTdIo6nLaZcwUJWAzwNS0tBnqqKzQDnjdG/iPyZxo46HaKUpbvYkj8qYRTZsBhge+JHhZyh0x9b95JqjVJkT084kZIPwu/mPWqPgfQ5jXh2+92Ay7HedfAgwA6KDWafb4w3cAAAAASUVORK5CYII=\\\");\\n    background-repeat: no-repeat;\\n    background-position: 2px center;\\n}\\n\\n.ace_gutter-cell.ace_warning {\\n    background-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTg4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTk4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBNjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBNzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pgd7PfIAAAGmSURBVHjaYvr//z8DJZiJgUIANoCRkREb9gLiSVAaQx4OQM7AAkwd7XU2/v++/rOttdYGEB9dASEvOMydGKfH8Gv/p4XTkvRBfLxeQAP+1cUhXopyvzhP7P/IoSj7g7Mw09cNKO6J1QQ0L4gICPIv/veg/8W+JdFvQNLHVsW9/nmn9zk7B+cCkDwhL7gt6knSZnx9/LuCEOcvkIAMP+cvto9nfqyZmmUAksfnBUtbM60gX/3/kgyv3/xSFOL5DZT+L8vP+Yfh5cvfPvp/xUHyQHXGyAYwgpwBjZYFT3Y1OEl/OfCH4ffv3wzc4iwMvNIsDJ+f/mH4+vIPAxsb631WW0Yln6ZpQLXdMK/DXGDflh+sIv37EivD5x//Gb7+YWT4y86sl7BCCkSD+Z++/1dkvsFRl+HnD1Rvje4F8whjMXmGj58YGf5zsDMwcnAwfPvKcml62DsQDeaDxN+/Y0qwlpEHqrdB94IRNIDUgfgfKJChGK4OikEW3gTiXUB950ASLFAF54AC94A0G9QAfOnmF9DCDzABFqS08IHYDIScdijOjQABBgC+/9awBH96jwAAAABJRU5ErkJggg==\\\");\\n    background-position: 2px center;\\n}\\n\\n.ace_gutter-cell.ace_info {\\n    background-image: url(\\\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\\\");\\n    background-position: 2px center;\\n}\\n.ace_dark .ace_gutter-cell.ace_info {\\n    background-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRTk5MTVGREIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRTk5MTVGRUIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZFOTkxNUZCQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFOTkxNUZDQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SIDkjAAAAJ1JREFUeNpi/P//PwMlgImBQkB7A6qrq/+DMC55FkIGKCoq4pVnpFkgTp069f/+/fv/r1u37r+tre1/kg0A+ptn9uzZYLaRkRHpLvjw4cNXWVlZhufPnzOcO3eOdAO0tbVPAjHDmzdvGA4fPsxIsgGSkpJmv379Ynj37h2DjIyMCMkG3LhxQ/T27dsMampqDHZ2dq/pH41DxwCAAAMAFdc68dUsFZgAAAAASUVORK5CYII=\\\");\\n}\\n\\n.ace_editor .ace_sb {\\n    position: absolute;\\n    overflow-x: hidden;\\n    overflow-y: scroll;\\n    right: 0;\\n}\\n\\n.ace_editor .ace_sb div {\\n    position: absolute;\\n    width: 1px;\\n    left: 0;\\n}\\n\\n.ace_editor .ace_print_margin_layer {\\n    z-index: 0;\\n    position: absolute;\\n    overflow: hidden;\\n    margin: 0;\\n    left: 0;\\n    height: 100%;\\n    width: 100%;\\n}\\n\\n.ace_editor .ace_print_margin {\\n    position: absolute;\\n    height: 100%;\\n}\\n\\n.ace_editor > textarea {\\n    position: absolute;\\n    z-index: 0;\\n    width: 0.5em;\\n    height: 1em;\\n    opacity: 0;\\n    background: transparent;\\n    appearance: none;\\n    -moz-appearance: none;\\n    border: none;\\n    resize: none;\\n    outline: none;\\n    overflow: hidden;\\n}\\n\\n.ace_editor > textarea.ace_composition {\\n    background: #fff;\\n    color: #000;\\n    z-index: 1000;\\n    opacity: 1;\\n    border: solid lightgray 1px;\\n    margin: -1px\\n}\\n\\n.ace_layer {\\n    z-index: 1;\\n    position: absolute;\\n    overflow: hidden;\\n    white-space: nowrap;\\n    height: 100%;\\n    width: 100%;\\n    box-sizing: border-box;\\n    -moz-box-sizing: border-box;\\n    -webkit-box-sizing: border-box;\\n    /* setting pointer-events: auto; on node under the mouse, which changes\\n        during scroll, will break mouse wheel scrolling in Safari */\\n    pointer-events: none;\\n}\\n\\n.ace_gutter .ace_layer {\\n    position: relative;\\n    width: auto;\\n    text-align: right;\\n    pointer-events: auto;\\n}\\n\\n.ace_text-layer {\\n    color: black;\\n    font: inherit !important;\\n}\\n\\n.ace_cjk {\\n    display: inline-block;\\n    text-align: center;\\n}\\n\\n.ace_cursor-layer {\\n    z-index: 4;\\n}\\n\\n.ace_cursor {\\n    z-index: 4;\\n    position: absolute;\\n}\\n\\n.ace_cursor.ace_hidden {\\n    opacity: 0.2;\\n}\\n\\n.ace_editor.multiselect .ace_cursor {\\n    border-left-width: 1px;\\n}\\n\\n.ace_line {\\n    white-space: nowrap;\\n}\\n\\n.ace_marker-layer .ace_step {\\n    position: absolute;\\n    z-index: 3;\\n}\\n\\n.ace_marker-layer .ace_selection {\\n    position: absolute;\\n    z-index: 5;\\n}\\n\\n.ace_marker-layer .ace_bracket {\\n    position: absolute;\\n    z-index: 6;\\n}\\n\\n.ace_marker-layer .ace_active_line {\\n    position: absolute;\\n    z-index: 2;\\n}\\n\\n.ace_marker-layer .ace_selected_word {\\n    position: absolute;\\n    z-index: 4;\\n    box-sizing: border-box;\\n    -moz-box-sizing: border-box;\\n    -webkit-box-sizing: border-box;\\n}\\n\\n.ace_line .ace_fold {\\n    box-sizing: border-box;\\n    -moz-box-sizing: border-box;\\n    -webkit-box-sizing: border-box;\\n\\n    display: inline-block;\\n    height: 11px;\\n    margin-top: -2px;\\n    vertical-align: middle;\\n\\n    background-image:\\n        url(\\\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\\\"),\\n        url(\\\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\\\");\\n    background-repeat: no-repeat, repeat-x;\\n    background-position: center center, top left;\\n    color: transparent;\\n\\n    border: 1px solid black;\\n    -moz-border-radius: 2px;\\n    -webkit-border-radius: 2px;\\n    border-radius: 2px;\\n\\n    cursor: pointer;\\n    pointer-events: auto;\\n}\\n\\n.ace_dark .ace_fold {\\n}\\n\\n.ace_fold:hover{\\n    background-image:\\n        url(\\\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\\\"),\\n        url(\\\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\\\");\\n    background-repeat: no-repeat, repeat-x;\\n    background-position: center center, top left;\\n}\\n\\n.ace_dragging .ace_content {\\n    cursor: move;\\n}\\n\\n.ace_gutter_tooltip {\\n    background-color: #FFFFD5;\\n    border: 1px solid gray;\\n    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);\\n    color: black;\\n    display: inline-block;\\n    padding: 4px;\\n    position: absolute;\\n    z-index: 300;\\n    box-sizing: border-box;\\n    -moz-box-sizing: border-box;\\n    -webkit-box-sizing: border-box;\\n    cursor: default;\\n}\\n\\n.ace_folding-enabled > .ace_gutter-cell {\\n    padding-right: 13px;\\n}\\n\\n.ace_fold-widget {\\n    box-sizing: border-box;\\n    -moz-box-sizing: border-box;\\n    -webkit-box-sizing: border-box;\\n\\n    margin: 0 -12px 0 1px;\\n    display: inline-block;\\n    height: 100%;\\n    width: 11px;\\n    vertical-align: bottom;\\n\\n    background-image: url(\\\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\\\");\\n    background-repeat: no-repeat;\\n    background-position: center;\\n\\n    border-radius: 3px;\\n    \\n    border: 1px solid transparent;\\n}\\n\\n.ace_fold-widget.end {\\n    background-image: url(\\\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\\\");\\n}\\n\\n.ace_fold-widget.closed {\\n    background-image: url(\\\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\\\");\\n}\\n\\n.ace_fold-widget:hover {\\n    border: 1px solid rgba(0, 0, 0, 0.3);\\n    background-color: rgba(255, 255, 255, 0.2);\\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\\n}\\n\\n.ace_fold-widget:active {\\n    border: 1px solid rgba(0, 0, 0, 0.4);\\n    background-color: rgba(0, 0, 0, 0.05);\\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\\n}\\n/**\\n * Dark version for fold widgets\\n */\\n.ace_dark .ace_fold-widget {\\n    background-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\\\");\\n}\\n.ace_dark .ace_fold-widget.end {\\n    background-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\\\");\\n}\\n.ace_dark .ace_fold-widget.closed {\\n    background-image: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\\\");\\n}\\n.ace_dark .ace_fold-widget:hover {\\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\\n    background-color: rgba(255, 255, 255, 0.1);\\n}\\n.ace_dark .ace_fold-widget:active {\\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\\n}\\n    \\n    \\n    \\n.ace_fold-widget.invalid {\\n    background-color: #FFB4B4;\\n    border-color: #DE5555;\\n}\\n\\n.ace_fade-fold-widgets .ace_fold-widget {\\n       -moz-transition: opacity 0.4s ease 0.05s;\\n    -webkit-transition: opacity 0.4s ease 0.05s;\\n         -o-transition: opacity 0.4s ease 0.05s;\\n        -ms-transition: opacity 0.4s ease 0.05s;\\n            transition: opacity 0.4s ease 0.05s;\\n    opacity: 0;\\n}\\n\\n.ace_fade-fold-widgets:hover .ace_fold-widget {\\n       -moz-transition: opacity 0.05s ease 0.05s;\\n    -webkit-transition: opacity 0.05s ease 0.05s;\\n         -o-transition: opacity 0.05s ease 0.05s;\\n        -ms-transition: opacity 0.05s ease 0.05s;\\n            transition: opacity 0.05s ease 0.05s;\\n    opacity:1;\\n}\\n\"),ace.define(\"ace/multi_select\",[\"require\",\"exports\",\"module\",\"ace/range_list\",\"ace/range\",\"ace/selection\",\"ace/mouse/multi_select_handler\",\"ace/lib/event\",\"ace/commands/multi_select_commands\",\"ace/search\",\"ace/edit_session\",\"ace/editor\"],function(a,b,c){function l(a,b,c){return k.$options.wrap=!0,k.$options.needle=b,k.$options.backwards=c==-1,k.find(a)}function o(a,b){return a.row==b.row&&a.column==b.column}function p(a){a.$onAddRange=a.$onAddRange.bind(a),a.$onRemoveRange=a.$onRemoveRange.bind(a),a.$onMultiSelect=a.$onMultiSelect.bind(a),a.$onSingleSelect=a.$onSingleSelect.bind(a),b.onSessionChange.call(a,a),a.on(\"changeSession\",b.onSessionChange.bind(a)),a.on(\"mousedown\",g),a.commands.addCommands(i.defaultCommands),q(a)}function q(a){function e(){c&&(d.style.cursor=\"\",c=!1)}var b=a.textInput.getElement(),c=!1,d=a.renderer.content;h.addListener(b,\"keydown\",function(a){a.keyCode==18&&!(a.ctrlKey||a.shiftKey||a.metaKey)?c||(d.style.cursor=\"crosshair\",c=!0):c&&(d.style.cursor=\"\")}),h.addListener(b,\"keyup\",e),h.addListener(b,\"blur\",e)}var d=a(\"./range_list\").RangeList,e=a(\"./range\").Range,f=a(\"./selection\").Selection,g=a(\"./mouse/multi_select_handler\").onMouseDown,h=a(\"./lib/event\"),i=a(\"./commands/multi_select_commands\");b.commands=i.defaultCommands.concat(i.multiSelectCommands);var j=a(\"./search\").Search,k=new j,m=a(\"./edit_session\").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(m.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(a,b){if(!a)return;if(!this.inMultiSelectMode&&this.rangeCount==0){var c=this.toOrientedRange();if(a.intersects(c))return b||this.fromOrientedRange(a);this.rangeList.add(c),this.$onAddRange(c)}a.cursor||(a.cursor=a.end);var d=this.rangeList.add(a);return this.$onAddRange(a),d.length&&this.$onRemoveRange(d),this.rangeCount>1&&!this.inMultiSelectMode&&(this._emit(\"multiSelect\"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),b||this.fromOrientedRange(a)},this.toSingleRange=function(a){a=a||this.ranges[0];var b=this.rangeList.removeAll();b.length&&this.$onRemoveRange(b),a&&this.fromOrientedRange(a)},this.substractPoint=function(a){var b=this.rangeList.substractPoint(a);if(b)return this.$onRemoveRange(b),b[0]},this.mergeOverlappingRanges=function(){var a=this.rangeList.merge();a.length?this.$onRemoveRange(a):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(a){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(a),this._emit(\"addRange\",{range:a})},this.$onRemoveRange=function(a){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var b=this.rangeList.ranges.pop();a.push(b),this.rangeCount=0}for(var c=a.length;c--;){var d=this.ranges.indexOf(a[c]);this.ranges.splice(d,1)}this._emit(\"removeRange\",{ranges:a}),this.rangeCount==0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._emit(\"singleSelect\"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),b=b||this.ranges[0],b&&!b.isEqual(this.getRange())&&this.fromOrientedRange(b)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new d,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeList.ranges.concat()},this.splitIntoLines=function(){if(this.rangeCount>1){var a=this.rangeList.ranges,b=a[a.length-1],c=e.fromPoints(a[0].start,b.end);this.toSingleRange(),this.setSelectionRange(c,b.cursor==b.start)}else{var c=this.getRange(),d=c.start.row,f=c.end.row;if(d==f)return;var g=[],h=this.getLineRange(d,!0);h.start.column=c.start.column,g.push(h);for(var i=d+1;i<f;i++)g.push(this.getLineRange(i,!0));h=this.getLineRange(f,!0),h.end.column=c.end.column,g.push(h),g.forEach(this.addRange,this)}},this.toggleBlockSelection=function(){if(this.rangeCount>1){var a=this.rangeList.ranges,b=a[a.length-1],c=e.fromPoints(a[0].start,b.end);this.toSingleRange(),this.setSelectionRange(c,b.cursor==b.start)}else{var d=this.session.documentToScreenPosition(this.selectionLead),f=this.session.documentToScreenPosition(this.selectionAnchor),g=this.rectangularRangeBlock(d,f);g.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(a,b,c){var d=[],f=a.column<b.column;if(f)var g=a.column,h=b.column;else var g=b.column,h=a.column;var i=a.row<b.row;if(i)var j=a.row,k=b.row;else var j=b.row,k=a.row;g<0&&(g=0),j<0&&(j=0),j==k&&(c=!0);for(var l=j;l<=k;l++){var m=e.fromPoints(this.session.screenToDocumentPosition(l,g),this.session.screenToDocumentPosition(l,h));if(m.isEmpty()){if(n&&o(m.end,n))break;var n=m.end}m.cursor=f?m.start:m.end,d.push(m)}i&&d.reverse();if(!c){var p=d.length-1;while(d[p].isEmpty()&&p>0)p--;if(p>0){var q=0;while(d[q].isEmpty())q++}for(var r=p;r>=q;r--)d[r].isEmpty()&&d.splice(r,1)}return d}}.call(f.prototype);var n=a(\"./editor\").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(a){a.cursor||(a.cursor=a.end);var b=this.getSelectionStyle();return a.marker=this.session.addMarker(a,\"ace_selection\",b),this.session.$selectionMarkers.push(a),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,a},this.removeSelectionMarker=function(a){if(!a.marker)return;this.session.removeMarker(a.marker);var b=this.session.$selectionMarkers.indexOf(a);b!=-1&&this.session.$selectionMarkers.splice(b,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(a){var b=this.session.$selectionMarkers;for(var c=a.length;c--;){var d=a[c];if(!d.marker)continue;this.session.removeMarker(d.marker);var e=b.indexOf(d);e!=-1&&b.splice(e,1)}this.session.selectionMarkerCount=b.length},this.$onAddRange=function(a){this.addSelectionMarker(a.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(a){this.removeSelectionMarkers(a.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(a){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle(\"multiselect\"),this.keyBinding.addKeyboardHandler(i.keyboardHandler),this.commands.on(\"exec\",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(a){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle(\"multiselect\"),this.keyBinding.removeKeyboardHandler(i.keyboardHandler),this.commands.removeEventListener(\"exec\",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelectExec=function(a){var b=a.command,c=a.editor;if(!c.multiSelect)return;b.multiSelectAction?b.multiSelectAction==\"forEach\"?c.forEachSelection(b,a.args):b.multiSelectAction==\"single\"?(c.exitMultiSelectMode(),b.exec(c,a.args||{})):b.multiSelectAction(c,a.args||{}):(b.exec(c,a.args||{}),c.multiSelect.addRange(c.multiSelect.toOrientedRange()),c.multiSelect.mergeOverlappingRanges()),a.preventDefault()},this.forEachSelection=function(a,b){if(this.inVirtualSelectionMode)return;var c=this.session,d=this.selection,e=d.rangeList,g=d._eventRegistry;d._eventRegistry={};var h=new f(c);this.inVirtualSelectionMode=!0;for(var i=e.ranges.length;i--;)h.fromOrientedRange(e.ranges[i]),this.selection=c.selection=h,a.exec(this,b||{}),h.toOrientedRange(e.ranges[i]);h.detach(),this.selection=c.selection=d,this.inVirtualSelectionMode=!1,d._eventRegistry=g,d.mergeOverlappingRanges(),this.onCursorChange(),this.onSelectionChange()},this.exitMultiSelectMode=function(){if(this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getCopyText=function(){var a=\"\";if(this.inMultiSelectMode){var b=this.multiSelect.rangeList.ranges;a=[];for(var c=0;c<b.length;c++)a.push(this.session.getTextRange(b[c]));a=a.join(this.session.getDocument().getNewLineCharacter())}else this.selection.isEmpty()||(a=this.session.getTextRange(this.getSelectionRange()));return a},this.onPaste=function(a){if(this.$readOnly)return;this._emit(\"paste\",a);if(!this.inMultiSelectMode)return this.insert(a);var b=a.split(/\\r\\n|\\r|\\n/),c=this.selection.rangeList.ranges;if(b.length>c.length||b.length<=2||!b[1])return this.commands.exec(\"insertstring\",this,a);for(var d=c.length;d--;){var e=c[d];e.isEmpty()||this.session.remove(e),this.session.insert(e.start,b[d])}},this.findAll=function(a,b,c){b=b||{},b.needle=a||b.needle,this.$search.set(b);var d=this.$search.findAll(this.session);if(!d.length)return 0;this.$blockScrolling+=1;var e=this.multiSelect;c||e.toSingleRange(d[0]);for(var f=d.length;f--;)e.addRange(d[f],!0);return this.$blockScrolling-=1,d.length},this.selectMoreLines=function(a,b){var c=this.selection.toOrientedRange(),d=c.cursor==c.end,f=this.session.documentToScreenPosition(c.cursor);this.selection.$desiredColumn&&(f.column=this.selection.$desiredColumn);var g=this.session.screenToDocumentPosition(f.row+a,f.column);if(!c.isEmpty())var h=this.session.documentToScreenPosition(d?c.end:c.start),i=this.session.screenToDocumentPosition(h.row+a,h.column);else var i=g;if(d){var j=e.fromPoints(g,i);j.cursor=j.start}else{var j=e.fromPoints(i,g);j.cursor=j.end}j.desiredColumn=f.column;if(!this.selection.inMultiSelectMode)this.selection.addRange(c);else if(b)var k=c.cursor;this.selection.addRange(j),k&&this.selection.substractPoint(k)},this.transposeSelections=function(a){var b=this.session,c=b.multiSelect,d=c.ranges;for(var e=d.length;e--;){var f=d[e];if(f.isEmpty()){var g=b.getWordRange(f.start.row,f.start.column);f.start.row=g.start.row,f.start.column=g.start.column,f.end.row=g.end.row,f.end.column=g.end.column}}c.mergeOverlappingRanges();var h=[];for(var e=d.length;e--;){var f=d[e];h.unshift(b.getTextRange(f))}a<0?h.unshift(h.pop()):h.push(h.shift());for(var e=d.length;e--;){var f=d[e],g=f.clone();b.replace(f,h[e]),f.start.row=g.start.row,f.start.column=g.start.column}},this.selectMore=function(a,b){var c=this.session,d=c.multiSelect,e=d.toOrientedRange();if(e.isEmpty()){var e=c.getWordRange(e.start.row,e.start.column);e.cursor=e.end,this.multiSelect.addRange(e)}var f=c.getTextRange(e),g=l(c,f,a);g&&(g.cursor=a==-1?g.start:g.end,this.multiSelect.addRange(g)),b&&this.multiSelect.substractPoint(e.cursor)}}).call(n.prototype),b.onSessionChange=function(a){var b=a.session;b.multiSelect||(b.$selectionMarkers=[],b.selection.$initRangeList(),b.multiSelect=b.selection),this.multiSelect=b.multiSelect;var c=a.oldSession;c&&(c.multiSelect&&c.multiSelect.editor==this&&(c.multiSelect.editor=null),b.multiSelect.removeEventListener(\"addRange\",this.$onAddRange),b.multiSelect.removeEventListener(\"removeRange\",this.$onRemoveRange),b.multiSelect.removeEventListener(\"multiSelect\",this.$onMultiSelect),b.multiSelect.removeEventListener(\"singleSelect\",this.$onSingleSelect)),b.multiSelect.on(\"addRange\",this.$onAddRange),b.multiSelect.on(\"removeRange\",this.$onRemoveRange),b.multiSelect.on(\"multiSelect\",this.$onMultiSelect),b.multiSelect.on(\"singleSelect\",this.$onSingleSelect),this.inMultiSelectMode!=b.selection.inMultiSelectMode&&(b.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},b.MultiSelect=p}),ace.define(\"ace/range_list\",[\"require\",\"exports\",\"module\"],function(a,b,c){var d=function(){this.ranges=[]};(function(){this.comparePoints=function(a,b){return a.row-b.row||a.column-b.column},this.pointIndex=function(a,b){var c=this.ranges;for(var d=b||0;d<c.length;d++){var e=c[d],f=this.comparePoints(a,e.end);if(f>0)continue;return f==0?d:(f=this.comparePoints(a,e.start),f>=0?d:-d-1)}return-d-1},this.add=function(a){var b=this.pointIndex(a.start);b<0&&(b=-b-1);var c=this.pointIndex(a.end,b);return c<0?c=-c-1:c++,this.ranges.splice(b,c-b,a)},this.addList=function(a){var b=[];for(var c=a.length;c--;)b.push.call(b,this.add(a[c]));return b},this.substractPoint=function(a){var b=this.pointIndex(a);if(b>=0)return this.ranges.splice(b,1)},this.merge=function(){var a=[],b=this.ranges,c=b[0],d;for(var e=1;e<b.length;e++){d=c,c=b[e];var f=this.comparePoints(d.end,c.start);if(f<0)continue;if(f==0&&!d.isEmpty()&&!c.isEmpty())continue;this.comparePoints(d.end,c.end)<0&&(d.end.row=c.end.row,d.end.column=c.end.column),b.splice(e,1),a.push(c),c=d,e--}return a},this.contains=function(a,b){return this.pointIndex({row:a,column:b})>=0},this.containsPoint=function(a){return this.pointIndex(a)>=0},this.rangeAtPoint=function(a){var b=this.pointIndex(a);if(b>=0)return this.ranges[b]},this.clipRows=function(a,b){var c=this.ranges;if(c[0].start.row>b||c[c.length-1].start.row<a)return[];var d=this.pointIndex({row:a,column:0});d<0&&(d=-d-1);var e=this.pointIndex({row:b,column:0},d);e<0&&(e=-e-1);var f=[];for(var g=d;g<e;g++)f.push(c[g]);return f},this.removeAll=function(){return this.ranges.splice(0,this.ranges.length)},this.attach=function(a){this.session&&this.detach(),this.session=a,this.onChange=this.$onChange.bind(this),this.session.on(\"change\",this.onChange)},this.detach=function(){if(!this.session)return;this.session.removeListener(\"change\",this.onChange),this.session=null},this.$onChange=function(a){var b=a.data.range;if(a.data.action[0]==\"i\")var c=b.start,d=b.end;else var d=b.start,c=b.end;var e=c.row,f=d.row,g=f-e,h=-c.column+d.column,i=this.ranges;for(var j=0,k=i.length;j<k;j++){var l=i[j];if(l.end.row<e)continue;if(l.start.row>e)break;l.start.row==e&&l.start.column>=c.column&&(l.start.column+=h,l.start.row+=g),l.end.row==e&&l.end.column>=c.column&&(l.end.column+=h,l.end.row+=g)}if(g!=0&&j<k)for(;j<k;j++){var l=i[j];l.start.row+=g,l.end.row+=g}}}).call(d.prototype),b.RangeList=d}),ace.define(\"ace/mouse/multi_select_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\"],function(a,b,c){function e(a,b){return a.row==b.row&&a.column==b.column}function f(a){var b=a.domEvent,c=b.altKey,f=b.shiftKey,g=a.getAccelKey(),h=a.getButton();if(a.editor.inMultiSelectMode&&h==2){a.editor.textInput.onContextMenu(a.domEvent);return}if(!g&&!c){h==0&&a.editor.inMultiSelectMode&&a.editor.exitMultiSelectMode();return}var i=a.editor,j=i.selection,k=i.inMultiSelectMode,l=a.getDocumentPosition(),m=j.getCursor(),n=a.inSelection()||j.isEmpty()&&e(l,m),o=a.x,p=a.y,q=function(a){o=a.clientX,p=a.clientY},r=function(){var a=i.renderer.pixelToScreenCoordinates(o,p),b=s.screenToDocumentPosition(a.row,a.column);if(e(u,a)&&e(b,j.selectionLead))return;u=a,i.selection.moveCursorToPosition(b),i.selection.clearSelection(),i.renderer.scrollCursorIntoView(),i.removeSelectionMarkers(x),x=j.rectangularRangeBlock(u,t),x.forEach(i.addSelectionMarker,i),i.updateSelectionMarkers()},s=i.session,t=i.renderer.pixelToScreenCoordinates(o,p),u=t;if(g&&!f&&!c&&h==0){if(!k&&n)return;if(!k){var v=j.toOrientedRange();i.addSelectionMarker(v)}var w=j.rangeList.rangeAtPoint(l);d.capture(i.container,function(){},function(){var a=j.toOrientedRange();w&&a.isEmpty()&&e(w.cursor,a.cursor)?j.substractPoint(a.cursor):(v&&(i.removeSelectionMarker(v),j.addRange(v)),j.addRange(a))})}else if(!f&&c&&h==0){a.stop(),k&&!g?j.toSingleRange():!k&&g&&j.addRange(),j.moveCursorToPosition(l),j.clearSelection();var x=[],y=function(a){clearInterval(A),i.removeSelectionMarkers(x);for(var b=0;b<x.length;b++)j.addRange(x[b])},z=r;d.capture(i.container,q,y);var A=setInterval(function(){z()},20);return a.preventDefault()}}var d=a(\"../lib/event\");b.onMouseDown=f}),ace.define(\"ace/commands/multi_select_commands\",[\"require\",\"exports\",\"module\",\"ace/keyboard/hash_handler\"],function(a,b,c){b.defaultCommands=[{name:\"addCursorAbove\",exec:function(a){a.selectMoreLines(-1)},bindKey:{win:\"Ctrl-Alt-Up\",mac:\"Ctrl-Alt-Up\"},readonly:!0},{name:\"addCursorBelow\",exec:function(a){a.selectMoreLines(1)},bindKey:{win:\"Ctrl-Alt-Down\",mac:\"Ctrl-Alt-Down\"},readonly:!0},{name:\"addCursorAboveSkipCurrent\",exec:function(a){a.selectMoreLines(-1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Up\",mac:\"Ctrl-Alt-Shift-Up\"},readonly:!0},{name:\"addCursorBelowSkipCurrent\",exec:function(a){a.selectMoreLines(1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Down\",mac:\"Ctrl-Alt-Shift-Down\"},readonly:!0},{name:\"selectMoreBefore\",exec:function(a){a.selectMore(-1)},bindKey:{win:\"Ctrl-Alt-Left\",mac:\"Ctrl-Alt-Left\"},readonly:!0},{name:\"selectMoreAfter\",exec:function(a){a.selectMore(1)},bindKey:{win:\"Ctrl-Alt-Right\",mac:\"Ctrl-Alt-Right\"},readonly:!0},{name:\"selectNextBefore\",exec:function(a){a.selectMore(-1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Left\",mac:\"Ctrl-Alt-Shift-Left\"},readonly:!0},{name:\"selectNextAfter\",exec:function(a){a.selectMore(1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Right\",mac:\"Ctrl-Alt-Shift-Right\"},readonly:!0},{name:\"splitIntoLines\",exec:function(a){a.multiSelect.splitIntoLines()},bindKey:{win:\"Ctrl-Shift-L\",mac:\"Ctrl-Shift-L\"},readonly:!0}],b.multiSelectCommands=[{name:\"singleSelection\",bindKey:\"esc\",exec:function(a){a.exitMultiSelectMode()},readonly:!0,isAvailable:function(a){return a&&a.inMultiSelectMode}}];var d=a(\"../keyboard/hash_handler\").HashHandler;b.keyboardHandler=new d(b.multiSelectCommands)}),ace.define(\"ace/worker/worker_client\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\",\"ace/config\"],function(a,b,c){var d=a(\"../lib/oop\"),e=a(\"../lib/event_emitter\").EventEmitter,f=a(\"../config\"),g=function(b,c,d){this.changeListener=this.changeListener.bind(this);if(f.get(\"packaged\"))this.$worker=new Worker(f.moduleUrl(c,\"worker\"));else{var e;typeof a.supports!=\"undefined\"&&a.supports.indexOf(\"ucjs2-pinf-0\")>=0?e=a.nameToUrl(\"ace/worker/worker_sourcemint\"):(a.nameToUrl&&!a.toUrl&&(a.toUrl=a.nameToUrl),e=this.$normalizePath(a.toUrl(\"ace/worker/worker\",null,\"_\"))),this.$worker=new Worker(e);var g={};for(var h=0;h<b.length;h++){var i=b[h],j=this.$normalizePath(a.toUrl(i,null,\"_\").replace(/.js(\\?.*)?$/,\"\"));g[i]=j}}this.$worker.postMessage({init:!0,tlns:g,module:c,classname:d}),this.callbackId=1,this.callbacks={};var k=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case\"log\":window.console&&console.log&&console.log(b.data);break;case\"event\":k._emit(b.name,{data:b.data});break;case\"call\":var c=k.callbacks[b.id];c&&(c(b.data),delete k.callbacks[b.id])}}};(function(){d.implement(this,e),this.$normalizePath=function(a){return location.host?(a=a.replace(/^[a-z]+:\\/\\/[^\\/]+/,\"\"),a=location.protocol+\"//\"+location.host+(a.charAt(0)==\"/\"?\"\":location.pathname.replace(/\\/[^\\/]*$/,\"\"))+\"/\"+a.replace(/^[\\/]+/,\"\"),a):a},this.terminate=function(){this._emit(\"terminate\",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener(\"change\",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call(\"setValue\",[a.getValue()]),a.on(\"change\",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit(\"change\",a)}}).call(g.prototype),b.WorkerClient=g}),ace.define(\"ace/keyboard/state_handler\",[\"require\",\"exports\",\"module\"],function(a,b,c){function e(a){this.keymapping=this.$buildKeymappingRegex(a)}var d=!1;e.prototype={$buildKeymappingRegex:function(a){for(var b in a)this.$buildBindingsRegex(a[b]);return a},$buildBindingsRegex:function(a){a.forEach(function(a){a.key?a.key=new RegExp(\"^\"+a.key+\"$\"):Array.isArray(a.regex)?(\"key\"in a||(a.key=new RegExp(\"^\"+a.regex[1]+\"$\")),a.regex=new RegExp(a.regex.join(\"\")+\"$\")):a.regex&&(a.regex=new RegExp(a.regex+\"$\"))})},$composeBuffer:function(a,b,c,d){if(a.state==null||a.buffer==null)a.state=\"start\",a.buffer=\"\";var e=[];b&1&&e.push(\"ctrl\"),b&8&&e.push(\"command\"),b&2&&e.push(\"option\"),b&4&&e.push(\"shift\"),c&&e.push(c);var f=e.join(\"-\"),g=a.buffer+f;b!=2&&(a.buffer=g);var h={bufferToUse:g,symbolicName:f};return d&&(h.keyIdentifier=d.keyIdentifier),h},$find:function(a,b,c,e,f,g){var h={};return this.keymapping[a.state].some(function(i){var j;if(i.key&&!i.key.test(c))return!1;if(i.regex&&!(j=i.regex.exec(b)))return!1;if(i.match&&!i.match(b,e,f,c,g))return!1;if(i.disallowMatches)for(var k=0;k<i.disallowMatches.length;k++)if(!!j[i.disallowMatches[k]])return!1;if(i.exec){h.command=i.exec;if(i.params){var l;h.args={},i.params.forEach(function(a){a.match!=null&&j!=null?l=j[a.match]||a.defaultValue:l=a.defaultValue,a.type===\"number\"&&(l=parseInt(l)),h.args[a.name]=l})}a.buffer=\"\"}return i.then&&(a.state=i.then,a.buffer=\"\"),h.command==null&&(h.command=\"null\"),d&&console.log(\"KeyboardStateMapper#find\",i),!0}),h.command?h:(a.buffer=\"\",!1)},handleKeyboard:function(a,b,c,e,f){b==-1&&(b=0);if(b==0||c!=\"\"&&c!=String.fromCharCode(0)){var g=this.$composeBuffer(a,b,c,f),h=g.bufferToUse,i=g.symbolicName,j=g.keyIdentifier;return g=this.$find(a,h,i,b,c,j),d&&console.log(\"KeyboardStateMapper#match\",h,i,g),g}return null}},b.matchCharacterOnly=function(a,b,c,d){return b==0?!0:b==4&&c.length==1?!0:!1},b.StateHandler=e}),ace.define(\"ace/placeholder\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/lib/oop\"],function(a,b,c){var d=a(\"./range\").Range,e=a(\"./lib/event_emitter\").EventEmitter,f=a(\"./lib/oop\"),g=function(a,b,c,d,e,f){var g=this;this.length=b,this.session=a,this.doc=a.getDocument(),this.mainClass=e,this.othersClass=f,this.$onUpdate=this.onUpdate.bind(this),this.doc.on(\"change\",this.$onUpdate),this.$others=d,this.$onCursorChange=function(){setTimeout(function(){g.onCursorChange()})},this.$pos=c;var h=a.getUndoManager().$undoStack||a.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=h.length,this.setup(),a.selection.on(\"changeCursor\",this.$onCursorChange)};(function(){f.implement(this,e),this.setup=function(){var a=this,b=this.doc,c=this.session,e=this.$pos;this.pos=b.createAnchor(e.row,e.column),this.markerId=c.addMarker(new d(e.row,e.column,e.row,e.column+this.length),this.mainClass,null,!1),this.pos.on(\"change\",function(b){c.removeMarker(a.markerId),a.markerId=c.addMarker(new d(b.value.row,b.value.column,b.value.row,b.value.column+a.length),a.mainClass,null,!1)}),this.others=[],this.$others.forEach(function(c){var d=b.createAnchor(c.row,c.column);a.others.push(d)}),c.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var a=this.session,b=this;this.othersActive=!0,this.others.forEach(function(c){c.markerId=a.addMarker(new d(c.row,c.column,c.row,c.column+b.length),b.othersClass,null,!1),c.on(\"change\",function(e){a.removeMarker(c.markerId),c.markerId=a.addMarker(new d(e.value.row,e.value.column,e.value.row,e.value.column+b.length),b.othersClass,null,!1)})})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var a=0;a<this.others.length;a++)this.session.removeMarker(this.others[a].markerId)},this.onUpdate=function(a){var b=a.data,c=b.range;if(c.start.row!==c.end.row)return;if(c.start.row!==this.pos.row)return;if(this.$updating)return;this.$updating=!0;var e=b.action===\"insertText\"?c.end.column-c.start.column:c.start.column-c.end.column;if(c.start.column>=this.pos.column&&c.start.column<=this.pos.column+this.length+1){var f=c.start.column-this.pos.column;this.length+=e;if(!this.session.$fromUndo){if(b.action===\"insertText\")for(var g=this.others.length-1;g>=0;g--){var h=this.others[g],i={row:h.row,column:h.column+f};h.row===c.start.row&&c.start.column<h.column&&(i.column+=e),this.doc.insert(i,b.text)}else if(b.action===\"removeText\")for(var g=this.others.length-1;g>=0;g--){var h=this.others[g],i={row:h.row,column:h.column+f};h.row===c.start.row&&c.start.column<h.column&&(i.column+=e),this.doc.remove(new d(i.row,i.column,i.row,i.column-e))}c.start.column===this.pos.column&&b.action===\"insertText\"?setTimeout(function(){this.pos.setPosition(this.pos.row,this.pos.column-e);for(var a=0;a<this.others.length;a++){var b=this.others[a],d={row:b.row,column:b.column-e};b.row===c.start.row&&c.start.column<b.column&&(d.column+=e),b.setPosition(d.row,d.column)}}.bind(this),0):c.start.column===this.pos.column&&b.action===\"removeText\"&&setTimeout(function(){for(var a=0;a<this.others.length;a++){var b=this.others[a];b.row===c.start.row&&c.start.column<b.column&&b.setPosition(b.row,b.column-e)}}.bind(this),0)}this.pos._emit(\"change\",{value:this.pos});for(var g=0;g<this.others.length;g++)this.others[g]._emit(\"change\",{value:this.others[g]})}this.$updating=!1},this.onCursorChange=function(a){if(this.$updating)return;var b=this.session.selection.getCursor();b.row===this.pos.row&&b.column>=this.pos.column&&b.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit(\"cursorEnter\",a)):(this.hideOtherMarkers(),this._emit(\"cursorLeave\",a))},this.detach=function(){this.session.removeMarker(this.markerId),this.hideOtherMarkers(),this.doc.removeEventListener(\"change\",this.$onUpdate),this.session.selection.removeEventListener(\"changeCursor\",this.$onCursorChange),this.pos.detach();for(var a=0;a<this.others.length;a++)this.others[a].detach();this.session.setUndoSelect(!0)},this.cancel=function(){if(this.$undoStackDepth===-1)throw Error(\"Canceling placeholders only supported with undo manager attached to session.\");var a=this.session.getUndoManager(),b=(a.$undoStack||a.$undostack).length-this.$undoStackDepth;for(var c=0;c<b;c++)a.undo(!0)}}).call(g.prototype),b.PlaceHolder=g}),ace.define(\"ace/theme/textmate\",[\"require\",\"exports\",\"module\",\"ace/requirejs/text!ace/theme/textmate.css\",\"ace/lib/dom\"],function(a,b,c){b.isDark=!1,b.cssClass=\"ace-tm\",b.cssText=a(\"ace/requirejs/text!./textmate.css\");var d=a(\"../lib/dom\");d.importCssString(b.cssText,b.cssClass)}),ace.define(\"ace/requirejs/text!ace/theme/textmate.css\",[],'.ace-tm .ace_editor {\\n  border: 2px solid rgb(159, 159, 159);\\n}\\n\\n.ace-tm .ace_editor.ace_focus {\\n  border: 2px solid #327fbd;\\n}\\n\\n.ace-tm .ace_gutter {\\n  background: #f0f0f0;\\n  color: #333;\\n}\\n\\n.ace-tm .ace_print_margin {\\n  width: 1px;\\n  background: #e8e8e8;\\n}\\n\\n.ace-tm .ace_fold {\\n    background-color: #6B72E6;\\n}\\n\\n.ace-tm .ace_text-layer {\\n}\\n\\n.ace-tm .ace_cursor {\\n  border-left: 2px solid black;\\n}\\n\\n.ace-tm .ace_cursor.ace_overwrite {\\n  border-left: 0px;\\n  border-bottom: 1px solid black;\\n}\\n        \\n.ace-tm .ace_line .ace_invisible {\\n  color: rgb(191, 191, 191);\\n}\\n\\n.ace-tm .ace_line .ace_storage,\\n.ace-tm .ace_line .ace_keyword {\\n  color: blue;\\n}\\n\\n.ace-tm .ace_line .ace_constant {\\n  color: rgb(197, 6, 11);\\n}\\n\\n.ace-tm .ace_line .ace_constant.ace_buildin {\\n  color: rgb(88, 72, 246);\\n}\\n\\n.ace-tm .ace_line .ace_constant.ace_language {\\n  color: rgb(88, 92, 246);\\n}\\n\\n.ace-tm .ace_line .ace_constant.ace_library {\\n  color: rgb(6, 150, 14);\\n}\\n\\n.ace-tm .ace_line .ace_invalid {\\n  background-color: rgba(255, 0, 0, 0.1);\\n  color: red;\\n}\\n\\n.ace-tm .ace_line .ace_support.ace_function {\\n  color: rgb(60, 76, 114);\\n}\\n\\n.ace-tm .ace_line .ace_support.ace_constant {\\n  color: rgb(6, 150, 14);\\n}\\n\\n.ace-tm .ace_line .ace_support.ace_type,\\n.ace-tm .ace_line .ace_support.ace_class {\\n  color: rgb(109, 121, 222);\\n}\\n\\n.ace-tm .ace_line .ace_keyword.ace_operator {\\n  color: rgb(104, 118, 135);\\n}\\n\\n.ace-tm .ace_line .ace_string {\\n  color: rgb(3, 106, 7);\\n}\\n\\n.ace-tm .ace_line .ace_comment {\\n  color: rgb(76, 136, 107);\\n}\\n\\n.ace-tm .ace_line .ace_comment.ace_doc {\\n  color: rgb(0, 102, 255);\\n}\\n\\n.ace-tm .ace_line .ace_comment.ace_doc.ace_tag {\\n  color: rgb(128, 159, 191);\\n}\\n\\n.ace-tm .ace_line .ace_constant.ace_numeric {\\n  color: rgb(0, 0, 205);\\n}\\n\\n.ace-tm .ace_line .ace_variable {\\n  color: rgb(49, 132, 149);\\n}\\n\\n.ace-tm .ace_line .ace_xml_pe {\\n  color: rgb(104, 104, 91);\\n}\\n\\n.ace-tm .ace_entity.ace_name.ace_function {\\n  color: #0000A2;\\n}\\n\\n.ace-tm .ace_markup.ace_markupine {\\n    text-decoration:underline;\\n}\\n\\n.ace-tm .ace_markup.ace_heading {\\n  color: rgb(12, 7, 255);\\n}\\n\\n.ace-tm .ace_markup.ace_list {\\n  color:rgb(185, 6, 144);\\n}\\n\\n.ace-tm .ace_marker-layer .ace_selection {\\n  background: rgb(181, 213, 255);\\n}\\n.ace-tm.multiselect .ace_selection.start {\\n  box-shadow: 0 0 3px 0px white;\\n  border-radius: 2px;\\n}\\n.ace-tm .ace_marker-layer .ace_step {\\n  background: rgb(252, 255, 0);\\n}\\n\\n.ace-tm .ace_marker-layer .ace_stack {\\n  background: rgb(164, 229, 101);\\n}\\n\\n.ace-tm .ace_marker-layer .ace_bracket {\\n  margin: -1px 0 0 -1px;\\n  border: 1px solid rgb(192, 192, 192);\\n}\\n\\n.ace-tm .ace_marker-layer .ace_active_line {\\n  background: rgba(0, 0, 0, 0.07);\\n}\\n\\n.ace-tm .ace_gutter_active_line {\\n    background-color : #dcdcdc;\\n}\\n\\n.ace-tm .ace_marker-layer .ace_selected_word {\\n  background: rgb(250, 250, 255);\\n  border: 1px solid rgb(200, 200, 250);\\n}\\n\\n.ace-tm .ace_meta.ace_tag {\\n  color:rgb(0, 22, 142);\\n}\\n\\n.ace-tm .ace_string.ace_regex {\\n  color: rgb(255, 0, 0)\\n}\\n\\n.ace-tm .ace_indent-guide {\\n  background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\\n}\\n');\n            (function() {\n                ace.require([\"ace/ace\"], function(a) {\n                    a && a.config.init();\n                    if (!window.ace)\n                        window.ace = {};\n                    for (var key in a) if (a.hasOwnProperty(key))\n                        ace[key] = a[key];\n                });\n            })();\n        "
  },
  {
    "path": "togetherjs/tests/codemirror4.js",
    "content": "/* CodeMirror - Minified & Bundled\n   Generated on 8/20/2014 with http://codemirror.net/doc/compress.html\n   Version: 4.4\n\n   CodeMirror Library:\n   - codemirror.js\n   Modes:\n   - htmlembedded.js\n   - htmlmixed.js\n   - javascript.js\n */\n\n!function(a){if(\"object\"==typeof exports&&\"object\"==typeof module)module.exports=a();else{if(\"function\"==typeof define&&define.amd)return define([],a);this.CodeMirror=a()}}(function(){\"use strict\";function w(a,b){if(!(this instanceof w))return new w(a,b);this.options=b=b||{},Og(ie,b,!1),K(b);var c=b.value;\"string\"==typeof c&&(c=new Jf(c,b.mode)),this.doc=c;var f=this.display=new x(a,c);f.wrapper.CodeMirror=this,G(this),E(this),b.lineWrapping&&(this.display.wrapper.className+=\" CodeMirror-wrap\"),b.autofocus&&!o&&_c(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,draggingText:!1,highlight:new Eg},d&&11>e&&setTimeout(Pg($c,this,!0),20),cd(this),gh();var g=this;Jc(this,function(){g.curOp.forceUpdate=!0,Nf(g,c),b.autofocus&&!o||_g()==f.input?setTimeout(Pg(Gd,g),20):Hd(g);for(var a in je)je.hasOwnProperty(a)&&je[a](g,b[a],le);Q(g);for(var d=0;d<pe.length;++d)pe[d](g)})}function x(a,b){var c=this,g=c.input=Wg(\"textarea\",null,null,\"position: absolute; padding: 0; width: 1px; height: 1em; outline: none\");f?g.style.width=\"1000px\":g.setAttribute(\"wrap\",\"off\"),n&&(g.style.border=\"1px solid black\"),g.setAttribute(\"autocorrect\",\"off\"),g.setAttribute(\"autocapitalize\",\"off\"),g.setAttribute(\"spellcheck\",\"false\"),c.inputDiv=Wg(\"div\",[g],null,\"overflow: hidden; position: relative; width: 3px; height: 0px;\"),c.scrollbarH=Wg(\"div\",[Wg(\"div\",null,null,\"height: 100%; min-height: 1px\")],\"CodeMirror-hscrollbar\"),c.scrollbarV=Wg(\"div\",[Wg(\"div\",null,null,\"min-width: 1px\")],\"CodeMirror-vscrollbar\"),c.scrollbarFiller=Wg(\"div\",null,\"CodeMirror-scrollbar-filler\"),c.gutterFiller=Wg(\"div\",null,\"CodeMirror-gutter-filler\"),c.lineDiv=Wg(\"div\",null,\"CodeMirror-code\"),c.selectionDiv=Wg(\"div\",null,null,\"position: relative; z-index: 1\"),c.cursorDiv=Wg(\"div\",null,\"CodeMirror-cursors\"),c.measure=Wg(\"div\",null,\"CodeMirror-measure\"),c.lineMeasure=Wg(\"div\",null,\"CodeMirror-measure\"),c.lineSpace=Wg(\"div\",[c.measure,c.lineMeasure,c.selectionDiv,c.cursorDiv,c.lineDiv],null,\"position: relative; outline: none\"),c.mover=Wg(\"div\",[Wg(\"div\",[c.lineSpace],\"CodeMirror-lines\")],null,\"position: relative\"),c.sizer=Wg(\"div\",[c.mover],\"CodeMirror-sizer\"),c.heightForcer=Wg(\"div\",null,null,\"position: absolute; height: \"+zg+\"px; width: 1px;\"),c.gutters=Wg(\"div\",null,\"CodeMirror-gutters\"),c.lineGutter=null,c.scroller=Wg(\"div\",[c.sizer,c.heightForcer,c.gutters],\"CodeMirror-scroll\"),c.scroller.setAttribute(\"tabIndex\",\"-1\"),c.wrapper=Wg(\"div\",[c.inputDiv,c.scrollbarH,c.scrollbarV,c.scrollbarFiller,c.gutterFiller,c.scroller],\"CodeMirror\"),d&&8>e&&(c.gutters.style.zIndex=-1,c.scroller.style.paddingRight=0),n&&(g.style.width=\"0px\"),f||(c.scroller.draggable=!0),k&&(c.inputDiv.style.height=\"1px\",c.inputDiv.style.position=\"absolute\"),d&&8>e&&(c.scrollbarH.style.minHeight=c.scrollbarV.style.minWidth=\"18px\"),a.appendChild?a.appendChild(c.wrapper):a(c.wrapper),c.viewFrom=c.viewTo=b.first,c.view=[],c.externalMeasured=null,c.viewOffset=0,c.lastSizeC=0,c.updateLineNumbers=null,c.lineNumWidth=c.lineNumInnerWidth=c.lineNumChars=null,c.prevInput=\"\",c.alignWidgets=!1,c.pollingFast=!1,c.poll=new Eg,c.cachedCharWidth=c.cachedTextHeight=c.cachedPaddingH=null,c.inaccurateSelection=!1,c.maxLine=null,c.maxLineLength=0,c.maxLineChanged=!1,c.wheelDX=c.wheelDY=c.wheelStartX=c.wheelStartY=null,c.shift=!1,c.selForContextMenu=null}function y(a){a.doc.mode=w.getMode(a.options,a.doc.modeOption),z(a)}function z(a){a.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),a.doc.frontier=a.doc.first,Tb(a,100),a.state.modeGen++,a.curOp&&Pc(a)}function A(a){a.options.lineWrapping?(ch(a.display.wrapper,\"CodeMirror-wrap\"),a.display.sizer.style.minWidth=\"\"):(bh(a.display.wrapper,\"CodeMirror-wrap\"),J(a)),C(a),Pc(a),kc(a),setTimeout(function(){N(a)},100)}function B(a){var b=wc(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/xc(a.display)-3);return function(e){if(df(a.doc,e))return 0;var f=0;if(e.widgets)for(var g=0;g<e.widgets.length;g++)e.widgets[g].height&&(f+=e.widgets[g].height);return c?f+(Math.ceil(e.text.length/d)||1)*b:f+b}}function C(a){var b=a.doc,c=B(a);b.iter(function(a){var b=c(a);b!=a.height&&Rf(a,b)})}function D(a){var b=ue[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 E(a){a.display.wrapper.className=a.display.wrapper.className.replace(/\\s*cm-s-\\S+/g,\"\")+a.options.theme.replace(/(^|\\s)\\s*/g,\" cm-s-\"),kc(a)}function F(a){G(a),Pc(a),setTimeout(function(){P(a)},20)}function G(a){var b=a.display.gutters,c=a.options.gutters;Yg(b);for(var d=0;d<c.length;++d){var e=c[d],f=b.appendChild(Wg(\"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\",H(a)}function H(a){var b=a.display.gutters.offsetWidth;a.display.sizer.style.marginLeft=b+\"px\",a.display.scrollbarH.style.left=a.options.fixedGutter?b+\"px\":0}function I(a){if(0==a.height)return 0;for(var c,b=a.text.length,d=a;c=Ye(d);){var e=c.find(0,!0);d=e.from.line,b+=e.from.ch-e.to.ch}for(d=a;c=Ze(d);){var e=c.find(0,!0);b-=d.text.length-e.from.ch,d=e.to.line,b+=d.text.length-e.to.ch}return b}function J(a){var b=a.display,c=a.doc;b.maxLine=Of(c,c.first),b.maxLineLength=I(b.maxLine),b.maxLineChanged=!0,c.iter(function(a){var c=I(a);c>b.maxLineLength&&(b.maxLineLength=c,b.maxLine=a)})}function K(a){var b=Lg(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 L(a){return a.display.scroller.clientHeight-a.display.wrapper.clientHeight<zg-3}function M(a){var b=a.display.scroller;return{clientHeight:b.clientHeight,barHeight:a.display.scrollbarV.clientHeight,scrollWidth:b.scrollWidth,clientWidth:b.clientWidth,hScrollbarTakesSpace:L(a),barWidth:a.display.scrollbarH.clientWidth,docHeight:Math.round(a.doc.height+Yb(a.display))}}function N(a,b){b||(b=M(a));var c=a.display,d=kh(c.measure),e=b.docHeight+zg,f=b.scrollWidth>b.clientWidth;f&&b.scrollWidth<=b.clientWidth+1&&d>0&&!b.hScrollbarTakesSpace&&(f=!1);var g=e>b.clientHeight;if(g?(c.scrollbarV.style.display=\"block\",c.scrollbarV.style.bottom=f?d+\"px\":\"0\",c.scrollbarV.firstChild.style.height=Math.max(0,e-b.clientHeight+(b.barHeight||c.scrollbarV.clientHeight))+\"px\"):(c.scrollbarV.style.display=\"\",c.scrollbarV.firstChild.style.height=\"0\"),f?(c.scrollbarH.style.display=\"block\",c.scrollbarH.style.right=g?d+\"px\":\"0\",c.scrollbarH.firstChild.style.width=b.scrollWidth-b.clientWidth+(b.barWidth||c.scrollbarH.clientWidth)+\"px\"):(c.scrollbarH.style.display=\"\",c.scrollbarH.firstChild.style.width=\"0\"),f&&g?(c.scrollbarFiller.style.display=\"block\",c.scrollbarFiller.style.height=c.scrollbarFiller.style.width=d+\"px\"):c.scrollbarFiller.style.display=\"\",f&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(c.gutterFiller.style.display=\"block\",c.gutterFiller.style.height=d+\"px\",c.gutterFiller.style.width=c.gutters.offsetWidth+\"px\"):c.gutterFiller.style.display=\"\",!a.state.checkedOverlayScrollbar&&b.clientHeight>0){if(0===d){var h=p&&!l?\"12px\":\"18px\";c.scrollbarV.style.minWidth=c.scrollbarH.style.minHeight=h;var i=function(b){ng(b)!=c.scrollbarV&&ng(b)!=c.scrollbarH&&Kc(a,gd)(b)};pg(c.scrollbarV,\"mousedown\",i),pg(c.scrollbarH,\"mousedown\",i)}a.state.checkedOverlayScrollbar=!0}}function O(a,b,c){var d=c&&null!=c.top?Math.max(0,c.top):a.scroller.scrollTop;d=Math.floor(d-Xb(a));var e=c&&null!=c.bottom?c.bottom:d+a.wrapper.clientHeight,f=Tf(b,d),g=Tf(b,e);if(c&&c.ensure){var h=c.ensure.from.line,i=c.ensure.to.line;if(f>h)return{from:h,to:Tf(b,Uf(Of(b,h))+a.wrapper.clientHeight)};if(Math.min(i,b.lastLine())>=g)return{from:Tf(b,Uf(Of(b,i))-a.wrapper.clientHeight),to:i}}return{from:f,to:Math.max(g,f+1)}}function P(a){var b=a.display,c=b.view;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var d=S(b)-b.scroller.scrollLeft+a.doc.scrollLeft,e=b.gutters.offsetWidth,f=d+\"px\",g=0;g<c.length;g++)if(!c[g].hidden){a.options.fixedGutter&&c[g].gutter&&(c[g].gutter.style.left=f);var h=c[g].alignable;if(h)for(var i=0;i<h.length;i++)h[i].style.left=f}a.options.fixedGutter&&(b.gutters.style.left=d+e+\"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(Wg(\"div\",[Wg(\"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\",H(a),!0}return!1}function R(a,b){return String(a.lineNumberFormatter(b+a.firstLineNumber))}function S(a){return a.scroller.getBoundingClientRect().left-a.sizer.getBoundingClientRect().left}function T(a,b,c){var d=a.display;this.viewport=b,this.visible=O(d,a.doc,b),this.editorIsHidden=!d.wrapper.offsetWidth,this.wrapperHeight=d.wrapper.clientHeight,this.oldViewFrom=d.viewFrom,this.oldViewTo=d.viewTo,this.oldScrollerWidth=d.scroller.clientWidth,this.force=c,this.dims=_(a)}function U(a,b){var c=a.display,d=a.doc;if(b.editorIsHidden)return Rc(a),!1;if(!b.force&&b.visible.from>=c.viewFrom&&b.visible.to<=c.viewTo&&(null==c.updateLineNumbers||c.updateLineNumbers>=c.viewTo)&&0==Vc(a))return!1;Q(a)&&(Rc(a),b.dims=_(a));var e=d.first+d.size,f=Math.max(b.visible.from-a.options.viewportMargin,d.first),g=Math.min(e,b.visible.to+a.options.viewportMargin);c.viewFrom<f&&f-c.viewFrom<20&&(f=Math.max(d.first,c.viewFrom)),c.viewTo>g&&c.viewTo-g<20&&(g=Math.min(e,c.viewTo)),v&&(f=bf(a.doc,f),g=cf(a.doc,g));var h=f!=c.viewFrom||g!=c.viewTo||c.lastSizeC!=b.wrapperHeight;Uc(a,f,g),c.viewOffset=Uf(Of(a.doc,c.viewFrom)),a.display.mover.style.top=c.viewOffset+\"px\";var i=Vc(a);if(!h&&0==i&&!b.force&&(null==c.updateLineNumbers||c.updateLineNumbers>=c.viewTo))return!1;var j=_g();return i>4&&(c.lineDiv.style.display=\"none\"),ab(a,c.updateLineNumbers,b.dims),i>4&&(c.lineDiv.style.display=\"\"),j&&_g()!=j&&j.offsetHeight&&j.focus(),Yg(c.cursorDiv),Yg(c.selectionDiv),h&&(c.lastSizeC=b.wrapperHeight,Tb(a,400)),c.updateLineNumbers=null,!0}function V(a,b){for(var c=b.force,d=b.viewport,e=!0;;e=!1){if(e&&a.options.lineWrapping&&b.oldScrollerWidth!=a.display.scroller.clientWidth)c=!0;else if(c=!1,d&&null!=d.top&&(d={top:Math.min(a.doc.height+Yb(a.display)-zg-a.display.scroller.clientHeight,d.top)}),b.visible=O(a.display,a.doc,d),b.visible.from>=a.display.viewFrom&&b.visible.to<=a.display.viewTo)break;if(!U(a,b))break;Z(a);var f=M(a);Pb(a),X(a,f),N(a,f)}tg(a,\"update\",a),(a.display.viewFrom!=b.oldViewFrom||a.display.viewTo!=b.oldViewTo)&&tg(a,\"viewportChange\",a,a.display.viewFrom,a.display.viewTo)}function W(a,b){var c=new T(a,b);if(U(a,c)){V(a,c);var d=M(a);Pb(a),X(a,d),N(a,d)}}function X(a,b){a.display.sizer.style.minHeight=a.display.heightForcer.style.top=b.docHeight+\"px\",a.display.gutters.style.height=Math.max(b.docHeight,b.clientHeight-zg)+\"px\"}function Y(a,b){a.display.sizer.offsetWidth+a.display.gutters.offsetWidth<a.display.scroller.clientWidth-1&&(a.display.sizer.style.minHeight=a.display.heightForcer.style.top=\"0px\",a.display.gutters.style.height=b.docHeight+\"px\")}function Z(a){for(var b=a.display,c=b.lineDiv.offsetTop,f=0;f<b.view.length;f++){var h,g=b.view[f];if(!g.hidden){if(d&&8>e){var i=g.node.offsetTop+g.node.offsetHeight;h=i-c,c=i}else{var j=g.node.getBoundingClientRect();h=j.bottom-j.top}var k=g.line.height-h;if(2>h&&(h=wc(b)),(k>.001||-.001>k)&&(Rf(g.line,h),$(g.line),g.rest))for(var l=0;l<g.rest.length;l++)$(g.rest[l])}}}function $(a){if(a.widgets)for(var b=0;b<a.widgets.length;++b)a.widgets[b].height=a.widgets[b].node.offsetHeight}function _(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 ab(a,b,c){function i(b){var c=b.nextSibling;return f&&p&&a.display.currentWheelTarget==b?b.style.display=\"none\":b.parentNode.removeChild(b),c}for(var d=a.display,e=a.options.lineNumbers,g=d.lineDiv,h=g.firstChild,j=d.view,k=d.viewFrom,l=0;l<j.length;l++){var m=j[l];if(m.hidden);else if(m.node){for(;h!=m.node;)h=i(h);var o=e&&null!=b&&k>=b&&m.lineNumber;m.changes&&(Lg(m.changes,\"gutter\")>-1&&(o=!1),bb(a,m,k,c)),o&&(Yg(m.lineNumber),m.lineNumber.appendChild(document.createTextNode(R(a.options,k)))),h=m.node.nextSibling}else{var n=jb(a,m,k,c);g.insertBefore(n,h)}k+=m.size}for(;h;)h=i(h)}function bb(a,b,c,d){for(var e=0;e<b.changes.length;e++){var f=b.changes[e];\"text\"==f?fb(a,b):\"gutter\"==f?hb(a,b,c,d):\"class\"==f?gb(b):\"widget\"==f&&ib(b,d)}b.changes=null}function cb(a){return a.node==a.text&&(a.node=Wg(\"div\",null,null,\"position: relative\"),a.text.parentNode&&a.text.parentNode.replaceChild(a.node,a.text),a.node.appendChild(a.text),d&&8>e&&(a.node.style.zIndex=2)),a.node}function db(a){var b=a.bgClass?a.bgClass+\" \"+(a.line.bgClass||\"\"):a.line.bgClass;if(b&&(b+=\" CodeMirror-linebackground\"),a.background)b?a.background.className=b:(a.background.parentNode.removeChild(a.background),a.background=null);else if(b){var c=cb(a);a.background=c.insertBefore(Wg(\"div\",null,b),c.firstChild)}}function eb(a,b){var c=a.display.externalMeasured;return c&&c.line==b.line?(a.display.externalMeasured=null,b.measure=c.measure,c.built):xf(a,b)}function fb(a,b){var c=b.text.className,d=eb(a,b);b.text==b.node&&(b.node=d.pre),b.text.parentNode.replaceChild(d.pre,b.text),b.text=d.pre,d.bgClass!=b.bgClass||d.textClass!=b.textClass?(b.bgClass=d.bgClass,b.textClass=d.textClass,gb(b)):c&&(b.text.className=c)}function gb(a){db(a),a.line.wrapClass?cb(a).className=a.line.wrapClass:a.node!=a.text&&(a.node.className=\"\");var b=a.textClass?a.textClass+\" \"+(a.line.textClass||\"\"):a.line.textClass;a.text.className=b||\"\"}function hb(a,b,c,d){b.gutter&&(b.node.removeChild(b.gutter),b.gutter=null);var e=b.line.gutterMarkers;if(a.options.lineNumbers||e){var f=cb(b),g=b.gutter=f.insertBefore(Wg(\"div\",null,\"CodeMirror-gutter-wrapper\",\"position: absolute; left: \"+(a.options.fixedGutter?d.fixedPos:-d.gutterTotalWidth)+\"px\"),b.text);if(!a.options.lineNumbers||e&&e[\"CodeMirror-linenumbers\"]||(b.lineNumber=g.appendChild(Wg(\"div\",R(a.options,c),\"CodeMirror-linenumber CodeMirror-gutter-elt\",\"left: \"+d.gutterLeft[\"CodeMirror-linenumbers\"]+\"px; width: \"+a.display.lineNumInnerWidth+\"px\"))),e)for(var h=0;h<a.options.gutters.length;++h){var i=a.options.gutters[h],j=e.hasOwnProperty(i)&&e[i];j&&g.appendChild(Wg(\"div\",[j],\"CodeMirror-gutter-elt\",\"left: \"+d.gutterLeft[i]+\"px; width: \"+d.gutterWidth[i]+\"px\"))}}}function ib(a,b){a.alignable&&(a.alignable=null);for(var d,c=a.node.firstChild;c;c=d){var d=c.nextSibling;\"CodeMirror-linewidget\"==c.className&&a.node.removeChild(c)}kb(a,b)}function jb(a,b,c,d){var e=eb(a,b);return b.text=b.node=e.pre,e.bgClass&&(b.bgClass=e.bgClass),e.textClass&&(b.textClass=e.textClass),gb(b),hb(a,b,c,d),kb(b,d),b.node}function kb(a,b){if(lb(a.line,a,b,!0),a.rest)for(var c=0;c<a.rest.length;c++)lb(a.rest[c],a,b,!1)}function lb(a,b,c,d){if(a.widgets)for(var e=cb(b),f=0,g=a.widgets;f<g.length;++f){var h=g[f],i=Wg(\"div\",[h.node],\"CodeMirror-linewidget\");h.handleMouseEvents||(i.ignoreEvents=!0),mb(h,i,b,c),d&&h.above?e.insertBefore(i,b.gutter||b.text):e.appendChild(i),tg(h,\"redraw\")}}function mb(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 pb(a){return nb(a.line,a.ch)}function qb(a,b){return ob(a,b)<0?b:a}function rb(a,b){return ob(a,b)<0?a:b}function sb(a,b){this.ranges=a,this.primIndex=b}function tb(a,b){this.anchor=a,this.head=b}function ub(a,b){var c=a[b];a.sort(function(a,b){return ob(a.from(),b.from())}),b=Lg(a,c);for(var d=1;d<a.length;d++){var e=a[d],f=a[d-1];if(ob(f.to(),e.from())>=0){var g=rb(f.from(),e.from()),h=qb(f.to(),e.to()),i=f.empty()?e.from()==e.head:f.from()==f.head;b>=d&&--b,a.splice(--d,2,new tb(i?h:g,i?g:h))}}return new sb(a,b)}function vb(a,b){return new sb([new tb(a,b||a)],0)}function wb(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function xb(a,b){if(b.line<a.first)return nb(a.first,0);var c=a.first+a.size-1;return b.line>c?nb(c,Of(a,c).text.length):yb(b,Of(a,b.line).text.length)}function yb(a,b){var c=a.ch;return null==c||c>b?nb(a.line,b):0>c?nb(a.line,0):a}function zb(a,b){return b>=a.first&&b<a.first+a.size}function Ab(a,b){for(var c=[],d=0;d<b.length;d++)c[d]=xb(a,b[d]);return c}function Bb(a,b,c,d){if(a.cm&&a.cm.display.shift||a.extend){var e=b.anchor;if(d){var f=ob(c,e)<0;f!=ob(d,e)<0?(e=c,c=d):f!=ob(c,d)<0&&(c=d)}return new tb(e,c)}return new tb(d||c,c)}function Cb(a,b,c,d){Ib(a,new sb([Bb(a,a.sel.primary(),b,c)],0),d)}function Db(a,b,c){for(var d=[],e=0;e<a.sel.ranges.length;e++)d[e]=Bb(a,a.sel.ranges[e],b[e],null);var f=ub(d,a.sel.primIndex);Ib(a,f,c)}function Eb(a,b,c,d){var e=a.sel.ranges.slice(0);e[b]=c,Ib(a,ub(e,a.sel.primIndex),d)}function Fb(a,b,c,d){Ib(a,vb(b,c),d)}function Gb(a,b){var c={ranges:b.ranges,update:function(b){this.ranges=[];for(var c=0;c<b.length;c++)this.ranges[c]=new tb(xb(a,b[c].anchor),xb(a,b[c].head))}};return rg(a,\"beforeSelectionChange\",a,c),a.cm&&rg(a.cm,\"beforeSelectionChange\",a.cm,c),c.ranges!=b.ranges?ub(c.ranges,c.ranges.length-1):b}function Hb(a,b,c){var d=a.history.done,e=Jg(d);e&&e.ranges?(d[d.length-1]=b,Jb(a,b,c)):Ib(a,b,c)}function Ib(a,b,c){Jb(a,b,c),ag(a,a.sel,a.cm?a.cm.curOp.id:0/0,c)}function Jb(a,b,c){(xg(a,\"beforeSelectionChange\")||a.cm&&xg(a.cm,\"beforeSelectionChange\"))&&(b=Gb(a,b));var d=c&&c.bias||(ob(b.primary().head,a.sel.primary().head)<0?-1:1);Kb(a,Mb(a,b,d,!0)),c&&c.scroll===!1||!a.cm||ae(a.cm)}function Kb(a,b){b.equals(a.sel)||(a.sel=b,a.cm&&(a.cm.curOp.updateInput=a.cm.curOp.selectionChanged=!0,wg(a.cm)),tg(a,\"cursorActivity\",a))}function Lb(a){Kb(a,Mb(a,a.sel,null,!1),Bg)}function Mb(a,b,c,d){for(var e,f=0;f<b.ranges.length;f++){var g=b.ranges[f],h=Nb(a,g.anchor,c,d),i=Nb(a,g.head,c,d);(e||h!=g.anchor||i!=g.head)&&(e||(e=b.ranges.slice(0,f)),e[f]=new tb(h,i))}return e?ub(e,b.primIndex):b}function Nb(a,b,c,d){var e=!1,f=b,g=c||1;a.cantEdit=!1;a:for(;;){var h=Of(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&&(rg(k,\"beforeCursorEnter\"),k.explicitlyCleared)){if(h.markedSpans){--i;continue}break}if(!k.atomic)continue;var l=k.find(0>g?-1:1);if(0==ob(l,f)&&(l.ch+=g,l.ch<0?l=l.line>a.first?xb(a,nb(l.line-1)):null:l.ch>h.text.length&&(l=l.line<a.first+a.size-1?nb(l.line+1,0):null),!l)){if(e)return d?(a.cantEdit=!0,nb(a.first,0)):Nb(a,b,c,!0);e=!0,l=b,g=-g}f=l;continue a}}return f}}function Ob(a){for(var b=a.display,c=a.doc,d={},e=d.cursors=document.createDocumentFragment(),f=d.selection=document.createDocumentFragment(),g=0;g<c.sel.ranges.length;g++){var h=c.sel.ranges[g],i=h.empty();(i||a.options.showCursorWhenSelecting)&&Qb(a,h,e),i||Rb(a,h,f)}if(a.options.moveInputWithCursor){var j=qc(a,c.sel.primary().head,\"div\"),k=b.wrapper.getBoundingClientRect(),l=b.lineDiv.getBoundingClientRect();d.teTop=Math.max(0,Math.min(b.wrapper.clientHeight-10,j.top+l.top-k.top)),d.teLeft=Math.max(0,Math.min(b.wrapper.clientWidth-10,j.left+l.left-k.left))}return d}function Pb(a,b){b||(b=Ob(a)),Zg(a.display.cursorDiv,b.cursors),Zg(a.display.selectionDiv,b.selection),null!=b.teTop&&(a.display.inputDiv.style.top=b.teTop+\"px\",a.display.inputDiv.style.left=b.teLeft+\"px\")}function Qb(a,b,c){var d=qc(a,b.head,\"div\",null,null,!a.options.singleCursorHeightPerLine),e=c.appendChild(Wg(\"div\",\"\\xa0\",\"CodeMirror-cursor\"));if(e.style.left=d.left+\"px\",e.style.top=d.top+\"px\",e.style.height=Math.max(0,d.bottom-d.top)*a.options.cursorHeight+\"px\",d.other){var f=c.appendChild(Wg(\"div\",\"\\xa0\",\"CodeMirror-cursor CodeMirror-secondarycursor\"));f.style.display=\"\",f.style.left=d.other.left+\"px\",f.style.top=d.other.top+\"px\",f.style.height=.85*(d.other.bottom-d.other.top)+\"px\"}}function Rb(a,b,c){function j(a,b,c,d){0>b&&(b=0),b=Math.round(b),d=Math.round(d),f.appendChild(Wg(\"div\",null,\"CodeMirror-selected\",\"position: absolute; left: \"+a+\"px; top: \"+b+\"px; width: \"+(null==c?i-a:c)+\"px; height: \"+(d-b)+\"px\"))}function k(b,c,d){function m(c,d){return pc(a,nb(b,c),\"div\",f,d)}var k,l,f=Of(e,b),g=f.text.length;return vh(Vf(f),c||0,null==d?g:d,function(a,b,e){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\"==e){var q=f;f=n,n=q}o=f.left,p=n.right}null==c&&0==a&&(o=h),n.top-f.top>3&&(j(o,f.top,null,f.bottom),o=h,f.bottom<n.top&&j(o,f.bottom,null,n.top)),null==d&&b==g&&(p=i),(!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),h+1>o&&(o=h),j(o,n.top,p-o,n.bottom)}),{start:k,end:l}}var d=a.display,e=a.doc,f=document.createDocumentFragment(),g=Zb(a.display),h=g.left,i=d.lineSpace.offsetWidth-g.right,l=b.from(),m=b.to();if(l.line==m.line)k(l.line,l.ch,m.ch);else{var n=Of(e,l.line),o=Of(e,m.line),p=_e(n)==_e(o),q=k(l.line,l.ch,p?n.text.length+1:null).end,r=k(m.line,p?0:null,m.ch).start;p&&(q.top<r.top-2?(j(q.right,q.top,null,q.bottom),j(h,r.top,r.left,r.bottom)):j(q.right,q.top,r.left-q.right,q.bottom)),q.bottom<r.top&&j(h,q.bottom,null,r.top)}c.appendChild(f)}function Sb(a){if(a.state.focused){var b=a.display;clearInterval(b.blinker);var c=!0;b.cursorDiv.style.visibility=\"\",a.options.cursorBlinkRate>0?b.blinker=setInterval(function(){b.cursorDiv.style.visibility=(c=!c)?\"\":\"hidden\"},a.options.cursorBlinkRate):a.options.cursorBlinkRate<0&&(b.cursorDiv.style.visibility=\"hidden\")}}function Tb(a,b){a.doc.mode.startState&&a.doc.frontier<a.display.viewTo&&a.state.highlight.set(b,Pg(Ub,a))}function Ub(a){var b=a.doc;if(b.frontier<b.first&&(b.frontier=b.first),!(b.frontier>=a.display.viewTo)){var c=+new Date+a.options.workTime,d=re(b.mode,Wb(a,b.frontier)),e=[];b.iter(b.frontier,Math.min(b.first+b.size,a.display.viewTo+500),function(f){if(b.frontier>=a.display.viewFrom){var g=f.styles,h=rf(a,f,d,!0);f.styles=h.styles;var i=f.styleClasses,j=h.classes;j?f.styleClasses=j:i&&(f.styleClasses=null);for(var k=!g||g.length!=f.styles.length||i!=j&&(!i||!j||i.bgClass!=j.bgClass||i.textClass!=j.textClass),l=0;!k&&l<g.length;++l)k=g[l]!=f.styles[l];k&&e.push(b.frontier),f.stateAfter=re(b.mode,d)}else tf(a,f.text,d),f.stateAfter=0==b.frontier%5?re(b.mode,d):null;return++b.frontier,+new Date>c?(Tb(a,a.options.workDelay),!0):void 0}),e.length&&Jc(a,function(){for(var b=0;b<e.length;b++)Qc(a,e[b],\"text\")})}}function Vb(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=Of(f,h-1);if(i.stateAfter&&(!c||h<=f.frontier))return h;var j=Fg(i.text,null,a.options.tabSize);(null==e||d>j)&&(e=h-1,d=j)}return e}function Wb(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return!0;var f=Vb(a,b,c),g=f>d.first&&Of(d,f-1).stateAfter;return g=g?re(d.mode,g):se(d.mode),d.iter(f,b,function(c){tf(a,c.text,g);var h=f==b-1||0==f%5||f>=e.viewFrom&&f<e.viewTo;c.stateAfter=h?re(d.mode,g):null,++f}),c&&(d.frontier=f),g}function Xb(a){return a.lineSpace.offsetTop}function Yb(a){return a.mover.offsetHeight-a.lineSpace.offsetHeight}function Zb(a){if(a.cachedPaddingH)return a.cachedPaddingH;var b=Zg(a.measure,Wg(\"pre\",\"x\")),c=window.getComputedStyle?window.getComputedStyle(b):b.currentStyle,d={left:parseInt(c.paddingLeft),right:parseInt(c.paddingRight)};return isNaN(d.left)||isNaN(d.right)||(a.cachedPaddingH=d),d}function $b(a,b,c){var d=a.options.lineWrapping,e=d&&a.display.scroller.clientWidth;if(!b.measure.heights||d&&b.measure.width!=e){var f=b.measure.heights=[];if(d){b.measure.width=e;for(var g=b.text.firstChild.getClientRects(),h=0;h<g.length-1;h++){var i=g[h],j=g[h+1];Math.abs(i.bottom-j.bottom)>2&&f.push((i.bottom+j.top)/2-c.top)}}f.push(c.bottom-c.top)}}function _b(a,b,c){if(a.line==b)return{map:a.measure.map,cache:a.measure.cache};for(var d=0;d<a.rest.length;d++)if(a.rest[d]==b)return{map:a.measure.maps[d],cache:a.measure.caches[d]};for(var d=0;d<a.rest.length;d++)if(Sf(a.rest[d])>c)return{map:a.measure.maps[d],cache:a.measure.caches[d],before:!0}}function ac(a,b){b=_e(b);var c=Sf(b),d=a.display.externalMeasured=new Nc(a.doc,b,c);d.lineN=c;var e=d.built=xf(a,d);return d.text=e.pre,Zg(a.display.lineMeasure,e.pre),d}function bc(a,b,c,d){return ec(a,dc(a,b),c,d)}function cc(a,b){if(b>=a.display.viewFrom&&b<a.display.viewTo)return a.display.view[Sc(a,b)];var c=a.display.externalMeasured;return c&&b>=c.lineN&&b<c.lineN+c.size?c:void 0}function dc(a,b){var c=Sf(b),d=cc(a,c);d&&!d.text?d=null:d&&d.changes&&bb(a,d,c,_(a)),d||(d=ac(a,b));var e=_b(d,b,c);return{line:b,view:d,rect:null,map:e.map,cache:e.cache,before:e.before,hasHeights:!1}}function ec(a,b,c,d,e){b.before&&(c=-1);var g,f=c+(d||\"\");return b.cache.hasOwnProperty(f)?g=b.cache[f]:(b.rect||(b.rect=b.view.text.getBoundingClientRect()),b.hasHeights||($b(a,b.view,b.rect),b.hasHeights=!0),g=gc(a,b,c,d),g.bogus||(b.cache[f]=g)),{left:g.left,right:g.right,top:e?g.rtop:g.top,bottom:e?g.rbottom:g.bottom}}function gc(a,b,c,f){for(var h,i,j,k,g=b.map,l=0;l<g.length;l+=3){var m=g[l],n=g[l+1];if(m>c?(i=0,j=1,k=\"left\"):n>c?(i=c-m,j=i+1):(l==g.length-3||c==n&&g[l+3]>c)&&(j=n-m,i=j-1,c>=n&&(k=\"right\")),null!=i){if(h=g[l+2],m==n&&f==(h.insertLeft?\"left\":\"right\")&&(k=f),\"left\"==f&&0==i)for(;l&&g[l-2]==g[l-3]&&g[l-1].insertLeft;)h=g[(l-=3)+2],k=\"left\";if(\"right\"==f&&i==n-m)for(;l<g.length-3&&g[l+3]==g[l+4]&&!g[l+5].insertLeft;)h=g[(l+=3)+2],k=\"right\";break}}var o;if(3==h.nodeType){for(;i&&Vg(b.line.text.charAt(m+i));)--i;for(;n>m+j&&Vg(b.line.text.charAt(m+j));)++j;if(d&&9>e&&0==i&&j==n-m)o=h.parentNode.getBoundingClientRect();else if(d&&a.options.lineWrapping){var p=Xg(h,i,j).getClientRects();o=p.length?p[\"right\"==f?p.length-1:0]:fc}else o=Xg(h,i,j).getBoundingClientRect()||fc}else{i>0&&(k=f=\"right\");var p;o=a.options.lineWrapping&&(p=h.getClientRects()).length>1?p[\"right\"==f?p.length-1:0]:h.getBoundingClientRect()}if(d&&9>e&&!i&&(!o||!o.left&&!o.right)){var q=h.parentNode.getClientRects()[0];o=q?{left:q.left,right:q.left+xc(a.display),top:q.top,bottom:q.bottom}:fc}d&&11>e&&(o=hc(a.display.measure,o));for(var r=o.top-b.rect.top,s=o.bottom-b.rect.top,t=(r+s)/2,u=b.view.measure.heights,l=0;l<u.length-1&&!(t<u[l]);l++);var v=l?u[l-1]:0,w=u[l],x={left:(\"right\"==k?o.right:o.left)-b.rect.left,right:(\"left\"==k?o.left:o.right)-b.rect.left,top:v,bottom:w};return o.left||o.right||(x.bogus=!0),a.options.singleCursorHeightPerLine||(x.rtop=r,x.rbottom=s),x}function hc(a,b){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!th(a))return b;var c=screen.logicalXDPI/screen.deviceXDPI,d=screen.logicalYDPI/screen.deviceYDPI;return{left:b.left*c,right:b.right*c,top:b.top*d,bottom:b.bottom*d}}function ic(a){if(a.measure&&(a.measure.cache={},a.measure.heights=null,a.rest))for(var b=0;b<a.rest.length;b++)a.measure.caches[b]={}}function jc(a){a.display.externalMeasure=null,Yg(a.display.lineMeasure);for(var b=0;b<a.display.view.length;b++)ic(a.display.view[b])}function kc(a){jc(a),a.display.cachedCharWidth=a.display.cachedTextHeight=a.display.cachedPaddingH=null,a.options.lineWrapping||(a.display.maxLineChanged=!0),a.display.lineNumChars=null}function lc(){return window.pageXOffset||(document.documentElement||document.body).scrollLeft}function mc(){return window.pageYOffset||(document.documentElement||document.body).scrollTop}function nc(a,b,c,d){if(b.widgets)for(var e=0;e<b.widgets.length;++e)if(b.widgets[e].above){var f=hf(b.widgets[e]);c.top+=f,c.bottom+=f}if(\"line\"==d)return c;d||(d=\"local\");var g=Uf(b);if(\"local\"==d?g+=Xb(a.display):g-=a.display.viewOffset,\"page\"==d||\"window\"==d){var h=a.display.lineSpace.getBoundingClientRect();g+=h.top+(\"window\"==d?0:mc());var i=h.left+(\"window\"==d?0:lc());c.left+=i,c.right+=i}return c.top+=g,c.bottom+=g,c}function oc(a,b,c){if(\"div\"==c)return b;var d=b.left,e=b.top;if(\"page\"==c)d-=lc(),e-=mc();else if(\"local\"==c||!c){var f=a.display.sizer.getBoundingClientRect();d+=f.left,e+=f.top}var g=a.display.lineSpace.getBoundingClientRect();return{left:d-g.left,top:e-g.top}}function pc(a,b,c,d,e){return d||(d=Of(a.doc,b.line)),nc(a,d,bc(a,d,b.ch,e),c)}function qc(a,b,c,d,e,f){function g(b,g){var h=ec(a,e,b,g?\"right\":\"left\",f);return g?h.left=h.right:h.right=h.left,nc(a,d,h,c)}function h(a,b){var c=i[b],d=c.level%2;return a==wh(c)&&b&&c.level<i[b-1].level?(c=i[--b],a=xh(c)-(c.level%2?0:1),d=!0):a==xh(c)&&b<i.length-1&&c.level<i[b+1].level&&(c=i[++b],a=wh(c)-c.level%2,d=!1),d&&a==c.to&&a>c.from?g(a-1):g(a,d)}d=d||Of(a.doc,b.line),e||(e=dc(a,d));var i=Vf(d),j=b.ch;if(!i)return g(j);var k=Eh(i,j),l=h(j,k);return null!=Dh&&(l.other=h(j,Dh)),l}function rc(a,b){var c=0,b=xb(a.doc,b);a.options.lineWrapping||(c=xc(a.display)*b.ch);var d=Of(a.doc,b.line),e=Uf(d)+Xb(a.display);return{left:c,right:c,top:e,bottom:e+d.height}}function sc(a,b,c,d){var e=nb(a,b);return e.xRel=d,c&&(e.outside=!0),e}function tc(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,0>c)return sc(d.first,0,!0,-1);var e=Tf(d,c),f=d.first+d.size-1;if(e>f)return sc(d.first+d.size-1,Of(d,f).text.length,!0,1);0>b&&(b=0);for(var g=Of(d,e);;){var h=uc(a,g,e,b,c),i=Ze(g),j=i&&i.find(0,!0);if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=Sf(g=j.to.line)}}function uc(a,b,c,d,e){function j(d){var e=qc(a,nb(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-Uf(b),g=!1,h=2*a.display.wrapper.clientWidth,i=dc(a,b),k=Vf(b),l=b.text.length,m=yh(b),n=zh(b),o=j(m),p=g,q=j(n),r=g;if(d>q)return sc(c,n,r,1);for(;;){if(k?n==m||n==Gh(b,m,1):1>=n-m){for(var s=o>d||q-d>=d-o?m:n,t=d-(s==m?o:q);Vg(b.text.charAt(s));)++s;var u=sc(c,s,s==m?p:r,-1>t?-1:t>1?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=Gh(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 wc(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==vc){vc=Wg(\"pre\");for(var b=0;49>b;++b)vc.appendChild(document.createTextNode(\"x\")),vc.appendChild(Wg(\"br\"));vc.appendChild(document.createTextNode(\"x\"))}Zg(a.measure,vc);var c=vc.offsetHeight/50;return c>3&&(a.cachedTextHeight=c),Yg(a.measure),c||1}function xc(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=Wg(\"span\",\"xxxxxxxxxx\"),c=Wg(\"pre\",[b]);Zg(a.measure,c);var d=b.getBoundingClientRect(),e=(d.right-d.left)/10;return e>2&&(a.cachedCharWidth=e),e||10}function Ac(a){a.curOp={cm:a,viewChanged:!1,startHeight:a.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,id:++zc},yc?yc.ops.push(a.curOp):a.curOp.ownsGroup=yc={ops:[a.curOp],delayedCallbacks:[]}}function Bc(a){var b=a.delayedCallbacks,c=0;do{for(;c<b.length;c++)b[c]();for(var d=0;d<a.ops.length;d++){var e=a.ops[d];if(e.cursorActivityHandlers)for(;e.cursorActivityCalled<e.cursorActivityHandlers.length;)e.cursorActivityHandlers[e.cursorActivityCalled++](e.cm)}}while(c<b.length)}function Cc(a){var b=a.curOp,c=b.ownsGroup;if(c)try{Bc(c)}finally{yc=null;for(var d=0;d<c.ops.length;d++)c.ops[d].cm.curOp=null;Dc(c)}}function Dc(a){for(var b=a.ops,c=0;c<b.length;c++)Ec(b[c]);for(var c=0;c<b.length;c++)Fc(b[c]);for(var c=0;c<b.length;c++)Gc(b[c]);for(var c=0;c<b.length;c++)Hc(b[c]);for(var c=0;c<b.length;c++)Ic(b[c])}function Ec(a){var b=a.cm,c=b.display;a.updateMaxLine&&J(b),a.mustUpdate=a.viewChanged||a.forceUpdate||null!=a.scrollTop||a.scrollToPos&&(a.scrollToPos.from.line<c.viewFrom||a.scrollToPos.to.line>=c.viewTo)||c.maxLineChanged&&b.options.lineWrapping,a.update=a.mustUpdate&&new T(b,a.mustUpdate&&{top:a.scrollTop,ensure:a.scrollToPos},a.forceUpdate)\n}function Fc(a){a.updatedDisplay=a.mustUpdate&&U(a.cm,a.update)}function Gc(a){var b=a.cm,c=b.display;a.updatedDisplay&&Z(b),c.maxLineChanged&&!b.options.lineWrapping&&(a.adjustWidthTo=bc(b,c.maxLine,c.maxLine.text.length).left,a.maxScrollLeft=Math.max(0,c.sizer.offsetLeft+a.adjustWidthTo+zg-c.scroller.clientWidth)),a.barMeasure=M(b),(a.updatedDisplay||a.selectionChanged)&&(a.newSelectionNodes=Ob(b))}function Hc(a){var b=a.cm;null!=a.adjustWidthTo&&(b.display.sizer.style.minWidth=a.adjustWidthTo+\"px\",a.maxScrollLeft<b.doc.scrollLeft&&sd(b,Math.min(b.display.scroller.scrollLeft,a.maxScrollLeft),!0)),a.newSelectionNodes&&Pb(b,a.newSelectionNodes),a.updatedDisplay&&X(b,a.barMeasure),(a.updatedDisplay||a.startHeight!=b.doc.height)&&N(b,a.barMeasure),a.selectionChanged&&Sb(b),b.state.focused&&a.updateInput&&$c(b,a.typing)}function Ic(a){var b=a.cm,c=b.display,d=b.doc;if(a.updatedDisplay&&V(b,a.update),null==c.wheelStartX||null==a.scrollTop&&null==a.scrollLeft&&!a.scrollToPos||(c.wheelStartX=c.wheelStartY=null),null!=a.scrollTop&&c.scroller.scrollTop!=a.scrollTop){var e=Math.max(0,Math.min(c.scroller.scrollHeight-c.scroller.clientHeight,a.scrollTop));c.scroller.scrollTop=c.scrollbarV.scrollTop=d.scrollTop=e}if(null!=a.scrollLeft&&c.scroller.scrollLeft!=a.scrollLeft){var g=Math.max(0,Math.min(c.scroller.scrollWidth-c.scroller.clientWidth,a.scrollLeft));c.scroller.scrollLeft=c.scrollbarH.scrollLeft=d.scrollLeft=g,P(b)}if(a.scrollToPos){var h=Yd(b,xb(d,a.scrollToPos.from),xb(d,a.scrollToPos.to),a.scrollToPos.margin);a.scrollToPos.isCursor&&b.state.focused&&Xd(b,h)}var i=a.maybeHiddenMarkers,j=a.maybeUnhiddenMarkers;if(i)for(var k=0;k<i.length;++k)i[k].lines.length||rg(i[k],\"hide\");if(j)for(var k=0;k<j.length;++k)j[k].lines.length&&rg(j[k],\"unhide\");c.wrapper.offsetHeight&&(d.scrollTop=b.display.scroller.scrollTop),a.updatedDisplay&&f&&(b.options.lineWrapping&&Y(b,a.barMeasure),a.barMeasure.scrollWidth>a.barMeasure.clientWidth&&a.barMeasure.scrollWidth<a.barMeasure.clientWidth+1&&!L(b)&&N(b)),a.changeObjs&&rg(b,\"changes\",b,a.changeObjs)}function Jc(a,b){if(a.curOp)return b();Ac(a);try{return b()}finally{Cc(a)}}function Kc(a,b){return function(){if(a.curOp)return b.apply(a,arguments);Ac(a);try{return b.apply(a,arguments)}finally{Cc(a)}}}function Lc(a){return function(){if(this.curOp)return a.apply(this,arguments);Ac(this);try{return a.apply(this,arguments)}finally{Cc(this)}}}function Mc(a){return function(){var b=this.cm;if(!b||b.curOp)return a.apply(this,arguments);Ac(b);try{return a.apply(this,arguments)}finally{Cc(b)}}}function Nc(a,b,c){this.line=b,this.rest=af(b),this.size=this.rest?Sf(Jg(this.rest))-c+1:1,this.node=this.text=null,this.hidden=df(a,b)}function Oc(a,b,c){for(var e,d=[],f=b;c>f;f=e){var g=new Nc(a.doc,Of(a.doc,f),f);e=f+g.size,d.push(g)}return d}function Pc(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),d||(d=0);var e=a.display;if(d&&c<e.viewTo&&(null==e.updateLineNumbers||e.updateLineNumbers>b)&&(e.updateLineNumbers=b),a.curOp.viewChanged=!0,b>=e.viewTo)v&&bf(a.doc,b)<e.viewTo&&Rc(a);else if(c<=e.viewFrom)v&&cf(a.doc,c+d)>e.viewFrom?Rc(a):(e.viewFrom+=d,e.viewTo+=d);else if(b<=e.viewFrom&&c>=e.viewTo)Rc(a);else if(b<=e.viewFrom){var f=Tc(a,c,c+d,1);f?(e.view=e.view.slice(f.index),e.viewFrom=f.lineN,e.viewTo+=d):Rc(a)}else if(c>=e.viewTo){var f=Tc(a,b,b,-1);f?(e.view=e.view.slice(0,f.index),e.viewTo=f.lineN):Rc(a)}else{var g=Tc(a,b,b,-1),h=Tc(a,c,c+d,1);g&&h?(e.view=e.view.slice(0,g.index).concat(Oc(a,g.lineN,h.lineN)).concat(e.view.slice(h.index)),e.viewTo+=d):Rc(a)}var i=e.externalMeasured;i&&(c<i.lineN?i.lineN+=d:b<i.lineN+i.size&&(e.externalMeasured=null))}function Qc(a,b,c){a.curOp.viewChanged=!0;var d=a.display,e=a.display.externalMeasured;if(e&&b>=e.lineN&&b<e.lineN+e.size&&(d.externalMeasured=null),!(b<d.viewFrom||b>=d.viewTo)){var f=d.view[Sc(a,b)];if(null!=f.node){var g=f.changes||(f.changes=[]);-1==Lg(g,c)&&g.push(c)}}}function Rc(a){a.display.viewFrom=a.display.viewTo=a.doc.first,a.display.view=[],a.display.viewOffset=0}function Sc(a,b){if(b>=a.display.viewTo)return null;if(b-=a.display.viewFrom,0>b)return null;for(var c=a.display.view,d=0;d<c.length;d++)if(b-=c[d].size,0>b)return d}function Tc(a,b,c,d){var f,e=Sc(a,b),g=a.display.view;if(!v||c==a.doc.first+a.doc.size)return{index:e,lineN:c};for(var h=0,i=a.display.viewFrom;e>h;h++)i+=g[h].size;if(i!=b){if(d>0){if(e==g.length-1)return null;f=i+g[e].size-b,e++}else f=i-b;b+=f,c+=f}for(;bf(a.doc,c)!=c;){if(e==(0>d?0:g.length-1))return null;c+=d*g[e-(0>d?1:0)].size,e+=d}return{index:e,lineN:c}}function Uc(a,b,c){var d=a.display,e=d.view;0==e.length||b>=d.viewTo||c<=d.viewFrom?(d.view=Oc(a,b,c),d.viewFrom=b):(d.viewFrom>b?d.view=Oc(a,b,d.viewFrom).concat(d.view):d.viewFrom<b&&(d.view=d.view.slice(Sc(a,b))),d.viewFrom=b,d.viewTo<c?d.view=d.view.concat(Oc(a,d.viewTo,c)):d.viewTo>c&&(d.view=d.view.slice(0,Sc(a,c)))),d.viewTo=c}function Vc(a){for(var b=a.display.view,c=0,d=0;d<b.length;d++){var e=b[d];e.hidden||e.node&&!e.changes||++c}return c}function Wc(a){a.display.pollingFast||a.display.poll.set(a.options.pollInterval,function(){Zc(a),a.state.focused&&Wc(a)})}function Xc(a){function c(){var d=Zc(a);d||b?(a.display.pollingFast=!1,Wc(a)):(b=!0,a.display.poll.set(60,c))}var b=!1;a.display.pollingFast=!0,a.display.poll.set(20,c)}function Zc(a){var b=a.display.input,c=a.display.prevInput,f=a.doc;if(!a.state.focused||qh(b)&&!c||bd(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 g=b.value;if(g==c&&!a.somethingSelected())return!1;if(d&&e>=9&&a.display.inputHasSelection===g||p&&/[\\uf700-\\uf7ff]/.test(g))return $c(a),!1;var h=!a.curOp;h&&Ac(a),a.display.shift=!1,8203!=g.charCodeAt(0)||f.sel!=a.display.selForContextMenu||c||(c=\"\\u200b\");for(var i=0,j=Math.min(c.length,g.length);j>i&&c.charCodeAt(i)==g.charCodeAt(i);)++i;var k=g.slice(i),l=ph(k),m=null;a.state.pasteIncoming&&f.sel.ranges.length>1&&(Yc&&Yc.join(\"\\n\")==k?m=0==f.sel.ranges.length%Yc.length&&Mg(Yc,ph):l.length==f.sel.ranges.length&&(m=Mg(l,function(a){return[a]})));for(var n=f.sel.ranges.length-1;n>=0;n--){var o=f.sel.ranges[n],q=o.from(),r=o.to();i<c.length?q=nb(q.line,q.ch-(c.length-i)):a.state.overwrite&&o.empty()&&!a.state.pasteIncoming&&(r=nb(r.line,Math.min(Of(f,r.line).text.length,r.ch+Jg(l).length)));var s=a.curOp.updateInput,t={from:q,to:r,text:m?m[n%m.length]:l,origin:a.state.pasteIncoming?\"paste\":a.state.cutIncoming?\"cut\":\"+input\"};if(Qd(a.doc,t),tg(a,\"inputRead\",a,t),k&&!a.state.pasteIncoming&&a.options.electricChars&&a.options.smartIndent&&o.head.ch<100&&(!n||f.sel.ranges[n-1].head.line!=o.head.line)){var u=a.getModeAt(o.head);if(u.electricChars){for(var v=0;v<u.electricChars.length;v++)if(k.indexOf(u.electricChars.charAt(v))>-1){ce(a,o.head.line,\"smart\");break}}else if(u.electricInput){var w=Kd(t);u.electricInput.test(Of(f,w.line).text.slice(0,w.ch))&&ce(a,o.head.line,\"smart\")}}}return ae(a),a.curOp.updateInput=s,a.curOp.typing=!0,g.length>1e3||g.indexOf(\"\\n\")>-1?b.value=a.display.prevInput=\"\":a.display.prevInput=g,h&&Cc(a),a.state.pasteIncoming=a.state.cutIncoming=!1,!0}function $c(a,b){var c,f,g=a.doc;if(a.somethingSelected()){a.display.prevInput=\"\";var h=g.sel.primary();c=rh&&(h.to().line-h.from().line>100||(f=a.getSelection()).length>1e3);var i=c?\"-\":f||a.getSelection();a.display.input.value=i,a.state.focused&&Kg(a.display.input),d&&e>=9&&(a.display.inputHasSelection=i)}else b||(a.display.prevInput=a.display.input.value=\"\",d&&e>=9&&(a.display.inputHasSelection=null));a.display.inaccurateSelection=c}function _c(a){\"nocursor\"==a.options.readOnly||o&&_g()==a.display.input||a.display.input.focus()}function ad(a){a.state.focused||(_c(a),Gd(a))}function bd(a){return a.options.readOnly||a.doc.cantEdit}function cd(a){function c(){a.state.focused&&setTimeout(Pg(_c,a),0)}function g(b){vg(a,b)||mg(b)}function h(c){if(a.somethingSelected())Yc=a.getSelections(),b.inaccurateSelection&&(b.prevInput=\"\",b.inaccurateSelection=!1,b.input.value=Yc.join(\"\\n\"),Kg(b.input));else{for(var d=[],e=[],f=0;f<a.doc.sel.ranges.length;f++){var g=a.doc.sel.ranges[f].head.line,h={anchor:nb(g,0),head:nb(g+1,0)};e.push(h),d.push(a.getRange(h.anchor,h.head))}\"cut\"==c.type?a.setSelections(e,null,Bg):(b.prevInput=\"\",b.input.value=d.join(\"\\n\"),Kg(b.input)),Yc=d}\"cut\"==c.type&&(a.state.cutIncoming=!0)}var b=a.display;pg(b.scroller,\"mousedown\",Kc(a,gd)),d&&11>e?pg(b.scroller,\"dblclick\",Kc(a,function(b){if(!vg(a,b)){var c=fd(a,b);if(c&&!nd(a,b)&&!ed(a.display,b)){jg(b);var d=he(a,c);Cb(a.doc,d.anchor,d.head)}}})):pg(b.scroller,\"dblclick\",function(b){vg(a,b)||jg(b)}),pg(b.lineSpace,\"selectstart\",function(a){ed(b,a)||jg(a)}),t||pg(b.scroller,\"contextmenu\",function(b){Id(a,b)}),pg(b.scroller,\"scroll\",function(){b.scroller.clientHeight&&(rd(a,b.scroller.scrollTop),sd(a,b.scroller.scrollLeft,!0),rg(a,\"scroll\",a))}),pg(b.scrollbarV,\"scroll\",function(){b.scroller.clientHeight&&rd(a,b.scrollbarV.scrollTop)}),pg(b.scrollbarH,\"scroll\",function(){b.scroller.clientHeight&&sd(a,b.scrollbarH.scrollLeft)}),pg(b.scroller,\"mousewheel\",function(b){vd(a,b)}),pg(b.scroller,\"DOMMouseScroll\",function(b){vd(a,b)}),pg(b.scrollbarH,\"mousedown\",c),pg(b.scrollbarV,\"mousedown\",c),pg(b.wrapper,\"scroll\",function(){b.wrapper.scrollTop=b.wrapper.scrollLeft=0}),pg(b.input,\"keyup\",function(b){Ed.call(a,b)}),pg(b.input,\"input\",function(){d&&e>=9&&a.display.inputHasSelection&&(a.display.inputHasSelection=null),Xc(a)}),pg(b.input,\"keydown\",Kc(a,Cd)),pg(b.input,\"keypress\",Kc(a,Fd)),pg(b.input,\"focus\",Pg(Gd,a)),pg(b.input,\"blur\",Pg(Hd,a)),a.options.dragDrop&&(pg(b.scroller,\"dragstart\",function(b){qd(a,b)}),pg(b.scroller,\"dragenter\",g),pg(b.scroller,\"dragover\",g),pg(b.scroller,\"drop\",Kc(a,pd))),pg(b.scroller,\"paste\",function(c){ed(b,c)||(a.state.pasteIncoming=!0,_c(a),Xc(a))}),pg(b.input,\"paste\",function(){if(f&&!a.state.fakedLastChar&&!(new Date-a.state.lastMiddleDown<200)){var c=b.input.selectionStart,d=b.input.selectionEnd;b.input.value+=\"$\",b.input.selectionEnd=d,b.input.selectionStart=c,a.state.fakedLastChar=!0}a.state.pasteIncoming=!0,Xc(a)}),pg(b.input,\"cut\",h),pg(b.input,\"copy\",h),k&&pg(b.sizer,\"mouseup\",function(){_g()==b.input&&b.input.blur(),_c(a)})}function dd(a){var b=a.display;b.cachedCharWidth=b.cachedTextHeight=b.cachedPaddingH=null,a.setSize()}function ed(a,b){for(var c=ng(b);c!=a.wrapper;c=c.parentNode)if(!c||c.ignoreEvents||c.parentNode==a.sizer&&c!=a.mover)return!0}function fd(a,b,c,d){var e=a.display;if(!c){var f=ng(b);if(f==e.scrollbarH||f==e.scrollbarV||f==e.scrollbarFiller||f==e.gutterFiller)return null}var g,h,i=e.lineSpace.getBoundingClientRect();try{g=b.clientX-i.left,h=b.clientY-i.top}catch(b){return null}var k,j=tc(a,g,h);if(d&&1==j.xRel&&(k=Of(a.doc,j.line).text).length==j.ch){var l=Fg(k,k.length,a.options.tabSize)-k.length;j=nb(j.line,Math.max(0,Math.round((g-Zb(a.display).left)/xc(a.display))-l))}return j}function gd(a){if(!vg(this,a)){var b=this,c=b.display;if(c.shift=a.shiftKey,ed(c,a))return f||(c.scroller.draggable=!1,setTimeout(function(){c.scroller.draggable=!0},100)),void 0;if(!nd(b,a)){var d=fd(b,a);switch(window.focus(),og(a)){case 1:d?jd(b,a,d):ng(a)==c.scroller&&jg(a);break;case 2:f&&(b.state.lastMiddleDown=+new Date),d&&Cb(b.doc,d),setTimeout(Pg(_c,b),20),jg(a);break;case 3:t&&Id(b,a)}}}}function jd(a,b,c){setTimeout(Pg(ad,a),0);var e,d=+new Date;id&&id.time>d-400&&0==ob(id.pos,c)?e=\"triple\":hd&&hd.time>d-400&&0==ob(hd.pos,c)?(e=\"double\",id={time:d,pos:c}):(e=\"single\",hd={time:d,pos:c});var f=a.doc.sel,g=p?b.metaKey:b.ctrlKey;a.options.dragDrop&&ih&&!bd(a)&&\"single\"==e&&f.contains(c)>-1&&f.somethingSelected()?kd(a,b,c,g):ld(a,b,c,e,g)}function kd(a,b,c,g){var h=a.display,i=Kc(a,function(j){f&&(h.scroller.draggable=!1),a.state.draggingText=!1,qg(document,\"mouseup\",i),qg(h.scroller,\"drop\",i),Math.abs(b.clientX-j.clientX)+Math.abs(b.clientY-j.clientY)<10&&(jg(j),g||Cb(a.doc,c),_c(a),d&&9==e&&setTimeout(function(){document.body.focus(),_c(a)},20))});f&&(h.scroller.draggable=!0),a.state.draggingText=i,h.scroller.dragDrop&&h.scroller.dragDrop(),pg(document,\"mouseup\",i),pg(h.scroller,\"drop\",i)}function ld(a,b,c,d,e){function n(b){if(0!=ob(m,b))if(m=b,\"rect\"==d){for(var e=[],f=a.options.tabSize,k=Fg(Of(g,c.line).text,c.ch,f),l=Fg(Of(g,b.line).text,b.ch,f),n=Math.min(k,l),o=Math.max(k,l),p=Math.min(c.line,b.line),q=Math.min(a.lastLine(),Math.max(c.line,b.line));q>=p;p++){var r=Of(g,p).text,s=Gg(r,n,f);n==o?e.push(new tb(nb(p,s),nb(p,s))):r.length>s&&e.push(new tb(nb(p,s),nb(p,Gg(r,o,f))))}e.length||e.push(new tb(c,c)),Ib(g,ub(j.ranges.slice(0,i).concat(e),i),{origin:\"*mouse\",scroll:!1}),a.scrollIntoView(b)}else{var t=h,u=t.anchor,v=b;if(\"single\"!=d){if(\"double\"==d)var w=he(a,b);else var w=new tb(nb(b.line,0),xb(g,nb(b.line+1,0)));ob(w.anchor,u)>0?(v=w.head,u=rb(t.from(),w.anchor)):(v=w.anchor,u=qb(t.to(),w.head))}var e=j.ranges.slice(0);e[i]=new tb(xb(g,u),v),Ib(g,ub(e,i),Cg)}}function q(b){var c=++p,e=fd(a,b,!0,\"rect\"==d);if(e)if(0!=ob(e,m)){ad(a),n(e);var h=O(f,g);(e.line>=h.to||e.line<h.from)&&setTimeout(Kc(a,function(){p==c&&q(b)}),150)}else{var i=b.clientY<o.top?-20:b.clientY>o.bottom?20:0;i&&setTimeout(Kc(a,function(){p==c&&(f.scroller.scrollTop+=i,q(b))}),50)}}function r(b){p=1/0,jg(b),_c(a),qg(document,\"mousemove\",s),qg(document,\"mouseup\",t),g.history.lastSelOrigin=null}var f=a.display,g=a.doc;jg(b);var h,i,j=g.sel;if(e&&!b.shiftKey?(i=g.sel.contains(c),h=i>-1?g.sel.ranges[i]:new tb(c,c)):h=g.sel.primary(),b.altKey)d=\"rect\",e||(h=new tb(c,c)),c=fd(a,b,!0,!0),i=-1;else if(\"double\"==d){var k=he(a,c);h=a.display.shift||g.extend?Bb(g,h,k.anchor,k.head):k}else if(\"triple\"==d){var l=new tb(nb(c.line,0),xb(g,nb(c.line+1,0)));h=a.display.shift||g.extend?Bb(g,h,l.anchor,l.head):l}else h=Bb(g,h,c);e?i>-1?Eb(g,i,h,Cg):(i=g.sel.ranges.length,Ib(g,ub(g.sel.ranges.concat([h]),i),{scroll:!1,origin:\"*mouse\"})):(i=0,Ib(g,new sb([h],0),Cg),j=g.sel);var m=c,o=f.wrapper.getBoundingClientRect(),p=0,s=Kc(a,function(a){og(a)?q(a):r(a)}),t=Kc(a,r);pg(document,\"mousemove\",s),pg(document,\"mouseup\",t)}function md(a,b,c,d,e){try{var f=b.clientX,g=b.clientY}catch(b){return!1}if(f>=Math.floor(a.display.gutters.getBoundingClientRect().right))return!1;d&&jg(b);var h=a.display,i=h.lineDiv.getBoundingClientRect();if(g>i.bottom||!xg(a,c))return lg(b);g-=i.top-h.viewOffset;for(var j=0;j<a.options.gutters.length;++j){var k=h.gutters.childNodes[j];if(k&&k.getBoundingClientRect().right>=f){var l=Tf(a.doc,g),m=a.options.gutters[j];return e(a,c,a,l,m,b),lg(b)}}}function nd(a,b){return md(a,b,\"gutterClick\",!0,tg)}function pd(a){var b=this;if(!vg(b,a)&&!ed(b.display,a)){jg(a),d&&(od=+new Date);var c=fd(b,a,!0),e=a.dataTransfer.files;if(c&&!bd(b))if(e&&e.length&&window.FileReader&&window.File)for(var f=e.length,g=Array(f),h=0,i=function(a,d){var e=new FileReader;e.onload=Kc(b,function(){if(g[d]=e.result,++h==f){c=xb(b.doc,c);var a={from:c,to:c,text:ph(g.join(\"\\n\")),origin:\"paste\"};Qd(b.doc,a),Hb(b.doc,vb(c,Kd(a)))}}),e.readAsText(a)},j=0;f>j;++j)i(e[j],j);else{if(b.state.draggingText&&b.doc.sel.contains(c)>-1)return b.state.draggingText(a),setTimeout(Pg(_c,b),20),void 0;try{var g=a.dataTransfer.getData(\"Text\");if(g){if(b.state.draggingText&&!(p?a.metaKey:a.ctrlKey))var k=b.listSelections();if(Jb(b.doc,vb(c,c)),k)for(var j=0;j<k.length;++j)Wd(b.doc,\"\",k[j].anchor,k[j].head,\"drag\");b.replaceSelection(g,\"around\",\"paste\"),_c(b)}}catch(a){}}}}function qd(a,b){if(d&&(!a.state.draggingText||+new Date-od<100))return mg(b),void 0;if(!vg(a,b)&&!ed(a.display,b)&&(b.dataTransfer.setData(\"Text\",a.getSelection()),b.dataTransfer.setDragImage&&!j)){var c=Wg(\"img\",null,null,\"position: fixed; left: 0; top: 0;\");c.src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\",i&&(c.width=c.height=1,a.display.wrapper.appendChild(c),c._top=c.offsetTop),b.dataTransfer.setDragImage(c,0,0),i&&c.parentNode.removeChild(c)}}function rd(b,c){Math.abs(b.doc.scrollTop-c)<2||(b.doc.scrollTop=c,a||W(b,{top:c}),b.display.scroller.scrollTop!=c&&(b.display.scroller.scrollTop=c),b.display.scrollbarV.scrollTop!=c&&(b.display.scrollbarV.scrollTop=c),a&&W(b),Tb(b,100))}function sd(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 vd(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 g=b.display,h=g.scroller;if(d&&h.scrollWidth>h.clientWidth||e&&h.scrollHeight>h.clientHeight){if(e&&p&&f)a:for(var j=c.target,k=g.view;j!=h;j=j.parentNode)for(var l=0;l<k.length;l++)if(k[l].node==j){b.display.currentWheelTarget=j;break a}if(d&&!a&&!i&&null!=ud)return e&&rd(b,Math.max(0,Math.min(h.scrollTop+e*ud,h.scrollHeight-h.clientHeight))),sd(b,Math.max(0,Math.min(h.scrollLeft+d*ud,h.scrollWidth-h.clientWidth))),jg(c),g.wheelStartX=null,void 0;if(e&&null!=ud){var m=e*ud,n=b.doc.scrollTop,o=n+g.wrapper.clientHeight;0>m?n=Math.max(0,n+m-50):o=Math.min(b.doc.height,o+m+50),W(b,{top:n,bottom:o})}20>td&&(null==g.wheelStartX?(g.wheelStartX=h.scrollLeft,g.wheelStartY=h.scrollTop,g.wheelDX=d,g.wheelDY=e,setTimeout(function(){if(null!=g.wheelStartX){var a=h.scrollLeft-g.wheelStartX,b=h.scrollTop-g.wheelStartY,c=b&&g.wheelDY&&b/g.wheelDY||a&&g.wheelDX&&a/g.wheelDX;g.wheelStartX=g.wheelStartY=null,c&&(ud=(ud*td+c)/(td+1),++td)}},200)):(g.wheelDX+=d,g.wheelDY+=e))}}function wd(a,b,c){if(\"string\"==typeof b&&(b=te[b],!b))return!1;a.display.pollingFast&&Zc(a)&&(a.display.pollingFast=!1);var d=a.display.shift,e=!1;try{bd(a)&&(a.state.suppressEdits=!0),c&&(a.display.shift=!1),e=b(a)!=Ag}finally{a.display.shift=d,a.state.suppressEdits=!1}return e}function xd(a){var b=a.state.keyMaps.slice(0);return a.options.extraKeys&&b.push(a.options.extraKeys),b.push(a.options.keyMap),b}function zd(a,b){var c=ve(a.options.keyMap),d=c.auto;clearTimeout(yd),d&&!xe(b)&&(yd=setTimeout(function(){ve(a.options.keyMap)==c&&(a.options.keyMap=d.call?d.call(null,a):d,D(a))},50));var e=ye(b,!0),f=!1;if(!e)return!1;var g=xd(a);return f=b.shiftKey?we(\"Shift-\"+e,g,function(b){return wd(a,b,!0)})||we(e,g,function(b){return(\"string\"==typeof b?/^go[A-Z]/.test(b):b.motion)?wd(a,b):void 0}):we(e,g,function(b){return wd(a,b)}),f&&(jg(b),Sb(a),tg(a,\"keyHandled\",a,e,b)),f}function Ad(a,b,c){var d=we(\"'\"+c+\"'\",xd(a),function(b){return wd(a,b,!0)});return d&&(jg(b),Sb(a),tg(a,\"keyHandled\",a,\"'\"+c+\"'\",b)),d}function Cd(a){var b=this;if(ad(b),!vg(b,a)){d&&11>e&&27==a.keyCode&&(a.returnValue=!1);var c=a.keyCode;b.display.shift=16==c||a.shiftKey;var f=zd(b,a);i&&(Bd=f?c:null,!f&&88==c&&!rh&&(p?a.metaKey:a.ctrlKey)&&b.replaceSelection(\"\",null,\"cut\")),18!=c||/\\bCodeMirror-crosshair\\b/.test(b.display.lineDiv.className)||Dd(b)}}function Dd(a){function c(a){18!=a.keyCode&&a.altKey||(bh(b,\"CodeMirror-crosshair\"),qg(document,\"keyup\",c),qg(document,\"mouseover\",c))}var b=a.display.lineDiv;ch(b,\"CodeMirror-crosshair\"),pg(document,\"keyup\",c),pg(document,\"mouseover\",c)}function Ed(a){16==a.keyCode&&(this.doc.sel.shift=!1),vg(this,a)}function Fd(a){var b=this;if(!(vg(b,a)||a.ctrlKey&&!a.altKey||p&&a.metaKey)){var c=a.keyCode,f=a.charCode;if(i&&c==Bd)return Bd=null,jg(a),void 0;if(!(i&&(!a.which||a.which<10)||k)||!zd(b,a)){var g=String.fromCharCode(null==f?c:f);Ad(b,a,g)||(d&&e>=9&&(b.display.inputHasSelection=null),Xc(b))}}}function Gd(a){\"nocursor\"!=a.options.readOnly&&(a.state.focused||(rg(a,\"focus\",a),a.state.focused=!0,ch(a.display.wrapper,\"CodeMirror-focused\"),a.curOp||a.display.selForContextMenu==a.doc.sel||($c(a),f&&setTimeout(Pg($c,a,!0),0))),Wc(a),Sb(a))}function Hd(a){a.state.focused&&(rg(a,\"blur\",a),a.state.focused=!1,bh(a.display.wrapper,\"CodeMirror-focused\")),clearInterval(a.display.blinker),setTimeout(function(){a.state.focused||(a.display.shift=!1)},150)}function Id(a,b){function m(){if(null!=c.input.selectionStart){var b=a.somethingSelected(),d=c.input.value=\"\\u200b\"+(b?c.input.value:\"\");c.prevInput=b?\"\":\"\\u200b\",c.input.selectionStart=1,c.input.selectionEnd=d.length,c.selForContextMenu=a.doc.sel}}function n(){if(c.inputDiv.style.position=\"relative\",c.input.style.cssText=k,d&&9>e&&(c.scrollbarV.scrollTop=c.scroller.scrollTop=h),Wc(a),null!=c.input.selectionStart){(!d||d&&9>e)&&m();var b=0,f=function(){c.selForContextMenu==a.doc.sel&&0==c.input.selectionStart?Kc(a,te.selectAll)(a):b++<10?c.detectingSelectAll=setTimeout(f,500):$c(a)};c.detectingSelectAll=setTimeout(f,200)}}if(!vg(a,b,\"contextmenu\")){var c=a.display;if(!ed(c,b)&&!Jd(a,b)){var g=fd(a,b),h=c.scroller.scrollTop;if(g&&!i){var j=a.options.resetSelectionOnContextMenu;j&&-1==a.doc.sel.contains(g)&&Kc(a,Ib)(a.doc,vb(g),Bg);var k=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: \"+(d?\"rgba(255, 255, 255, .05)\":\"transparent\")+\"; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);\",f)var l=window.scrollY;if(_c(a),f&&window.scrollTo(null,l),$c(a),a.somethingSelected()||(c.input.value=c.prevInput=\" \"),c.selForContextMenu=a.doc.sel,clearTimeout(c.detectingSelectAll),d&&e>=9&&m(),t){mg(b);var o=function(){qg(window,\"mouseup\",o),setTimeout(n,20)};pg(window,\"mouseup\",o)}else setTimeout(n,50)}}}}function Jd(a,b){return xg(a,\"gutterContextMenu\")?md(a,b,\"gutterContextMenu\",!1,rg):!1}function Ld(a,b){if(ob(a,b.from)<0)return a;if(ob(a,b.to)<=0)return Kd(b);var c=a.line+b.text.length-(b.to.line-b.from.line)-1,d=a.ch;return a.line==b.to.line&&(d+=Kd(b).ch-b.to.ch),nb(c,d)}function Md(a,b){for(var c=[],d=0;d<a.sel.ranges.length;d++){var e=a.sel.ranges[d];c.push(new tb(Ld(e.anchor,b),Ld(e.head,b)))}return ub(c,a.sel.primIndex)}function Nd(a,b,c){return a.line==b.line?nb(c.line,a.ch-b.ch+c.ch):nb(c.line+(a.line-b.line),a.ch)}function Od(a,b,c){for(var d=[],e=nb(a.first,0),f=e,g=0;g<b.length;g++){var h=b[g],i=Nd(h.from,e,f),j=Nd(Kd(h),e,f);if(e=h.to,f=j,\"around\"==c){var k=a.sel.ranges[g],l=ob(k.head,k.anchor)<0;d[g]=new tb(l?j:i,l?i:j)}else d[g]=new tb(i,i)}return new sb(d,a.sel.primIndex)}function Pd(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=xb(a,b)),c&&(this.to=xb(a,c)),d&&(this.text=d),void 0!==e&&(this.origin=e)}),rg(a,\"beforeChange\",a,d),a.cm&&rg(a.cm,\"beforeChange\",a.cm,d),d.canceled?null:{from:d.from,to:d.to,text:d.text,origin:d.origin}}function Qd(a,b,c){if(a.cm){if(!a.cm.curOp)return Kc(a.cm,Qd)(a,b,c);if(a.cm.state.suppressEdits)return}if(!(xg(a,\"beforeChange\")||a.cm&&xg(a.cm,\"beforeChange\"))||(b=Pd(a,b,!0))){var d=u&&!c&&Re(a,b.from,b.to);if(d)for(var e=d.length-1;e>=0;--e)Rd(a,{from:d[e].from,to:d[e].to,text:e?[\"\"]:b.text});else Rd(a,b)}}function Rd(a,b){if(1!=b.text.length||\"\"!=b.text[0]||0!=ob(b.from,b.to)){var c=Md(a,b);$f(a,b,c,a.cm?a.cm.curOp.id:0/0),Ud(a,b,c,Oe(a,b));var d=[];Mf(a,function(a,c){c||-1!=Lg(d,a.history)||(ig(a.history,b),d.push(a.history)),Ud(a,b,null,Oe(a,b))})}}function Sd(a,b,c){if(!a.cm||!a.cm.state.suppressEdits){for(var e,d=a.history,f=a.sel,g=\"undo\"==b?d.done:d.undone,h=\"undo\"==b?d.undone:d.done,i=0;i<g.length&&(e=g[i],c?!e.ranges||e.equals(a.sel):e.ranges);i++);if(i!=g.length){for(d.lastOrigin=d.lastSelOrigin=null;e=g.pop(),e.ranges;){if(bg(e,h),c&&!e.equals(a.sel))return Ib(a,e,{clearRedo:!1}),void 0;f=e}var j=[];bg(f,h),h.push({changes:j,generation:d.generation}),d.generation=e.generation||++d.maxGeneration;for(var k=xg(a,\"beforeChange\")||a.cm&&xg(a.cm,\"beforeChange\"),i=e.changes.length-1;i>=0;--i){var l=e.changes[i];if(l.origin=b,k&&!Pd(a,l,!1))return g.length=0,void 0;j.push(Xf(a,l));var m=i?Md(a,l):Jg(g);Ud(a,l,m,Qe(a,l)),!i&&a.cm&&a.cm.scrollIntoView(l);var n=[];Mf(a,function(a,b){b||-1!=Lg(n,a.history)||(ig(a.history,l),n.push(a.history)),Ud(a,l,null,Qe(a,l))})}}}}function Td(a,b){if(0!=b&&(a.first+=b,a.sel=new sb(Mg(a.sel.ranges,function(a){return new tb(nb(a.anchor.line+b,a.anchor.ch),nb(a.head.line+b,a.head.ch))}),a.sel.primIndex),a.cm)){Pc(a.cm,a.first,a.first-b,b);for(var c=a.cm.display,d=c.viewFrom;d<c.viewTo;d++)Qc(a.cm,d,\"gutter\")}}function Ud(a,b,c,d){if(a.cm&&!a.cm.curOp)return Kc(a.cm,Ud)(a,b,c,d);if(b.to.line<a.first)return Td(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);Td(a,e),b={from:nb(a.first,0),to:nb(b.to.line+e,b.to.ch),text:[Jg(b.text)],origin:b.origin}}var f=a.lastLine();b.to.line>f&&(b={from:b.from,to:nb(f,Of(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=Pf(a,b.from,b.to),c||(c=Md(a,b)),a.cm?Vd(a.cm,b,d):Ff(a,b,d),Jb(a,c,Bg)}}function Vd(a,b,c){var d=a.doc,e=a.display,f=b.from,g=b.to,h=!1,i=f.line;a.options.lineWrapping||(i=Sf(_e(Of(d,f.line))),d.iter(i,g.line+1,function(a){return a==e.maxLine?(h=!0,!0):void 0})),d.sel.contains(b.from,b.to)>-1&&wg(a),Ff(d,b,c,B(a)),a.options.lineWrapping||(d.iter(i,f.line+b.text.length,function(a){var b=I(a);b>e.maxLineLength&&(e.maxLine=a,e.maxLineLength=b,e.maxLineChanged=!0,h=!1)}),h&&(a.curOp.updateMaxLine=!0)),d.frontier=Math.min(d.frontier,f.line),Tb(a,400);var j=b.text.length-(g.line-f.line)-1;f.line!=g.line||1!=b.text.length||Ef(a.doc,b)?Pc(a,f.line,g.line+1,j):Qc(a,f.line,\"text\");var k=xg(a,\"changes\"),l=xg(a,\"change\");if(l||k){var m={from:f,to:g,text:b.text,removed:b.removed,origin:b.origin};l&&tg(a,\"change\",a,m),k&&(a.curOp.changeObjs||(a.curOp.changeObjs=[])).push(m)}a.display.selForContextMenu=null}function Wd(a,b,c,d,e){if(d||(d=c),ob(d,c)<0){var f=d;d=c,c=f}\"string\"==typeof b&&(b=ph(b)),Qd(a,{from:c,to:d,text:b,origin:e})}function Xd(a,b){var c=a.display,d=c.sizer.getBoundingClientRect(),e=null;if(b.top+d.top<0?e=!0:b.bottom+d.top>(window.innerHeight||document.documentElement.clientHeight)&&(e=!1),null!=e&&!m){var f=Wg(\"div\",\"\\u200b\",null,\"position: absolute; top: \"+(b.top-c.viewOffset-Xb(a.display))+\"px; height: \"+(b.bottom-b.top+zg)+\"px; left: \"+b.left+\"px; width: 2px;\");a.display.lineSpace.appendChild(f),f.scrollIntoView(e),a.display.lineSpace.removeChild(f)}}function Yd(a,b,c,d){for(null==d&&(d=0);;){var e=!1,f=qc(a,b),g=c&&c!=b?qc(a,c):f,h=$d(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&&(rd(a,h.scrollTop),Math.abs(a.doc.scrollTop-i)>1&&(e=!0)),null!=h.scrollLeft&&(sd(a,h.scrollLeft),Math.abs(a.doc.scrollLeft-j)>1&&(e=!0)),!e)return f}}function Zd(a,b,c,d,e){var f=$d(a,b,c,d,e);null!=f.scrollTop&&rd(a,f.scrollTop),null!=f.scrollLeft&&sd(a,f.scrollLeft)}function $d(a,b,c,d,e){var f=a.display,g=wc(a.display);0>c&&(c=0);var h=a.curOp&&null!=a.curOp.scrollTop?a.curOp.scrollTop:f.scroller.scrollTop,i=f.scroller.clientHeight-zg,j={},k=a.doc.height+Yb(f),l=g>c,m=e>k-g;if(h>c)j.scrollTop=l?0:c;else if(e>h+i){var n=Math.min(c,(m?k:e)-i);n!=h&&(j.scrollTop=n)}var o=a.curOp&&null!=a.curOp.scrollLeft?a.curOp.scrollLeft:f.scroller.scrollLeft,p=f.scroller.clientWidth-zg;b+=f.gutters.offsetWidth,d+=f.gutters.offsetWidth;var q=f.gutters.offsetWidth,r=q+10>b;return o+q>b||r?(r&&(b=0),j.scrollLeft=Math.max(0,b-10-q)):d>p+o-3&&(j.scrollLeft=d+10-p),j}function _d(a,b,c){(null!=b||null!=c)&&be(a),null!=b&&(a.curOp.scrollLeft=(null==a.curOp.scrollLeft?a.doc.scrollLeft:a.curOp.scrollLeft)+b),null!=c&&(a.curOp.scrollTop=(null==a.curOp.scrollTop?a.doc.scrollTop:a.curOp.scrollTop)+c)}function ae(a){be(a);var b=a.getCursor(),c=b,d=b;a.options.lineWrapping||(c=b.ch?nb(b.line,b.ch-1):b,d=nb(b.line,b.ch+1)),a.curOp.scrollToPos={from:c,to:d,margin:a.options.cursorScrollMargin,isCursor:!0}}function be(a){var b=a.curOp.scrollToPos;if(b){a.curOp.scrollToPos=null;var c=rc(a,b.from),d=rc(a,b.to),e=$d(a,Math.min(c.left,d.left),Math.min(c.top,d.top)-b.margin,Math.max(c.right,d.right),Math.max(c.bottom,d.bottom)+b.margin);a.scrollTo(e.scrollLeft,e.scrollTop)}}function ce(a,b,c,d){var f,e=a.doc;null==c&&(c=\"add\"),\"smart\"==c&&(e.mode.indent?f=Wb(a,b):c=\"prev\");var g=a.options.tabSize,h=Of(e,b),i=Fg(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=e.mode.indent(f,h.text.slice(j.length),h.text),k==Ag||k>150)){if(!d)return;c=\"prev\"}}else k=0,c=\"not\";\"prev\"==c?k=b>e.first?Fg(Of(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\";if(k>m&&(l+=Ig(k-m)),l!=j)Wd(e,l,nb(b,0),nb(b,j.length),\"+input\");else for(var n=0;n<e.sel.ranges.length;n++){var o=e.sel.ranges[n];if(o.head.line==b&&o.head.ch<j.length){var m=nb(b,j.length);Eb(e,n,new tb(m,m));break}}h.stateAfter=null}function de(a,b,c,d){var e=b,f=b;return\"number\"==typeof b?f=Of(a,wb(a,b)):e=Sf(b),null==e?null:(d(f,e)&&a.cm&&Qc(a.cm,e,c),f)}function ee(a,b){for(var c=a.doc.sel.ranges,d=[],e=0;e<c.length;e++){for(var f=b(c[e]);d.length&&ob(f.from,Jg(d).to)<=0;){var g=d.pop();if(ob(g.from,f.from)<0){f.from=g.from;break}}d.push(f)}Jc(a,function(){for(var b=d.length-1;b>=0;b--)Wd(a.doc,\"\",d[b].from,d[b].to,\"+delete\");ae(a)})}function fe(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=Of(a,b))}function l(a){var b=(e?Gh:Hh)(i,g,c,!0);if(null==b){if(a||!k())return j=!1;g=e?(0>c?zh:yh)(i):0>c?i.text.length:0}else g=b;return!0}var f=b.line,g=b.ch,h=c,i=Of(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=a.cm&&a.cm.getHelper(b,\"wordChars\"),p=!0;!(0>c)||l(!p);p=!1){var q=i.text.charAt(g)||\"\\n\",r=Sg(q,o)?\"w\":n&&\"\\n\"==q?\"n\":!n||/\\s/.test(q)?null:\"p\";if(!n||p||r||(r=\"s\"),m&&m!=r){0>c&&(c=1,l());break}if(r&&(m=r),c>0&&!l(!p))break}var s=Nb(a,nb(f,g),h,!0);return j||(s.hitSide=!0),s}function ge(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)*wc(a.display))}else\"line\"==d&&(g=c>0?b.bottom+3:b.top-3);for(;;){var i=tc(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 he(a,b){var c=a.doc,d=Of(c,b.line).text,e=b.ch,f=b.ch;if(d){var g=a.getHelper(b,\"wordChars\");(b.xRel<0||f==d.length)&&e?--e:++f;for(var h=d.charAt(e),i=Sg(h,g)?function(a){return Sg(a,g)}:/\\s/.test(h)?function(a){return/\\s/.test(a)}:function(a){return!/\\s/.test(a)&&!Sg(a)};e>0&&i(d.charAt(e-1));)--e;for(;f<d.length&&i(d.charAt(f));)++f}return new tb(nb(b.line,e),nb(b.line,f))}function ke(a,b,c,d){w.defaults[a]=b,c&&(je[a]=d?function(a,b,d){d!=le&&c(a,b,d)}:c)}function ve(a){return\"string\"==typeof a?ue[a]:a}function Ce(a,b,c,d,e){if(d&&d.shared)return Ee(a,b,c,d,e);if(a.cm&&!a.cm.curOp)return Kc(a.cm,Ce)(a,b,c,d,e);var f=new Ae(a,e),g=ob(b,c);if(d&&Og(d,f,!1),g>0||0==g&&f.clearWhenEmpty!==!1)return f;if(f.replacedWith&&(f.collapsed=!0,f.widgetNode=Wg(\"span\",[f.replacedWith],\"CodeMirror-widget\"),d.handleMouseEvents||(f.widgetNode.ignoreEvents=!0),d.insertLeft&&(f.widgetNode.insertLeft=!0)),f.collapsed){if($e(a,b.line,b,c,f)||b.line!=c.line&&$e(a,c.line,b,c,f))throw new Error(\"Inserting collapsed marker partially overlapping an existing one\");v=!0}f.addToHistory&&$f(a,{from:b,to:c,origin:\"markText\"},a.sel,0/0);var j,h=b.line,i=a.cm;if(a.iter(h,c.line+1,function(a){i&&f.collapsed&&!i.options.lineWrapping&&_e(a)==i.display.maxLine&&(j=!0),f.collapsed&&h!=b.line&&Rf(a,0),Le(a,new Ie(f,h==b.line?b.ch:null,h==c.line?c.ch:null)),++h}),f.collapsed&&a.iter(b.line,c.line+1,function(b){df(a,b)&&Rf(b,0)}),f.clearOnEnter&&pg(f,\"beforeCursorEnter\",function(){f.clear()}),f.readOnly&&(u=!0,(a.history.done.length||a.history.undone.length)&&a.clearHistory()),f.collapsed&&(f.id=++Be,f.atomic=!0),i){if(j&&(i.curOp.updateMaxLine=!0),f.collapsed)Pc(i,b.line,c.line+1);\nelse if(f.className||f.title||f.startStyle||f.endStyle)for(var k=b.line;k<=c.line;k++)Qc(i,k,\"text\");f.atomic&&Lb(i.doc),tg(i,\"markerAdded\",i,f)}return f}function Ee(a,b,c,d,e){d=Og(d),d.shared=!1;var f=[Ce(a,b,c,d,e)],g=f[0],h=d.widgetNode;return Mf(a,function(a){h&&(d.widgetNode=h.cloneNode(!0)),f.push(Ce(a,xb(a,b),xb(a,c),d,e));for(var i=0;i<a.linked.length;++i)if(a.linked[i].isParent)return;g=Jg(f)}),new De(f,g)}function Fe(a){return a.findMarks(nb(a.first,0),a.clipPos(nb(a.lastLine())),function(a){return a.parent})}function Ge(a,b){for(var c=0;c<b.length;c++){var d=b[c],e=d.find(),f=a.clipPos(e.from),g=a.clipPos(e.to);if(ob(f,g)){var h=Ce(a,f,g,d.primary,d.primary.type);d.markers.push(h),h.parent=d}}}function He(a){for(var b=0;b<a.length;b++){var c=a[b],d=[c.primary.doc];Mf(c.primary.doc,function(a){d.push(a)});for(var e=0;e<c.markers.length;e++){var f=c.markers[e];-1==Lg(d,f.doc)&&(f.parent=null,c.markers.splice(e--,1))}}}function Ie(a,b,c){this.marker=a,this.from=b,this.to=c}function Je(a,b){if(a)for(var c=0;c<a.length;++c){var d=a[c];if(d.marker==b)return d}}function Ke(a,b){for(var c,d=0;d<a.length;++d)a[d]!=b&&(c||(c=[])).push(a[d]);return c}function Le(a,b){a.markedSpans=a.markedSpans?a.markedSpans.concat([b]):[b],b.marker.attachLine(a)}function Me(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(new Ie(g,f.from,i?null:f.to))}}return e}function Ne(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(new Ie(g,i?null:f.from-b,null==f.to?null:f.to-b))}}return e}function Oe(a,b){var c=zb(a,b.from.line)&&Of(a,b.from.line).markedSpans,d=zb(a,b.to.line)&&Of(a,b.to.line).markedSpans;if(!c&&!d)return null;var e=b.from.ch,f=b.to.ch,g=0==ob(b.from,b.to),h=Me(c,e,g),i=Ne(d,f,g),j=1==b.text.length,k=Jg(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=Je(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=Je(h,m.marker);n||(m.from=k,j&&(h||(h=[])).push(m))}else m.from+=k,j&&(h||(h=[])).push(m)}h&&(h=Pe(h)),i&&i!=h&&(i=Pe(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(new Ie(h[l].marker,null,null));for(var l=0;p>l;++l)o.push(q);o.push(i)}return o}function Pe(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 Qe(a,b){var c=eg(a,b),d=Oe(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 Re(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!=Lg(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(0),i=0;i<e.length;++i){var j=e[i];if(!(ob(j.to,h.from)<0||ob(j.from,h.to)>0)){var k=[i,1],l=ob(j.from,h.from),m=ob(j.to,h.to);(0>l||!g.inclusiveLeft&&!l)&&k.push({from:j.from,to:h.from}),(m>0||!g.inclusiveRight&&!m)&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-1}}return e}function Se(a){var b=a.markedSpans;if(b){for(var c=0;c<b.length;++c)b[c].marker.detachLine(a);a.markedSpans=null}}function Te(a,b){if(b){for(var c=0;c<b.length;++c)b[c].marker.attachLine(a);a.markedSpans=b}}function Ue(a){return a.inclusiveLeft?-1:0}function Ve(a){return a.inclusiveRight?1:0}function We(a,b){var c=a.lines.length-b.lines.length;if(0!=c)return c;var d=a.find(),e=b.find(),f=ob(d.from,e.from)||Ue(a)-Ue(b);if(f)return-f;var g=ob(d.to,e.to)||Ve(a)-Ve(b);return g?g:b.id-a.id}function Xe(a,b){var d,c=v&&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||We(d,e.marker)<0)&&(d=e.marker);return d}function Ye(a){return Xe(a,!0)}function Ze(a){return Xe(a,!1)}function $e(a,b,c,d,e){var f=Of(a,b),g=v&&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=ob(j.from,c)||Ue(i.marker)-Ue(e),l=ob(j.to,d)||Ve(i.marker)-Ve(e);if(!(k>=0&&0>=l||0>=k&&l>=0)&&(0>=k&&(ob(j.to,c)>0||i.marker.inclusiveRight&&e.inclusiveLeft)||k>=0&&(ob(j.from,d)<0||i.marker.inclusiveLeft&&e.inclusiveRight)))return!0}}}function _e(a){for(var b;b=Ye(a);)a=b.find(-1,!0).line;return a}function af(a){for(var b,c;b=Ze(a);)a=b.find(1,!0).line,(c||(c=[])).push(a);return c}function bf(a,b){var c=Of(a,b),d=_e(c);return c==d?b:Sf(d)}function cf(a,b){if(b>a.lastLine())return b;var d,c=Of(a,b);if(!df(a,c))return b;for(;d=Ze(c);)c=d.find(1,!0).line;return Sf(c)+1}function df(a,b){var c=v&&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.widgetNode&&0==d.from&&d.marker.inclusiveLeft&&ef(a,b,d))return!0}}function ef(a,b,c){if(null==c.to){var d=c.marker.find(1,!0);return ef(a,d.line,Je(d.line.markedSpans,c.marker))}if(c.marker.inclusiveRight&&c.to==b.text.length)return!0;for(var e,f=0;f<b.markedSpans.length;++f)if(e=b.markedSpans[f],e.marker.collapsed&&!e.marker.widgetNode&&e.from==c.to&&(null==e.to||e.to!=c.from)&&(e.marker.inclusiveLeft||c.marker.inclusiveRight)&&ef(a,b,e))return!0}function gf(a,b,c){Uf(b)<(a.curOp&&a.curOp.scrollTop||a.doc.scrollTop)&&_d(a,null,c)}function hf(a){if(null!=a.height)return a.height;if(!$g(document.body,a.node)){var b=\"position: relative;\";a.coverGutter&&(b+=\"margin-left: -\"+a.cm.getGutterElement().offsetWidth+\"px;\"),Zg(a.cm.display.measure,Wg(\"div\",[a.node],null,b))}return a.height=a.node.offsetHeight}function jf(a,b,c,d){var e=new ff(a,c,d);return e.noHScroll&&(a.display.alignWidgets=!0),de(a.doc,b,\"widget\",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,!df(a.doc,b)){var d=Uf(b)<a.doc.scrollTop;Rf(b,b.height+hf(e)),d&&_d(a,null,e.height),a.curOp.forceUpdate=!0}return!0}),e}function lf(a,b,c,d){a.text=b,a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null),null!=a.order&&(a.order=null),Se(a),Te(a,c);var e=d?d(a):1;e!=a.height&&Rf(a,e)}function mf(a){a.parent=null,Se(a)}function nf(a,b){if(a)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])}return a}function of(a,b){if(a.blankLine)return a.blankLine(b);if(a.innerMode){var c=w.innerMode(a,b);return c.mode.blankLine?c.mode.blankLine(c.state):void 0}}function pf(a,b,c){for(var d=0;10>d;d++){var e=a.token(b,c);if(b.pos>b.start)return e}throw new Error(\"Mode \"+a.name+\" failed to advance stream.\")}function qf(a,b,c,d,e,f,g){var h=c.flattenSpans;null==h&&(h=a.options.flattenSpans);var l,i=0,j=null,k=new ze(b,a.options.tabSize);for(\"\"==b&&nf(of(c,d),f);!k.eol();){if(k.pos>a.options.maxHighlightLength?(h=!1,g&&tf(a,b,d,k.pos),k.pos=b.length,l=null):l=nf(pf(c,k,d),f),a.options.addModeClass){var m=w.innerMode(c,d).mode.name;m&&(l=\"m-\"+(l?m+\" \"+l:m))}h&&j==l||(i<k.start&&e(k.start,j),i=k.start,j=l),k.start=k.pos}for(;i<k.pos;){var n=Math.min(k.pos,i+5e4);e(n,j),i=n}}function rf(a,b,c,d){var e=[a.state.modeGen],f={};qf(a,b.text,a.doc.mode,c,function(a,b){e.push(a,b)},f,d);for(var g=0;g<a.state.overlays.length;++g){var h=a.state.overlays[g],i=1,j=0;qf(a,b.text,h.mode,!0,function(a,b){for(var c=i;a>j;){var d=e[i];d>a&&e.splice(i,1,a,e[i+1],d),i+=2,j=Math.min(a,d)}if(b)if(h.opaque)e.splice(c,i-c,a,\"cm-overlay \"+b),i=c+2;else for(;i>c;c+=2){var f=e[c+1];e[c+1]=(f?f+\" \":\"\")+\"cm-overlay \"+b}},f)}return{styles:e,classes:f.bgClass||f.textClass?f:null}}function sf(a,b){if(!b.styles||b.styles[0]!=a.state.modeGen){var c=rf(a,b,b.stateAfter=Wb(a,Sf(b)));b.styles=c.styles,c.classes?b.styleClasses=c.classes:b.styleClasses&&(b.styleClasses=null)}return b.styles}function tf(a,b,c,d){var e=a.doc.mode,f=new ze(b,a.options.tabSize);for(f.start=f.pos=d||0,\"\"==b&&of(e,c);!f.eol()&&f.pos<=a.options.maxHighlightLength;)pf(e,f,c),f.start=f.pos}function wf(a,b){if(!a||/^\\s*$/.test(a))return null;var c=b.addModeClass?vf:uf;return c[a]||(c[a]=a.replace(/\\S+/g,\"cm-$&\"))}function xf(a,b){var c=Wg(\"span\",null,null,f?\"padding-right: .1px\":null),e={pre:Wg(\"pre\",[c]),content:c,col:0,pos:0,cm:a};b.measure={};for(var g=0;g<=(b.rest?b.rest.length:0);g++){var i,h=g?b.rest[g-1]:b.line;e.pos=0,e.addToken=zf,(d||f)&&a.getOption(\"lineWrapping\")&&(e.addToken=Af(e.addToken)),oh(a.display.measure)&&(i=Vf(h))&&(e.addToken=Bf(e.addToken,i)),e.map=[],Df(h,e,sf(a,h)),h.styleClasses&&(h.styleClasses.bgClass&&(e.bgClass=dh(h.styleClasses.bgClass,e.bgClass||\"\")),h.styleClasses.textClass&&(e.textClass=dh(h.styleClasses.textClass,e.textClass||\"\"))),0==e.map.length&&e.map.push(0,0,e.content.appendChild(mh(a.display.measure))),0==g?(b.measure.map=e.map,b.measure.cache={}):((b.measure.maps||(b.measure.maps=[])).push(e.map),(b.measure.caches||(b.measure.caches=[])).push({}))}return rg(a,\"renderLine\",a,b.line,e.pre),e.pre.className&&(e.textClass=dh(e.pre.className,e.textClass||\"\")),e}function yf(a){var b=Wg(\"span\",\"\\u2022\",\"cm-invalidchar\");return b.title=\"\\\\u\"+a.charCodeAt(0).toString(16),b}function zf(a,b,c,f,g,h){if(b){var i=a.cm.options.specialChars,j=!1;if(i.test(b))for(var k=document.createDocumentFragment(),l=0;;){i.lastIndex=l;var m=i.exec(b),n=m?m.index-l:b.length-l;if(n){var o=document.createTextNode(b.slice(l,l+n));d&&9>e?k.appendChild(Wg(\"span\",[o])):k.appendChild(o),a.map.push(a.pos,a.pos+n,o),a.col+=n,a.pos+=n}if(!m)break;if(l+=n+1,\"\t\"==m[0]){var p=a.cm.options.tabSize,q=p-a.col%p,o=k.appendChild(Wg(\"span\",Ig(q),\"cm-tab\"));a.col+=q}else{var o=a.cm.options.specialCharPlaceholder(m[0]);d&&9>e?k.appendChild(Wg(\"span\",[o])):k.appendChild(o),a.col+=1}a.map.push(a.pos,a.pos+1,o),a.pos++}else{a.col+=b.length;var k=document.createTextNode(b);a.map.push(a.pos,a.pos+b.length,k),d&&9>e&&(j=!0),a.pos+=b.length}if(c||f||g||j){var r=c||\"\";f&&(r+=f),g&&(r+=g);var s=Wg(\"span\",[k],r);return h&&(s.title=h),a.content.appendChild(s)}a.content.appendChild(k)}}function Af(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){a(c,d.replace(/ {3,}/g,b),e,f,g,h)}}function Bf(a,b){return function(c,d,e,f,g,h){e=e?e+\" cm-force-border\":\"cm-force-border\";for(var i=c.pos,j=i+d.length;;){for(var k=0;k<b.length;k++){var l=b[k];if(l.to>i&&l.from<=i)break}if(l.to>=j)return a(c,d,e,f,g,h);a(c,d.slice(0,l.to-i),e,f,null,h),f=null,d=d.slice(l.to-i),i=l.to}}}function Cf(a,b,c,d){var e=!d&&c.widgetNode;e&&(a.map.push(a.pos,a.pos+b,e),a.content.appendChild(e)),a.pos+=b}function Df(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||We(q.marker,u)<0)&&(q=t)):t.from>i&&l>t.from&&(l=t.from),\"bookmark\"==u.type&&t.from==i&&u.widgetNode&&r.push(u)}if(q&&(q.from||0)==i&&(Cf(b,(null==q.to?h+1:q.to)-i,q.marker,null==q.from),null==q.to))return;if(!q&&r.length)for(var s=0;s<r.length;++s)Cf(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=wf(c[g++],b.cm.options)}}else for(var g=1;g<c.length;g+=2)b.addToken(b,e.slice(f,f=c[g]),wf(c[g+1],b.cm.options))}function Ef(a,b){return 0==b.from.ch&&0==b.to.ch&&\"\"==Jg(b.text)&&(!a.cm||a.cm.options.wholeLineUpdateBefore)}function Ff(a,b,c,d){function e(a){return c?c[a]:null}function f(a,c,e){lf(a,c,e,d),tg(a,\"change\",a,b)}var g=b.from,h=b.to,i=b.text,j=Of(a,g.line),k=Of(a,h.line),l=Jg(i),m=e(i.length-1),n=h.line-g.line;if(Ef(a,b)){for(var o=0,p=[];o<i.length-1;++o)p.push(new kf(i[o],e(o),d));f(k,k.text,m),n&&a.remove(g.line,n),p.length&&a.insert(g.line,p)}else if(j==k)if(1==i.length)f(j,j.text.slice(0,g.ch)+l+j.text.slice(h.ch),m);else{for(var p=[],o=1;o<i.length-1;++o)p.push(new kf(i[o],e(o),d));p.push(new kf(l+j.text.slice(h.ch),m,d)),f(j,j.text.slice(0,g.ch)+i[0],e(0)),a.insert(g.line+1,p)}else if(1==i.length)f(j,j.text.slice(0,g.ch)+i[0]+k.text.slice(h.ch),e(0)),a.remove(g.line+1,n);else{f(j,j.text.slice(0,g.ch)+i[0],e(0)),f(k,l+k.text.slice(h.ch),m);for(var o=1,p=[];o<i.length-1;++o)p.push(new kf(i[o],e(o),d));n>1&&a.remove(g.line+1,n-1),a.insert(g.line+1,p)}tg(a,\"change\",a,b)}function Gf(a){this.lines=a,this.parent=null;for(var b=0,c=0;b<a.length;++b)a[b].parent=this,c+=a[b].height;this.height=c}function Hf(a){this.children=a;for(var b=0,c=0,d=0;d<a.length;++d){var e=a[d];b+=e.chunkSize(),c+=e.height,e.parent=this}this.size=b,this.height=c,this.parent=null}function Mf(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 Nf(a,b){if(b.cm)throw new Error(\"This document is already in use.\");a.doc=b,b.cm=a,C(a),y(a),a.options.lineWrapping||J(a),a.options.mode=b.modeOption,Pc(a)}function Of(a,b){if(b-=a.first,0>b||b>=a.size)throw new Error(\"There is no line \"+(b+a.first)+\" in the document.\");for(var c=a;!c.lines;)for(var d=0;;++d){var e=c.children[d],f=e.chunkSize();if(f>b){c=e;break}b-=f}return c.lines[b]}function Pf(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 Qf(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function Rf(a,b){var c=b-a.height;if(c)for(var d=a;d;d=d.parent)d.height+=c}function Sf(a){if(null==a.parent)return null;for(var b=a.parent,c=Lg(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 Tf(a,b){var c=a.first;a:do{for(var d=0;d<a.children.length;++d){var e=a.children[d],f=e.height;if(f>b){a=e;continue a}b-=f,c+=e.chunkSize()}return c}while(!a.lines);for(var d=0;d<a.lines.length;++d){var g=a.lines[d],h=g.height;if(h>b)break;b-=h}return c+d}function Uf(a){a=_e(a);for(var b=0,c=a.parent,d=0;d<c.lines.length;++d){var e=c.lines[d];if(e==a)break;b+=e.height}for(var f=c.parent;f;c=f,f=c.parent)for(var d=0;d<f.children.length;++d){var g=f.children[d];if(g==c)break;b+=g.height}return b}function Vf(a){var b=a.order;return null==b&&(b=a.order=Ih(a.text)),b}function Wf(a){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=a||1}function Xf(a,b){var c={from:pb(b.from),to:Kd(b),text:Pf(a,b.from,b.to)};return cg(a,c,b.from.line,b.to.line+1),Mf(a,function(a){cg(a,c,b.from.line,b.to.line+1)},!0),c}function Yf(a){for(;a.length;){var b=Jg(a);if(!b.ranges)break;a.pop()}}function Zf(a,b){return b?(Yf(a.done),Jg(a.done)):a.done.length&&!Jg(a.done).ranges?Jg(a.done):a.done.length>1&&!a.done[a.done.length-2].ranges?(a.done.pop(),Jg(a.done)):void 0}function $f(a,b,c,d){var e=a.history;e.undone.length=0;var g,f=+new Date;if((e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&(\"+\"==b.origin.charAt(0)&&a.cm&&e.lastModTime>f-a.cm.options.historyEventDelay||\"*\"==b.origin.charAt(0)))&&(g=Zf(e,e.lastOp==d))){var h=Jg(g.changes);0==ob(b.from,b.to)&&0==ob(b.from,h.to)?h.to=Kd(b):g.changes.push(Xf(a,b))}else{var i=Jg(e.done);for(i&&i.ranges||bg(a.sel,e.done),g={changes:[Xf(a,b)],generation:e.generation},e.done.push(g);e.done.length>e.undoDepth;)e.done.shift(),e.done[0].ranges||e.done.shift()}e.done.push(c),e.generation=++e.maxGeneration,e.lastModTime=e.lastSelTime=f,e.lastOp=d,e.lastOrigin=e.lastSelOrigin=b.origin,h||rg(a,\"historyAdded\")}function _f(a,b,c,d){var e=b.charAt(0);return\"*\"==e||\"+\"==e&&c.ranges.length==d.ranges.length&&c.somethingSelected()==d.somethingSelected()&&new Date-a.history.lastSelTime<=(a.cm?a.cm.options.historyEventDelay:500)}function ag(a,b,c,d){var e=a.history,f=d&&d.origin;c==e.lastOp||f&&e.lastSelOrigin==f&&(e.lastModTime==e.lastSelTime&&e.lastOrigin==f||_f(a,f,Jg(e.done),b))?e.done[e.done.length-1]=b:bg(b,e.done),e.lastSelTime=+new Date,e.lastSelOrigin=f,e.lastOp=c,d&&d.clearRedo!==!1&&Yf(e.undone)}function bg(a,b){var c=Jg(b);c&&c.ranges&&c.equals(a)||b.push(a)}function cg(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 dg(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 eg(a,b){var c=b[\"spans_\"+a.id];if(!c)return null;for(var d=0,e=[];d<b.text.length;++d)e.push(dg(c[d]));return e}function fg(a,b,c){for(var d=0,e=[];d<a.length;++d){var f=a[d];if(f.ranges)e.push(c?sb.prototype.deepCopy.call(f):f);else{var g=f.changes,h=[];e.push({changes:h});for(var i=0;i<g.length;++i){var k,j=g[i];if(h.push({from:j.from,to:j.to,text:j.text}),b)for(var l in j)(k=l.match(/^spans_(\\d+)$/))&&Lg(b,Number(k[1]))>-1&&(Jg(h)[l]=j[l],delete j[l])}}}return e}function gg(a,b,c,d){c<a.line?a.line+=d:b<a.line&&(a.line=b,a.ch=0)}function hg(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e],g=!0;if(f.ranges){f.copied||(f=a[e]=f.deepCopy(),f.copied=!0);for(var h=0;h<f.ranges.length;h++)gg(f.ranges[h].anchor,b,c,d),gg(f.ranges[h].head,b,c,d)}else{for(var h=0;h<f.changes.length;++h){var i=f.changes[h];if(c<i.from.line)i.from=nb(i.from.line+d,i.from.ch),i.to=nb(i.to.line+d,i.to.ch);else if(b<=i.to.line){g=!1;break}}g||(a.splice(0,e+1),e=0)}}}function ig(a,b){var c=b.from.line,d=b.to.line,e=b.text.length-(d-c)-1;hg(a.done,c,d,e),hg(a.undone,c,d,e)}function lg(a){return null!=a.defaultPrevented?a.defaultPrevented:0==a.returnValue}function ng(a){return a.target||a.srcElement}function og(a){var b=a.which;return null==b&&(1&a.button?b=1:2&a.button?b=3:4&a.button&&(b=2)),p&&a.ctrlKey&&1==b&&(b=3),b}function tg(a,b){function f(a){return function(){a.apply(null,d)}}var c=a._handlers&&a._handlers[b];if(c){var e,d=Array.prototype.slice.call(arguments,2);yc?e=yc.delayedCallbacks:sg?e=sg:(e=sg=[],setTimeout(ug,0));for(var g=0;g<c.length;++g)e.push(f(c[g]))}}function ug(){var a=sg;sg=null;for(var b=0;b<a.length;++b)a[b]()}function vg(a,b,c){return rg(a,c||b.type,a,b),lg(b)||b.codemirrorIgnore}function wg(a){var b=a._handlers&&a._handlers.cursorActivity;if(b)for(var c=a.curOp.cursorActivityHandlers||(a.curOp.cursorActivityHandlers=[]),d=0;d<b.length;++d)-1==Lg(c,b[d])&&c.push(b[d])}function xg(a,b){var c=a._handlers&&a._handlers[b];return c&&c.length>0}function yg(a){a.prototype.on=function(a,b){pg(this,a,b)},a.prototype.off=function(a,b){qg(this,a,b)}}function Eg(){this.id=null}function Gg(a,b,c){for(var d=0,e=0;;){var f=a.indexOf(\"\t\",d);-1==f&&(f=a.length);var g=f-d;if(f==a.length||e+g>=b)return d+Math.min(g,b-e);if(e+=f-d,e+=c-e%c,d=f+1,e>=b)return d}}function Ig(a){for(;Hg.length<=a;)Hg.push(Jg(Hg)+\" \");return Hg[a]}function Jg(a){return a[a.length-1]}function Lg(a,b){for(var c=0;c<a.length;++c)if(a[c]==b)return c;return-1}function Mg(a,b){for(var c=[],d=0;d<a.length;d++)c[d]=b(a[d],d);return c}function Ng(a,b){var c;if(Object.create)c=Object.create(a);else{var d=function(){};d.prototype=a,c=new d}return b&&Og(b,c),c}function Og(a,b,c){b||(b={});for(var d in a)!a.hasOwnProperty(d)||c===!1&&b.hasOwnProperty(d)||(b[d]=a[d]);return b}function Pg(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}}function Sg(a,b){return b?b.source.indexOf(\"\\\\w\")>-1&&Rg(a)?!0:b.test(a):Rg(a)}function Tg(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function Vg(a){return a.charCodeAt(0)>=768&&Ug.test(a)}function Wg(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),\"string\"==typeof b)e.appendChild(document.createTextNode(b));else if(b)for(var f=0;f<b.length;++f)e.appendChild(b[f]);return e}function Yg(a){for(var b=a.childNodes.length;b>0;--b)a.removeChild(a.firstChild);return a}function Zg(a,b){return Yg(a).appendChild(b)}function $g(a,b){if(a.contains)return a.contains(b);for(;b=b.parentNode;)if(b==a)return!0}function _g(){return document.activeElement}function ah(a){return new RegExp(\"\\\\b\"+a+\"\\\\b\\\\s*\")}function bh(a,b){var c=ah(b);c.test(a.className)&&(a.className=a.className.replace(c,\"\"))}function ch(a,b){ah(b).test(a.className)||(a.className+=\" \"+b)}function dh(a,b){for(var c=a.split(\" \"),d=0;d<c.length;d++)c[d]&&!ah(c[d]).test(b)&&(b+=\" \"+c[d]);return b}function eh(a){if(document.body.getElementsByClassName)for(var b=document.body.getElementsByClassName(\"CodeMirror\"),c=0;c<b.length;c++){var d=b[c].CodeMirror;d&&a(d)}}function gh(){fh||(hh(),fh=!0)}function hh(){var a;pg(window,\"resize\",function(){null==a&&(a=setTimeout(function(){a=null,jh=null,eh(dd)},100))}),pg(window,\"blur\",function(){eh(Hd)})}function kh(a){if(null!=jh)return jh;var b=Wg(\"div\",null,null,\"width: 50px; height: 50px; overflow-x: scroll\");return Zg(a,b),b.offsetWidth&&(jh=b.offsetHeight-b.clientHeight),jh||0}function mh(a){if(null==lh){var b=Wg(\"span\",\"\\u200b\");Zg(a,Wg(\"span\",[b,document.createTextNode(\"x\")])),0!=a.firstChild.offsetHeight&&(lh=b.offsetWidth<=1&&b.offsetHeight>2&&!(d&&8>e))}return lh?Wg(\"span\",\"\\u200b\"):Wg(\"span\",\"\\xa0\",null,\"display: inline-block; width: 1px; margin-right: -1px\")}function oh(a){if(null!=nh)return nh;var b=Zg(a,document.createTextNode(\"A\\u062eA\")),c=Xg(b,0,1).getBoundingClientRect();if(c.left==c.right)return!1;var d=Xg(b,1,2).getBoundingClientRect();return nh=d.right-c.right<3}function th(a){if(null!=sh)return sh;var b=Zg(a,Wg(\"span\",\"x\")),c=b.getBoundingClientRect(),d=Xg(b,0,1).getBoundingClientRect();return sh=Math.abs(c.left-d.left)>1}function vh(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 wh(a){return a.level%2?a.to:a.from}function xh(a){return a.level%2?a.from:a.to}function yh(a){var b=Vf(a);return b?wh(b[0]):0}function zh(a){var b=Vf(a);return b?xh(Jg(b)):a.text.length}function Ah(a,b){var c=Of(a.doc,b),d=_e(c);d!=c&&(b=Sf(d));var e=Vf(d),f=e?e[0].level%2?zh(d):yh(d):0;return nb(b,f)}function Bh(a,b){for(var c,d=Of(a.doc,b);c=Ze(d);)d=c.find(1,!0).line,b=null;var e=Vf(d),f=e?e[0].level%2?yh(d):zh(d):d.text.length;return nb(null==b?Sf(d):b,f)}function Ch(a,b,c){var d=a[0].level;return b==d?!0:c==d?!1:c>b}function Eh(a,b){Dh=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 Ch(a,e.level,a[d].level)?(e.from!=e.to&&(Dh=d),c):(e.from!=e.to&&(Dh=c),d);d=c}}return d}function Fh(a,b,c,d){if(!d)return b+c;do b+=c;while(b>0&&Vg(a.text.charAt(b)));return b}function Gh(a,b,c,d){var e=Vf(a);if(!e)return Hh(a,b,c,d);for(var f=Eh(e,b),g=e[f],h=Fh(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 Eh(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?Fh(a,g.to,-1,d):Fh(a,g.from,1,d)}}function Hh(a,b,c,d){var e=b+c;if(d)for(;e>0&&Vg(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=/Trident\\/(?:[7-9]|\\d{2,})\\..*rv:(\\d+)/.exec(navigator.userAgent),d=b||c,e=d&&(b?document.documentMode||6:c[1]),f=/WebKit\\//.test(navigator.userAgent),g=f&&/Qt\\/\\d+\\.\\d+/.test(navigator.userAgent),h=/Chrome\\//.test(navigator.userAgent),i=/Opera\\//.test(navigator.userAgent),j=/Apple Computer/.test(navigator.vendor),k=/KHTML\\//.test(navigator.userAgent),l=/Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(navigator.userAgent),m=/PhantomJS/.test(navigator.userAgent),n=/AppleWebKit/.test(navigator.userAgent)&&/Mobile\\/\\w+/.test(navigator.userAgent),o=n||/Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent),p=n||/Mac/.test(navigator.platform),q=/win/i.test(navigator.platform),r=i&&navigator.userAgent.match(/Version\\/(\\d*\\.\\d*)/);r&&(r=Number(r[1])),r&&r>=15&&(i=!1,f=!0);var s=p&&(g||i&&(null==r||12.11>r)),t=a||d&&e>=9,u=!1,v=!1,nb=w.Pos=function(a,b){return this instanceof nb?(this.line=a,this.ch=b,void 0):new nb(a,b)},ob=w.cmpPos=function(a,b){return a.line-b.line||a.ch-b.ch};sb.prototype={primary:function(){return this.ranges[this.primIndex]},equals:function(a){if(a==this)return!0;if(a.primIndex!=this.primIndex||a.ranges.length!=this.ranges.length)return!1;for(var b=0;b<this.ranges.length;b++){var c=this.ranges[b],d=a.ranges[b];if(0!=ob(c.anchor,d.anchor)||0!=ob(c.head,d.head))return!1}return!0},deepCopy:function(){for(var a=[],b=0;b<this.ranges.length;b++)a[b]=new tb(pb(this.ranges[b].anchor),pb(this.ranges[b].head));return new sb(a,this.primIndex)},somethingSelected:function(){for(var a=0;a<this.ranges.length;a++)if(!this.ranges[a].empty())return!0;return!1},contains:function(a,b){b||(b=a);for(var c=0;c<this.ranges.length;c++){var d=this.ranges[c];if(ob(b,d.from())>=0&&ob(a,d.to())<=0)return c}return-1}},tb.prototype={from:function(){return rb(this.anchor,this.head)},to:function(){return qb(this.anchor,this.head)},empty:function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch}};var vc,hd,id,fc={left:0,right:0,top:0,bottom:0},yc=null,zc=0,Yc=null,od=0,td=0,ud=null;d?ud=-.53:a?ud=15:h?ud=-.7:j&&(ud=-1/3);var yd,Bd=null,Kd=w.changeEnd=function(a){return a.text?nb(a.from.line+a.text.length-1,Jg(a.text).length+(1==a.text.length?a.from.ch:0)):a.to};w.prototype={constructor:w,focus:function(){window.focus(),_c(this),Xc(this)},setOption:function(a,b){var c=this.options,d=c[a];(c[a]!=b||\"mode\"==a)&&(c[a]=b,je.hasOwnProperty(a)&&Kc(this,je[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:Lc(function(a,b){var c=a.token?a:w.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++,Pc(this)}),removeOverlay:Lc(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++,Pc(this),void 0}}),indentLine:Lc(function(a,b,c){\"string\"!=typeof b&&\"number\"!=typeof b&&(b=null==b?this.options.smartIndent?\"smart\":\"prev\":b?\"add\":\"subtract\"),zb(this.doc,a)&&ce(this,a,b,c)}),indentSelection:Lc(function(a){for(var b=this.doc.sel.ranges,c=-1,d=0;d<b.length;d++){var e=b[d];if(e.empty())e.head.line>c&&(ce(this,e.head.line,a,!0),c=e.head.line,d==this.doc.sel.primIndex&&ae(this));else{var f=Math.max(c,e.from().line),g=e.to();c=Math.min(this.lastLine(),g.line-(g.ch?0:1))+1;for(var h=f;c>h;++h)ce(this,h,a)}}}),getTokenAt:function(a,b){var c=this.doc;a=xb(c,a);for(var d=Wb(this,a.line,b),e=this.doc.mode,f=Of(c,a.line),g=new ze(f.text,this.options.tabSize);g.pos<a.ch&&!g.eol();){g.start=g.pos;var h=pf(e,g,d)}return{start:g.start,end:g.pos,string:g.current(),type:h||null,state:d}},getTokenTypeAt:function(a){a=xb(this.doc,a);var f,b=sf(this,Of(this.doc,a.line)),c=0,d=(b.length-1)/2,e=a.ch;if(0==e)f=b[2];else for(;;){var g=c+d>>1;if((g?b[2*g-1]:0)>=e)d=g;else{if(!(b[2*g+1]<e)){f=b[2*g+2];break}c=g+1}}var h=f?f.indexOf(\"cm-overlay \"):-1;return 0>h?f:0==h?null:f.slice(0,h-1)},getModeAt:function(a){var b=this.doc.mode;return b.innerMode?w.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(!qe.hasOwnProperty(b))return qe;var d=qe[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==Lg(c,h.val)&&c.push(h.val)}return c},getStateAfter:function(a,b){var c=this.doc;return a=wb(c,null==a?c.first+c.size-1:a),Wb(this,a+1,b)},cursorCoords:function(a,b){var c,d=this.doc.sel.primary();return c=null==a?d.head:\"object\"==typeof a?xb(this.doc,a):a?d.from():d.to(),qc(this,c,b||\"page\")},charCoords:function(a,b){return pc(this,xb(this.doc,a),b||\"page\")},coordsChar:function(a,b){return a=oc(this,a,b||\"page\"),tc(this,a.left,a.top)},lineAtHeight:function(a,b){return a=oc(this,{top:a,left:0},b||\"page\").top,Tf(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=Of(this.doc,a);return nc(this,e,{top:0,left:0},b||\"page\").top+(c?this.doc.height-Uf(e):0)},defaultTextHeight:function(){return wc(this.display)},defaultCharWidth:function(){return xc(this.display)},setGutterMarker:Lc(function(a,b,c){return de(this.doc,a,\"gutter\",function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&Tg(d)&&(a.gutterMarkers=null),!0})}),clearGutter:Lc(function(a){var b=this,c=b.doc,d=c.first;c.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&(c.gutterMarkers[a]=null,Qc(b,d,\"gutter\"),Tg(c.gutterMarkers)&&(c.gutterMarkers=null)),++d})}),addLineWidget:Lc(function(a,b,c){return jf(this,a,b,c)}),removeLineWidget:function(a){a.clear()},lineInfo:function(a){if(\"number\"==typeof a){if(!zb(this.doc,a))return null;var b=a;if(a=Of(this.doc,a),!a)return null}else{var b=Sf(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.viewFrom,to:this.display.viewTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=qc(this,xb(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&&Zd(this,h,g,h+b.offsetWidth,g+b.offsetHeight)},triggerOnKeyDown:Lc(Cd),triggerOnKeyPress:Lc(Fd),triggerOnKeyUp:Ed,execCommand:function(a){return te.hasOwnProperty(a)?te[a](this):void 0},findPosH:function(a,b,c,d){var e=1;0>b&&(e=-1,b=-b);for(var f=0,g=xb(this.doc,a);b>f&&(g=fe(this.doc,g,e,c,d),!g.hitSide);++f);return g},moveH:Lc(function(a,b){var c=this;c.extendSelectionsBy(function(d){return c.display.shift||c.doc.extend||d.empty()?fe(c.doc,d.head,a,b,c.options.rtlMoveVisually):0>a?d.from():d.to()},Dg)}),deleteH:Lc(function(a,b){var c=this.doc.sel,d=this.doc;c.somethingSelected()?d.replaceSelection(\"\",null,\"+delete\"):ee(this,function(c){var e=fe(d,c.head,a,b,!1);return 0>a?{from:e,to:c.head}:{from:c.head,to:e}})}),findPosV:function(a,b,c,d){var e=1,f=d;0>b&&(e=-1,b=-b);for(var g=0,h=xb(this.doc,a);b>g;++g){var i=qc(this,h,\"div\");\nif(null==f?f=i.left:i.left=f,h=ge(this,i,e,c),h.hitSide)break}return h},moveV:Lc(function(a,b){var c=this,d=this.doc,e=[],f=!c.display.shift&&!d.extend&&d.sel.somethingSelected();if(d.extendSelectionsBy(function(g){if(f)return 0>a?g.from():g.to();var h=qc(c,g.head,\"div\");null!=g.goalColumn&&(h.left=g.goalColumn),e.push(h.left);var i=ge(c,h,a,b);return\"page\"==b&&g==d.sel.primary()&&_d(c,null,pc(c,i,\"div\").top-h.top),i},Dg),e.length)for(var g=0;g<d.sel.ranges.length;g++)d.sel.ranges[g].goalColumn=e[g]}),toggleOverwrite:function(a){(null==a||a!=this.state.overwrite)&&((this.state.overwrite=!this.state.overwrite)?ch(this.display.cursorDiv,\"CodeMirror-overwrite\"):bh(this.display.cursorDiv,\"CodeMirror-overwrite\"),rg(this,\"overwriteToggle\",this,this.state.overwrite))},hasFocus:function(){return _g()==this.display.input},scrollTo:Lc(function(a,b){(null!=a||null!=b)&&be(this),null!=a&&(this.curOp.scrollLeft=a),null!=b&&(this.curOp.scrollTop=b)}),getScrollInfo:function(){var a=this.display.scroller,b=zg;return{left:a.scrollLeft,top:a.scrollTop,height:a.scrollHeight-b,width:a.scrollWidth-b,clientHeight:a.clientHeight-b,clientWidth:a.clientWidth-b}},scrollIntoView:Lc(function(a,b){if(null==a?(a={from:this.doc.sel.primary().head,to:null},null==b&&(b=this.options.cursorScrollMargin)):\"number\"==typeof a?a={from:nb(a,0),to:null}:null==a.from&&(a={from:a,to:null}),a.to||(a.to=a.from),a.margin=b||0,null!=a.from.line)be(this),this.curOp.scrollToPos=a;else{var c=$d(this,Math.min(a.from.left,a.to.left),Math.min(a.from.top,a.to.top)-a.margin,Math.max(a.from.right,a.to.right),Math.max(a.from.bottom,a.to.bottom)+a.margin);this.scrollTo(c.scrollLeft,c.scrollTop)}}),setSize:Lc(function(a,b){function d(a){return\"number\"==typeof a||/^\\d+$/.test(String(a))?a+\"px\":a}var c=this;null!=a&&(c.display.wrapper.style.width=d(a)),null!=b&&(c.display.wrapper.style.height=d(b)),c.options.lineWrapping&&jc(this);var e=c.display.viewFrom;c.doc.iter(e,c.display.viewTo,function(a){if(a.widgets)for(var b=0;b<a.widgets.length;b++)if(a.widgets[b].noHScroll){Qc(c,e,\"widget\");break}++e}),c.curOp.forceUpdate=!0,rg(c,\"refresh\",this)}),operation:function(a){return Jc(this,a)},refresh:Lc(function(){var a=this.display.cachedTextHeight;Pc(this),this.curOp.forceUpdate=!0,kc(this),this.scrollTo(this.doc.scrollLeft,this.doc.scrollTop),H(this),(null==a||Math.abs(a-wc(this.display))>.5)&&C(this),rg(this,\"refresh\",this)}),swapDoc:Lc(function(a){var b=this.doc;return b.cm=null,Nf(this,a),kc(this),$c(this),this.scrollTo(a.scrollLeft,a.scrollTop),tg(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}},yg(w);var ie=w.defaults={},je=w.optionHandlers={},le=w.Init={toString:function(){return\"CodeMirror.Init\"}};ke(\"value\",\"\",function(a,b){a.setValue(b)},!0),ke(\"mode\",null,function(a,b){a.doc.modeOption=b,y(a)},!0),ke(\"indentUnit\",2,y,!0),ke(\"indentWithTabs\",!1),ke(\"smartIndent\",!0),ke(\"tabSize\",4,function(a){z(a),kc(a),Pc(a)},!0),ke(\"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),ke(\"specialCharPlaceholder\",yf,function(a){a.refresh()},!0),ke(\"electricChars\",!0),ke(\"rtlMoveVisually\",!q),ke(\"wholeLineUpdateBefore\",!0),ke(\"theme\",\"default\",function(a){E(a),F(a)},!0),ke(\"keyMap\",\"default\",D),ke(\"extraKeys\",null),ke(\"lineWrapping\",!1,A,!0),ke(\"gutters\",[],function(a){K(a.options),F(a)},!0),ke(\"fixedGutter\",!0,function(a,b){a.display.gutters.style.left=b?S(a.display)+\"px\":\"0\",a.refresh()},!0),ke(\"coverGutterNextToScrollbar\",!1,N,!0),ke(\"lineNumbers\",!1,function(a){K(a.options),F(a)},!0),ke(\"firstLineNumber\",1,F,!0),ke(\"lineNumberFormatter\",function(a){return a},F,!0),ke(\"showCursorWhenSelecting\",!1,Pb,!0),ke(\"resetSelectionOnContextMenu\",!0),ke(\"readOnly\",!1,function(a,b){\"nocursor\"==b?(Hd(a),a.display.input.blur(),a.display.disabled=!0):(a.display.disabled=!1,b||$c(a))}),ke(\"disableInput\",!1,function(a,b){b||$c(a)},!0),ke(\"dragDrop\",!0),ke(\"cursorBlinkRate\",530),ke(\"cursorScrollMargin\",0),ke(\"cursorHeight\",1,Pb,!0),ke(\"singleCursorHeightPerLine\",!0,Pb,!0),ke(\"workTime\",100),ke(\"workDelay\",100),ke(\"flattenSpans\",!0,z,!0),ke(\"addModeClass\",!1,z,!0),ke(\"pollInterval\",100),ke(\"undoDepth\",200,function(a,b){a.doc.history.undoDepth=b}),ke(\"historyEventDelay\",1250),ke(\"viewportMargin\",10,function(a){a.refresh()},!0),ke(\"maxHighlightLength\",1e4,z,!0),ke(\"moveInputWithCursor\",!0,function(a,b){b||(a.display.inputDiv.style.top=a.display.inputDiv.style.left=0)}),ke(\"tabindex\",null,function(a,b){a.display.input.tabIndex=b||\"\"}),ke(\"autofocus\",null);var me=w.modes={},ne=w.mimeModes={};w.defineMode=function(a,b){if(w.defaults.mode||\"null\"==a||(w.defaults.mode=a),arguments.length>2){b.dependencies=[];for(var c=2;c<arguments.length;++c)b.dependencies.push(arguments[c])}me[a]=b},w.defineMIME=function(a,b){ne[a]=b},w.resolveMode=function(a){if(\"string\"==typeof a&&ne.hasOwnProperty(a))a=ne[a];else if(a&&\"string\"==typeof a.name&&ne.hasOwnProperty(a.name)){var b=ne[a.name];\"string\"==typeof b&&(b={name:b}),a=Ng(b,a),a.name=b.name}else if(\"string\"==typeof a&&/^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(a))return w.resolveMode(\"application/xml\");return\"string\"==typeof a?{name:a}:a||{name:\"null\"}},w.getMode=function(a,b){var b=w.resolveMode(b),c=me[b.name];if(!c)return w.getMode(a,\"text/plain\");var d=c(a,b);if(oe.hasOwnProperty(b.name)){var e=oe[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},w.defineMode(\"null\",function(){return{token:function(a){a.skipToEnd()}}}),w.defineMIME(\"text/plain\",\"null\");var oe=w.modeExtensions={};w.extendMode=function(a,b){var c=oe.hasOwnProperty(a)?oe[a]:oe[a]={};Og(b,c)},w.defineExtension=function(a,b){w.prototype[a]=b},w.defineDocExtension=function(a,b){Jf.prototype[a]=b},w.defineOption=ke;var pe=[];w.defineInitHook=function(a){pe.push(a)};var qe=w.helpers={};w.registerHelper=function(a,b,c){qe.hasOwnProperty(a)||(qe[a]=w[a]={_global:[]}),qe[a][b]=c},w.registerGlobalHelper=function(a,b,c,d){w.registerHelper(a,b,d),qe[a]._global.push({pred:c,val:d})};var re=w.copyState=function(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},se=w.startState=function(a,b,c){return a.startState?a.startState(b,c):!0};w.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 te=w.commands={selectAll:function(a){a.setSelection(nb(a.firstLine(),0),nb(a.lastLine()),Bg)},singleSelection:function(a){a.setSelection(a.getCursor(\"anchor\"),a.getCursor(\"head\"),Bg)},killLine:function(a){ee(a,function(b){if(b.empty()){var c=Of(a.doc,b.head.line).text.length;return b.head.ch==c&&b.head.line<a.lastLine()?{from:b.head,to:nb(b.head.line+1,0)}:{from:b.head,to:nb(b.head.line,c)}}return{from:b.from(),to:b.to()}})},deleteLine:function(a){ee(a,function(b){return{from:nb(b.from().line,0),to:xb(a.doc,nb(b.to().line+1,0))}})},delLineLeft:function(a){ee(a,function(a){return{from:nb(a.from().line,0),to:a.from()}})},delWrappedLineLeft:function(a){ee(a,function(b){var c=a.charCoords(b.head,\"div\").top+5,d=a.coordsChar({left:0,top:c},\"div\");return{from:d,to:b.from()}})},delWrappedLineRight:function(a){ee(a,function(b){var c=a.charCoords(b.head,\"div\").top+5,d=a.coordsChar({left:a.display.lineDiv.offsetWidth+100,top:c},\"div\");return{from:b.from(),to:d}})},undo:function(a){a.undo()},redo:function(a){a.redo()},undoSelection:function(a){a.undoSelection()},redoSelection:function(a){a.redoSelection()},goDocStart:function(a){a.extendSelection(nb(a.firstLine(),0))},goDocEnd:function(a){a.extendSelection(nb(a.lastLine()))},goLineStart:function(a){a.extendSelectionsBy(function(b){return Ah(a,b.head.line)},{origin:\"+move\",bias:1})},goLineStartSmart:function(a){a.extendSelectionsBy(function(b){var c=Ah(a,b.head.line),d=a.getLineHandle(c.line),e=Vf(d);if(!e||0==e[0].level){var f=Math.max(0,d.text.search(/\\S/)),g=b.head.line==c.line&&b.head.ch<=f&&b.head.ch;return nb(c.line,g?0:f)}return c},{origin:\"+move\",bias:1})},goLineEnd:function(a){a.extendSelectionsBy(function(b){return Bh(a,b.head.line)},{origin:\"+move\",bias:-1})},goLineRight:function(a){a.extendSelectionsBy(function(b){var c=a.charCoords(b.head,\"div\").top+5;return a.coordsChar({left:a.display.lineDiv.offsetWidth+100,top:c},\"div\")},Dg)},goLineLeft:function(a){a.extendSelectionsBy(function(b){var c=a.charCoords(b.head,\"div\").top+5;return a.coordsChar({left:0,top:c},\"div\")},Dg)},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\")},insertSoftTab:function(a){for(var b=[],c=a.listSelections(),d=a.options.tabSize,e=0;e<c.length;e++){var f=c[e].from(),g=Fg(a.getLine(f.line),f.ch,d);b.push(new Array(d-g%d+1).join(\" \"))}a.replaceSelections(b)},defaultTab:function(a){a.somethingSelected()?a.indentSelection(\"add\"):a.execCommand(\"insertTab\")},transposeChars:function(a){Jc(a,function(){for(var b=a.listSelections(),c=[],d=0;d<b.length;d++){var e=b[d].head,f=Of(a.doc,e.line).text;if(f)if(e.ch==f.length&&(e=new nb(e.line,e.ch-1)),e.ch>0)e=new nb(e.line,e.ch+1),a.replaceRange(f.charAt(e.ch-1)+f.charAt(e.ch-2),nb(e.line,e.ch-2),e,\"+transpose\");else if(e.line>a.doc.first){var g=Of(a.doc,e.line-1).text;g&&a.replaceRange(f.charAt(0)+\"\\n\"+g.charAt(g.length-1),nb(e.line-1,g.length-1),nb(e.line,1),\"+transpose\")}c.push(new tb(e,e))}a.setSelections(c)})},newlineAndIndent:function(a){Jc(a,function(){for(var b=a.listSelections().length,c=0;b>c;c++){var d=a.listSelections()[c];a.replaceRange(\"\\n\",d.anchor,d.head,\"+input\"),a.indentLine(d.from().line+1,null,!0),ae(a)}})},toggleOverwrite:function(a){a.toggleOverwrite()}},ue=w.keyMap={};ue.basic={Left:\"goCharLeft\",Right:\"goCharRight\",Up:\"goLineUp\",Down:\"goLineDown\",End:\"goLineEnd\",Home:\"goLineStartSmart\",PageUp:\"goPageUp\",PageDown:\"goPageDown\",Delete:\"delCharAfter\",Backspace:\"delCharBefore\",\"Shift-Backspace\":\"delCharBefore\",Tab:\"defaultTab\",\"Shift-Tab\":\"indentAuto\",Enter:\"newlineAndIndent\",Insert:\"toggleOverwrite\",Esc:\"singleSelection\"},ue.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\",\"Ctrl-U\":\"undoSelection\",\"Shift-Ctrl-U\":\"redoSelection\",\"Alt-U\":\"redoSelection\",fallthrough:\"basic\"},ue.macDefault={\"Cmd-A\":\"selectAll\",\"Cmd-D\":\"deleteLine\",\"Cmd-Z\":\"undo\",\"Shift-Cmd-Z\":\"redo\",\"Cmd-Y\":\"redo\",\"Cmd-Home\":\"goDocStart\",\"Cmd-Up\":\"goDocStart\",\"Cmd-End\":\"goDocEnd\",\"Cmd-Down\":\"goDocEnd\",\"Alt-Left\":\"goGroupLeft\",\"Alt-Right\":\"goGroupRight\",\"Cmd-Left\":\"goLineLeft\",\"Cmd-Right\":\"goLineRight\",\"Alt-Backspace\":\"delGroupBefore\",\"Ctrl-Alt-Backspace\":\"delGroupAfter\",\"Alt-Delete\":\"delGroupAfter\",\"Cmd-S\":\"save\",\"Cmd-F\":\"find\",\"Cmd-G\":\"findNext\",\"Shift-Cmd-G\":\"findPrev\",\"Cmd-Alt-F\":\"replace\",\"Shift-Cmd-Alt-F\":\"replaceAll\",\"Cmd-[\":\"indentLess\",\"Cmd-]\":\"indentMore\",\"Cmd-Backspace\":\"delWrappedLineLeft\",\"Cmd-Delete\":\"delWrappedLineRight\",\"Cmd-U\":\"undoSelection\",\"Shift-Cmd-U\":\"redoSelection\",fallthrough:[\"basic\",\"emacsy\"]},ue.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\"},ue[\"default\"]=p?ue.macDefault:ue.pcDefault;var we=w.lookupKey=function(a,b,c){function d(b){b=ve(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;g<f.length;++g){var h=d(f[g]);if(h)return h}return!1}for(var e=0;e<b.length;++e){var f=d(b[e]);if(f)return\"stop\"!=f}},xe=w.isModifierKey=function(a){var b=uh[a.keyCode];return\"Ctrl\"==b||\"Alt\"==b||\"Shift\"==b||\"Mod\"==b},ye=w.keyName=function(a,b){if(i&&34==a.keyCode&&a[\"char\"])return!1;var c=uh[a.keyCode];return null==c||a.altGraphKey?!1:(a.altKey&&(c=\"Alt-\"+c),(s?a.metaKey:a.ctrlKey)&&(c=\"Ctrl-\"+c),(s?a.ctrlKey:a.metaKey)&&(c=\"Cmd-\"+c),!b&&a.shiftKey&&(c=\"Shift-\"+c),c)};w.fromTextArea=function(a,b){function d(){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=_g();b.autofocus=c==a||null!=a.getAttribute(\"autofocus\")&&c==document.body}if(a.form&&(pg(a.form,\"submit\",d),!b.leaveSubmitMethodAlone)){var e=a.form,f=e.submit;try{var g=e.submit=function(){d(),e.submit=f,e.submit(),e.submit=g}}catch(h){}}a.style.display=\"none\";var i=w(function(b){a.parentNode.insertBefore(b,a.nextSibling)},b);return i.save=d,i.getTextArea=function(){return a},i.toTextArea=function(){d(),a.parentNode.removeChild(i.getWrapperElement()),a.style.display=\"\",a.form&&(qg(a.form,\"submit\",d),\"function\"==typeof a.form.submit&&(a.form.submit=f))},i};var ze=w.StringStream=function(a,b){this.pos=this.start=0,this.string=a,this.tabSize=b||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0};ze.prototype={eol:function(){return this.pos>=this.string.length},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=Fg(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?Fg(this.string,this.lineStart,this.tabSize):0)},indentation:function(){return Fg(this.string,null,this.tabSize)-(this.lineStart?Fg(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}}};var Ae=w.TextMarker=function(a,b){this.lines=[],this.type=b,this.doc=a};yg(Ae),Ae.prototype.clear=function(){if(!this.explicitlyCleared){var a=this.doc.cm,b=a&&!a.curOp;if(b&&Ac(a),xg(this,\"clear\")){var c=this.find();c&&tg(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=Je(g.markedSpans,this);a&&!this.collapsed?Qc(a,Sf(g),\"text\"):a&&(null!=h.to&&(e=Sf(g)),null!=h.from&&(d=Sf(g))),g.markedSpans=Ke(g.markedSpans,h),null==h.from&&this.collapsed&&!df(this.doc,g)&&a&&Rf(g,wc(a.display))}if(a&&this.collapsed&&!a.options.lineWrapping)for(var f=0;f<this.lines.length;++f){var i=_e(this.lines[f]),j=I(i);j>a.display.maxLineLength&&(a.display.maxLine=i,a.display.maxLineLength=j,a.display.maxLineChanged=!0)}null!=d&&a&&this.collapsed&&Pc(a,d,e+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,a&&Lb(a.doc)),a&&tg(a,\"markerCleared\",a,this),b&&Cc(a),this.parent&&this.parent.clear()}},Ae.prototype.find=function(a,b){null==a&&\"bookmark\"==this.type&&(a=1);for(var c,d,e=0;e<this.lines.length;++e){var f=this.lines[e],g=Je(f.markedSpans,this);if(null!=g.from&&(c=nb(b?f:Sf(f),g.from),-1==a))return c;if(null!=g.to&&(d=nb(b?f:Sf(f),g.to),1==a))return d}return c&&{from:c,to:d}},Ae.prototype.changed=function(){var a=this.find(-1,!0),b=this,c=this.doc.cm;a&&c&&Jc(c,function(){var d=a.line,e=Sf(a.line),f=cc(c,e);if(f&&(ic(f),c.curOp.selectionChanged=c.curOp.forceUpdate=!0),c.curOp.updateMaxLine=!0,!df(b.doc,d)&&null!=b.height){var g=b.height;b.height=null;var h=hf(b)-g;h&&Rf(d,d.height+h)}})},Ae.prototype.attachLine=function(a){if(!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;b.maybeHiddenMarkers&&-1!=Lg(b.maybeHiddenMarkers,this)||(b.maybeUnhiddenMarkers||(b.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(a)},Ae.prototype.detachLine=function(a){if(this.lines.splice(Lg(this.lines,a),1),!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;(b.maybeHiddenMarkers||(b.maybeHiddenMarkers=[])).push(this)}};var Be=0,De=w.SharedTextMarker=function(a,b){this.markers=a,this.primary=b;for(var c=0;c<a.length;++c)a[c].parent=this};yg(De),De.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var a=0;a<this.markers.length;++a)this.markers[a].clear();tg(this,\"clear\")}},De.prototype.find=function(a,b){return this.primary.find(a,b)};var ff=w.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};yg(ff),ff.prototype.clear=function(){var a=this.cm,b=this.line.widgets,c=this.line,d=Sf(c);if(null!=d&&b){for(var e=0;e<b.length;++e)b[e]==this&&b.splice(e--,1);b.length||(c.widgets=null);var f=hf(this);Jc(a,function(){gf(a,c,-f),Qc(a,d,\"widget\"),Rf(c,Math.max(0,c.height-f))})}},ff.prototype.changed=function(){var a=this.height,b=this.cm,c=this.line;this.height=null;var d=hf(this)-a;d&&Jc(b,function(){b.curOp.forceUpdate=!0,gf(b,c,d),Rf(c,c.height+d)})};var kf=w.Line=function(a,b,c){this.text=a,Te(this,b),this.height=c?c(this):1};yg(kf),kf.prototype.lineNo=function(){return Sf(this)};var uf={},vf={};Gf.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,mf(e),tg(e,\"delete\")}this.lines.splice(a,b)},collapse:function(a){a.push.apply(a,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;d<b.length;++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}},Hf.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&&(this.children.length>1||!(this.children[0]instanceof Gf))){var h=[];this.collapse(h),this.children=[new Gf(h)],this.children[0].parent=this}},collapse:function(a){for(var b=0;b<this.children.length;++b)this.children[b].collapse(a)},insertInner:function(a,b,c){this.size+=b.length,this.height+=c;for(var d=0;d<this.children.length;++d){var e=this.children[d],f=e.chunkSize();if(f>=a){if(e.insertInner(a,b,c),e.lines&&e.lines.length>50){for(;e.lines.length>50;){var g=e.lines.splice(e.lines.length-25,25),h=new Gf(g);e.height-=h.height,this.children.splice(d+1,0,h),h.parent=this}this.maybeSpill()}break}a-=f}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new Hf(b);if(a.parent){a.size-=c.size,a.height-=c.height;var e=Lg(a.parent.children,a);a.parent.children.splice(e+1,0,c)}else{var d=new Hf(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;d<this.children.length;++d){var e=this.children[d],f=e.chunkSize();if(f>a){var g=Math.min(b,f-a);if(e.iterN(a,g,c))return!0;if(0==(b-=g))break;a=0}else a-=f}}};var If=0,Jf=w.Doc=function(a,b,c){if(!(this instanceof Jf))return new Jf(a,b,c);null==c&&(c=0),Hf.call(this,[new Gf([new kf(\"\",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.frontier=c;var d=nb(c,0);this.sel=vb(d),this.history=new Wf(null),this.id=++If,this.modeOption=b,\"string\"==typeof a&&(a=ph(a)),Ff(this,{from:d,to:d,text:a}),Ib(this,vb(d),Bg)};Jf.prototype=Ng(Hf.prototype,{constructor:Jf,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;d<b.length;++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=Qf(this,this.first,this.first+this.size);return a===!1?b:b.join(a||\"\\n\")},setValue:Mc(function(a){var b=nb(this.first,0),c=this.first+this.size-1;Qd(this,{from:b,to:nb(c,Of(this,c).text.length),text:ph(a),origin:\"setValue\"},!0),Ib(this,vb(b))}),replaceRange:function(a,b,c,d){b=xb(this,b),c=c?xb(this,c):b,Wd(this,a,b,c,d)},getRange:function(a,b,c){var d=Pf(this,xb(this,a),xb(this,b));return c===!1?d:d.join(c||\"\\n\")},getLine:function(a){var b=this.getLineHandle(a);return b&&b.text},getLineHandle:function(a){return zb(this,a)?Of(this,a):void 0},getLineNumber:function(a){return Sf(a)},getLineHandleVisualStart:function(a){return\"number\"==typeof a&&(a=Of(this,a)),_e(a)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(a){return xb(this,a)},getCursor:function(a){var c,b=this.sel.primary();return c=null==a||\"head\"==a?b.head:\"anchor\"==a?b.anchor:\"end\"==a||\"to\"==a||a===!1?b.to():b.from()},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:Mc(function(a,b,c){Fb(this,xb(this,\"number\"==typeof a?nb(a,b||0):a),null,c)}),setSelection:Mc(function(a,b,c){Fb(this,xb(this,a),xb(this,b||a),c)}),extendSelection:Mc(function(a,b,c){Cb(this,xb(this,a),b&&xb(this,b),c)}),extendSelections:Mc(function(a,b){Db(this,Ab(this,a,b))}),extendSelectionsBy:Mc(function(a,b){Db(this,Mg(this.sel.ranges,a),b)}),setSelections:Mc(function(a,b,c){if(a.length){for(var d=0,e=[];d<a.length;d++)e[d]=new tb(xb(this,a[d].anchor),xb(this,a[d].head));null==b&&(b=Math.min(a.length-1,this.sel.primIndex)),Ib(this,ub(e,b),c)}}),addSelection:Mc(function(a,b,c){var d=this.sel.ranges.slice(0);d.push(new tb(xb(this,a),xb(this,b||a))),Ib(this,ub(d,d.length-1),c)}),getSelection:function(a){for(var c,b=this.sel.ranges,d=0;d<b.length;d++){var e=Pf(this,b[d].from(),b[d].to());c=c?c.concat(e):e}return a===!1?c:c.join(a||\"\\n\")},getSelections:function(a){for(var b=[],c=this.sel.ranges,d=0;d<c.length;d++){var e=Pf(this,c[d].from(),c[d].to());a!==!1&&(e=e.join(a||\"\\n\")),b[d]=e}return b},replaceSelection:function(a,b,c){for(var d=[],e=0;e<this.sel.ranges.length;e++)d[e]=a;this.replaceSelections(d,b,c||\"+input\")},replaceSelections:Mc(function(a,b,c){for(var d=[],e=this.sel,f=0;f<e.ranges.length;f++){var g=e.ranges[f];d[f]={from:g.from(),to:g.to(),text:ph(a[f]),origin:c}}for(var h=b&&\"end\"!=b&&Od(this,d,b),f=d.length-1;f>=0;f--)Qd(this,d[f]);h?Hb(this,h):this.cm&&ae(this.cm)}),undo:Mc(function(){Sd(this,\"undo\")}),redo:Mc(function(){Sd(this,\"redo\")}),undoSelection:Mc(function(){Sd(this,\"undo\",!0)}),redoSelection:Mc(function(){Sd(this,\"redo\",!0)}),setExtending:function(a){this.extend=a},getExtending:function(){return this.extend},historySize:function(){for(var a=this.history,b=0,c=0,d=0;d<a.done.length;d++)a.done[d].ranges||++b;for(var d=0;d<a.undone.length;d++)a.undone[d].ranges||++c;return{undo:b,redo:c}},clearHistory:function(){this.history=new Wf(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:fg(this.history.done),undone:fg(this.history.undone)}},setHistory:function(a){var b=this.history=new Wf(this.history.maxGeneration);b.done=fg(a.done.slice(0),null,!0),b.undone=fg(a.undone.slice(0),null,!0)},addLineClass:Mc(function(a,b,c){return de(this,a,\"class\",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:Mc(function(a,b,c){return de(this,a,\"class\",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})}),markText:function(a,b,c){return Ce(this,xb(this,a),xb(this,b),c,\"range\")},setBookmark:function(a,b){var c={replacedWith:b&&(null==b.nodeType?b.widget:b),insertLeft:b&&b.insertLeft,clearWhenEmpty:!1,shared:b&&b.shared};return a=xb(this,a),Ce(this,a,a,c,\"bookmark\")},findMarksAt:function(a){a=xb(this,a);var b=[],c=Of(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,c){a=xb(this,a),b=xb(this,b);var d=[],e=a.line;return this.iter(a.line,b.line+1,function(f){var g=f.markedSpans;if(g)for(var h=0;h<g.length;h++){var i=g[h];e==a.line&&a.ch>i.to||null==i.from&&e!=a.line||e==b.line&&i.from>b.ch||c&&!c(i.marker)||d.push(i.marker.parent||i.marker)}++e}),d},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)}),xb(this,nb(c,b))},indexFromPos:function(a){a=xb(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 Jf(Qf(this,this.first,this.first+this.size),this.modeOption,this.first);return b.scrollTop=this.scrollTop,b.scrollLeft=this.scrollLeft,b.sel=this.sel,b.extend=!1,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 Jf(Qf(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}],Ge(d,Fe(this)),d},unlinkDoc:function(a){if(a instanceof w&&(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),He(Fe(this));break}}if(a.history==this.history){var d=[a.id];Mf(a,function(a){d.push(a.id)},!0),a.history=new Wf(null),a.history.done=fg(this.history.done,d),a.history.undone=fg(this.history.undone,d)}},iterLinkedDocs:function(a){Mf(this,a)},getMode:function(){return this.mode},getEditor:function(){return this.cm}}),Jf.prototype.eachLine=Jf.prototype.iter;var Kf=\"iter insert remove copy getEditor\".split(\" \");for(var Lf in Jf.prototype)Jf.prototype.hasOwnProperty(Lf)&&Lg(Kf,Lf)<0&&(w.prototype[Lf]=function(a){return function(){return a.apply(this.doc,arguments)}}(Jf.prototype[Lf]));yg(Jf);var jg=w.e_preventDefault=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},kg=w.e_stopPropagation=function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},mg=w.e_stop=function(a){jg(a),kg(a)},pg=w.on=function(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)}},qg=w.off=function(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}}},rg=w.signal=function(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)},sg=null,zg=30,Ag=w.Pass={toString:function(){return\"CodeMirror.Pass\"}},Bg={scroll:!1},Cg={origin:\"*mouse\"},Dg={origin:\"+move\"};Eg.prototype.set=function(a,b){clearTimeout(this.id),this.id=setTimeout(b,a)};var Fg=w.countColumn=function(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;;){var h=a.indexOf(\"\t\",f);if(0>h||h>=b)return g+(b-f);g+=h-f,g+=c-g%c,f=h+1}},Hg=[\"\"],Kg=function(a){a.select()};n?Kg=function(a){a.selectionStart=0,a.selectionEnd=a.value.length}:d&&(Kg=function(a){try{a.select()}catch(b){}}),[].indexOf&&(Lg=function(a,b){return a.indexOf(b)}),[].map&&(Mg=function(a,b){return a.map(b)});var Xg,Qg=/[\\u00df\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/,Rg=w.isWordChar=function(a){return/\\w/.test(a)||a>\"\\x80\"&&(a.toUpperCase()!=a.toLowerCase()||Qg.test(a))},Ug=/[\\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]/;\nXg=document.createRange?function(a,b,c){var d=document.createRange();return d.setEnd(a,c),d.setStart(a,b),d}:function(a,b,c){var d=document.body.createTextRange();return d.moveToElementText(a.parentNode),d.collapse(!0),d.moveEnd(\"character\",c),d.moveStart(\"character\",b),d},d&&11>e&&(_g=function(){try{return document.activeElement}catch(a){return document.body}});var jh,lh,nh,fh=!1,ih=function(){if(d&&9>e)return!1;var a=Wg(\"div\");return\"draggable\"in a||\"dragDrop\"in a}(),ph=w.splitLines=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/)},qh=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},rh=function(){var a=Wg(\"div\");return\"oncopy\"in a?!0:(a.setAttribute(\"oncopy\",\"return;\"),\"function\"==typeof a.oncopy)}(),sh=null,uh={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\"};w.keyNames=uh,function(){for(var a=0;10>a;a++)uh[a+48]=uh[a+96]=String(a);for(var a=65;90>=a;a++)uh[a]=String.fromCharCode(a);for(var a=1;12>=a;a++)uh[a+111]=uh[a+63235]=\"F\"+a}();var Dh,Ih=function(){function c(c){return 247>=c?a.charAt(c):c>=1424&&1524>=c?\"R\":c>=1536&&1773>=c?b.charAt(c-1536):c>=1774&&2220>=c?\"r\":c>=8192&&8203>=c?\"w\":8204==c?\"b\":\"L\"}function j(a,b,c){this.level=a,this.from=b,this.to=c}var a=\"bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN\",b=\"rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm\",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 m,b=a.length,k=[],l=0;b>l;++l)k.push(m=c(a.charCodeAt(l)));for(var l=0,n=i;b>l;++l){var m=k[l];\"m\"==m?k[l]=n:n=m}for(var l=0,o=i;b>l;++l){var m=k[l];\"1\"==m&&\"r\"==o?k[l]=\"n\":f.test(m)&&(o=m,\"r\"==m&&(k[l]=\"R\"))}for(var l=1,n=k[0];b-1>l;++l){var m=k[l];\"+\"==m&&\"1\"==n&&\"1\"==k[l+1]?k[l]=\"1\":\",\"!=m||n!=k[l+1]||\"1\"!=n&&\"n\"!=n||(k[l]=n),n=m}for(var l=0;b>l;++l){var m=k[l];if(\",\"==m)k[l]=\"N\";else if(\"%\"==m){for(var p=l+1;b>p&&\"%\"==k[p];++p);for(var q=l&&\"!\"==k[l-1]||b>p&&\"1\"==k[p]?\"1\":\"N\",r=l;p>r;++r)k[r]=q;l=p-1}}for(var l=0,o=i;b>l;++l){var m=k[l];\"L\"==o&&\"1\"==m?k[l]=\"L\":f.test(m)&&(o=m)}for(var l=0;b>l;++l)if(e.test(k[l])){for(var p=l+1;b>p&&e.test(k[p]);++p);for(var s=\"L\"==(l?k[l-1]:i),t=\"L\"==(b>p?k[p]:i),q=s||t?\"L\":\"R\",r=l;p>r;++r)k[r]=q;l=p-1}for(var v,u=[],l=0;b>l;)if(g.test(k[l])){var w=l;for(++l;b>l&&g.test(k[l]);++l);u.push(new j(0,w,l))}else{var x=l,y=u.length;for(++l;b>l&&\"L\"!=k[l];++l);for(var r=x;l>r;)if(h.test(k[r])){r>x&&u.splice(y,0,new j(1,x,r));var z=r;for(++r;l>r&&h.test(k[r]);++r);u.splice(y,0,new j(2,z,r)),x=r}else++r;l>x&&u.splice(y,0,new j(1,x,l))}return 1==u[0].level&&(v=a.match(/^\\s+/))&&(u[0].from=v[0].length,u.unshift(new j(0,0,v[0].length))),1==Jg(u).level&&(v=a.match(/\\s+$/))&&(Jg(u).to-=v[0].length,u.push(new j(0,b-v[0].length,b))),u[0].level!=Jg(u).level&&u.push(new j(u[0].level,b,b)),u}}();return w.version=\"4.4.0\",w}),function(a){\"object\"==typeof exports&&\"object\"==typeof module?a(require(\"../../lib/codemirror\"),require(\"../htmlmixed/htmlmixed\")):\"function\"==typeof define&&define.amd?define([\"../../lib/codemirror\",\"../htmlmixed/htmlmixed\"],a):a(CodeMirror)}(function(a){\"use strict\";a.defineMode(\"htmlembedded\",function(b,c){function h(a,b){return a.match(d,!1)?(b.token=i,f.token(a,b.scriptState)):g.token(a,b.htmlState)}function i(a,b){return a.match(e,!1)?(b.token=h,g.token(a,b.htmlState)):f.token(a,b.scriptState)}var f,g,d=c.scriptStartRegex||/^<%/i,e=c.scriptEndRegex||/^%>/i;return{startState:function(){return f=f||a.getMode(b,c.scriptingModeSpec),g=g||a.getMode(b,\"htmlmixed\"),{token:c.startOpen?i:h,htmlState:a.startState(g),scriptState:a.startState(f)}},token:function(a,b){return b.token(a,b)},indent:function(a,b){return a.token==h?g.indent(a.htmlState,b):f.indent?f.indent(a.scriptState,b):void 0},copyState:function(b){return{token:b.token,htmlState:a.copyState(g,b.htmlState),scriptState:a.copyState(f,b.scriptState)}},innerMode:function(a){return a.token==i?{state:a.scriptState,mode:f}:{state:a.htmlState,mode:g}}}},\"htmlmixed\"),a.defineMIME(\"application/x-ejs\",{name:\"htmlembedded\",scriptingModeSpec:\"javascript\"}),a.defineMIME(\"application/x-aspx\",{name:\"htmlembedded\",scriptingModeSpec:\"text/x-csharp\"}),a.defineMIME(\"application/x-jsp\",{name:\"htmlembedded\",scriptingModeSpec:\"text/x-java\"}),a.defineMIME(\"application/x-erb\",{name:\"htmlembedded\",scriptingModeSpec:\"ruby\"})}),function(a){\"object\"==typeof exports&&\"object\"==typeof module?a(require(\"../../lib/codemirror\"),require(\"../xml/xml\"),require(\"../javascript/javascript\"),require(\"../css/css\")):\"function\"==typeof define&&define.amd?define([\"../../lib/codemirror\",\"../xml/xml\",\"../javascript/javascript\",\"../css/css\"],a):a(CodeMirror)}(function(a){\"use strict\";a.defineMode(\"htmlmixed\",function(b,c){function j(a,b){var c=b.htmlState.tagName,g=d.token(a,b.htmlState);if(\"script\"==c&&/\\btag\\b/.test(g)&&\">\"==a.current()){var h=a.string.slice(Math.max(0,a.pos-100),a.pos).match(/\\btype\\s*=\\s*(\"[^\"]+\"|'[^']+'|\\S+)[^<]*$/i);h=h?h[1]:\"\",h&&/[\\\"\\']/.test(h.charAt(0))&&(h=h.slice(1,h.length-1));for(var i=0;i<f.length;++i){var j=f[i];if(\"string\"==typeof j.matches?h==j.matches:j.matches.test(h)){j.mode&&(b.token=l,b.localMode=j.mode,b.localState=j.mode.startState&&j.mode.startState(d.indent(b.htmlState,\"\")));break}}}else\"style\"==c&&/\\btag\\b/.test(g)&&\">\"==a.current()&&(b.token=m,b.localMode=e,b.localState=e.startState(d.indent(b.htmlState,\"\")));return g}function k(a,b,c){var f,d=a.current(),e=d.search(b);return e>-1?a.backUp(d.length-e):(f=d.match(/<\\/?$/))&&(a.backUp(d.length),a.match(b,!1)||a.match(d)),c}function l(a,b){return a.match(/^<\\/\\s*script\\s*>/i,!1)?(b.token=j,b.localState=b.localMode=null,j(a,b)):k(a,/<\\/\\s*script\\s*>/,b.localMode.token(a,b.localState))}function m(a,b){return a.match(/^<\\/\\s*style\\s*>/i,!1)?(b.token=j,b.localState=b.localMode=null,j(a,b)):k(a,/<\\/\\s*style\\s*>/,e.token(a,b.localState))}var d=a.getMode(b,{name:\"xml\",htmlMode:!0,multilineTagIndentFactor:c.multilineTagIndentFactor,multilineTagIndentPastTag:c.multilineTagIndentPastTag}),e=a.getMode(b,\"css\"),f=[],g=c&&c.scriptTypes;if(f.push({matches:/^(?:text|application)\\/(?:x-)?(?:java|ecma)script$|^$/i,mode:a.getMode(b,\"javascript\")}),g)for(var h=0;h<g.length;++h){var i=g[h];f.push({matches:i.matches,mode:i.mode&&a.getMode(b,i.mode)})}return f.push({matches:/./,mode:a.getMode(b,\"text/plain\")}),{startState:function(){var a=d.startState();return{token:j,localMode:null,localState:null,htmlState:a}},copyState:function(b){if(b.localState)var c=a.copyState(b.localMode,b.localState);return{token:b.token,localMode:b.localMode,localState:c,htmlState:a.copyState(d,b.htmlState)}},token:function(a,b){return b.token(a,b)},indent:function(b,c){return!b.localMode||/^\\s*<\\//.test(c)?d.indent(b.htmlState,c):b.localMode.indent?b.localMode.indent(b.localState,c):a.Pass},innerMode:function(a){return{state:a.localState||a.htmlState,mode:a.localMode||d}}}},\"xml\",\"javascript\",\"css\"),a.defineMIME(\"text/html\",\"htmlmixed\")}),function(a){\"object\"==typeof exports&&\"object\"==typeof module?a(require(\"../../lib/codemirror\")):\"function\"==typeof define&&define.amd?define([\"../../lib/codemirror\"],a):a(CodeMirror)}(function(a){\"use strict\";a.defineMode(\"javascript\",function(b,c){function l(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 o(a,b,c){return m=a,n=c,b}function p(a,b){var c=a.next();if('\"'==c||\"'\"==c)return b.tokenize=q(c),b.tokenize(a,b);if(\".\"==c&&a.match(/^\\d+(?:[eE][+\\-]?\\d+)?/))return o(\"number\",\"number\");if(\".\"==c&&a.match(\"..\"))return o(\"spread\",\"meta\");if(/[\\[\\]{}\\(\\),;\\:\\.]/.test(c))return o(c);if(\"=\"==c&&a.eat(\">\"))return o(\"=>\",\"operator\");if(\"0\"==c&&a.eat(/x/i))return a.eatWhile(/[\\da-f]/i),o(\"number\",\"number\");if(/\\d/.test(c))return a.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/),o(\"number\",\"number\");if(\"/\"==c)return a.eat(\"*\")?(b.tokenize=r,r(a,b)):a.eat(\"/\")?(a.skipToEnd(),o(\"comment\",\"comment\")):\"operator\"==b.lastType||\"keyword c\"==b.lastType||\"sof\"==b.lastType||/^[\\[{}\\(,;:]$/.test(b.lastType)?(l(a),a.eatWhile(/[gimy]/),o(\"regexp\",\"string-2\")):(a.eatWhile(j),o(\"operator\",\"operator\",a.current()));if(\"`\"==c)return b.tokenize=s,s(a,b);if(\"#\"==c)return a.skipToEnd(),o(\"error\",\"error\");if(j.test(c))return a.eatWhile(j),o(\"operator\",\"operator\",a.current());a.eatWhile(/[\\w\\$_]/);var d=a.current(),e=i.propertyIsEnumerable(d)&&i[d];return e&&\".\"!=b.lastType?o(e.type,e.style,d):o(\"variable\",\"variable\",d)}function q(a){return function(b,c){var e,d=!1;if(f&&\"@\"==b.peek()&&b.match(k))return c.tokenize=p,o(\"jsonld-keyword\",\"meta\");for(;null!=(e=b.next())&&(e!=a||d);)d=!d&&\"\\\\\"==e;return d||(c.tokenize=p),o(\"string\",\"string\")}}function r(a,b){for(var d,c=!1;d=a.next();){if(\"/\"==d&&c){b.tokenize=p;break}c=\"*\"==d}return o(\"comment\",\"comment\")}function s(a,b){for(var d,c=!1;null!=(d=a.next());){if(!c&&(\"`\"==d||\"$\"==d&&a.eat(\"{\"))){b.tokenize=p;break}c=!c&&\"\\\\\"==d}return o(\"quasi\",\"string-2\",a.current())}function u(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=t.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 w(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 x(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 y(a,b,c,d,e){var f=a.cc;for(z.state=a,z.stream=e,z.marked=null,z.cc=f,z.style=b,a.lexical.hasOwnProperty(\"align\")||(a.lexical.align=!0);;){var h=f.length?f.pop():g?K:J;if(h(c,d)){for(;f.length&&f[f.length-1].lex;)f.pop()();return z.marked?z.marked:\"variable\"==c&&x(a,d)?\"variable-2\":b}}}function A(){for(var a=arguments.length-1;a>=0;a--)z.cc.push(arguments[a])}function B(){return A.apply(null,arguments),!0}function C(a){function b(b){for(var c=b;c;c=c.next)if(c.name==a)return!0;return!1}var d=z.state;if(d.context){if(z.marked=\"def\",b(d.localVars))return;d.localVars={name:a,next:d.localVars}}else{if(b(d.globalVars))return;c.globalVars&&(d.globalVars={name:a,next:d.globalVars})}}function E(){z.state.context={prev:z.state.context,vars:z.state.localVars},z.state.localVars=D}function F(){z.state.localVars=z.state.context.vars,z.state.context=z.state.context.prev}function G(a,b){var c=function(){var c=z.state,d=c.indented;if(\"stat\"==c.lexical.type)d=c.lexical.indented;else for(var e=c.lexical;e&&\")\"==e.type&&e.align;e=e.prev)d=e.indented;c.lexical=new w(d,z.stream.column(),a,null,c.lexical,b)};return c.lex=!0,c}function H(){var a=z.state;a.lexical.prev&&(\")\"==a.lexical.type&&(a.indented=a.lexical.indented),a.lexical=a.lexical.prev)}function I(a){function b(c){return c==a?B():\";\"==a?A():B(b)}return b}function J(a,b){return\"var\"==a?B(G(\"vardef\",b.length),db,I(\";\"),H):\"keyword a\"==a?B(G(\"form\"),K,J,H):\"keyword b\"==a?B(G(\"form\"),J,H):\"{\"==a?B(G(\"}\"),ab,H):\";\"==a?B():\"if\"==a?(\"else\"==z.state.lexical.info&&z.state.cc[z.state.cc.length-1]==H&&z.state.cc.pop()(),B(G(\"form\"),K,J,H,ib)):\"function\"==a?B(ob):\"for\"==a?B(G(\"form\"),jb,J,H):\"variable\"==a?B(G(\"stat\"),V):\"switch\"==a?B(G(\"form\"),K,G(\"}\",\"switch\"),I(\"{\"),ab,H,H):\"case\"==a?B(K,I(\":\")):\"default\"==a?B(I(\":\")):\"catch\"==a?B(G(\"form\"),E,I(\"(\"),pb,I(\")\"),J,H,F):\"module\"==a?B(G(\"form\"),E,ub,F,H):\"class\"==a?B(G(\"form\"),qb,H):\"export\"==a?B(G(\"form\"),vb,H):\"import\"==a?B(G(\"form\"),wb,H):A(G(\"stat\"),K,I(\";\"),H)}function K(a){return M(a,!1)}function L(a){return M(a,!0)}function M(a,b){if(z.state.fatArrowAt==z.stream.start){var c=b?U:T;if(\"(\"==a)return B(E,G(\")\"),$(eb,\")\"),H,I(\"=>\"),c,F);if(\"variable\"==a)return A(E,eb,I(\"=>\"),c,F)}var d=b?Q:P;return v.hasOwnProperty(a)?B(d):\"function\"==a?B(ob,d):\"keyword c\"==a?B(b?O:N):\"(\"==a?B(G(\")\"),N,Bb,I(\")\"),H,d):\"operator\"==a||\"spread\"==a?B(b?L:K):\"[\"==a?B(G(\"]\"),zb,H,d):\"{\"==a?_(X,\"}\",null,d):\"quasi\"==a?A(R,d):B()}function N(a){return a.match(/[;\\}\\)\\],]/)?A():A(K)}function O(a){return a.match(/[;\\}\\)\\],]/)?A():A(L)}function P(a,b){return\",\"==a?B(K):Q(a,b,!1)}function Q(a,b,c){var d=0==c?P:Q,e=0==c?K:L;return\"=>\"==b?B(E,c?U:T,F):\"operator\"==a?/\\+\\+|--/.test(b)?B(d):\"?\"==b?B(K,I(\":\"),e):B(e):\"quasi\"==a?A(R,d):\";\"!=a?\"(\"==a?_(L,\")\",\"call\",d):\".\"==a?B(W,d):\"[\"==a?B(G(\"]\"),N,I(\"]\"),H,d):void 0:void 0}function R(a,b){return\"quasi\"!=a?A():\"${\"!=b.slice(b.length-2)?B(R):B(K,S)}function S(a){return\"}\"==a?(z.marked=\"string-2\",z.state.tokenize=s,B(R)):void 0}function T(a){return u(z.stream,z.state),\"{\"==a?A(J):A(K)}function U(a){return u(z.stream,z.state),\"{\"==a?A(J):A(L)}function V(a){return\":\"==a?B(H,J):A(P,I(\";\"),H)}function W(a){return\"variable\"==a?(z.marked=\"property\",B()):void 0}function X(a,b){return\"variable\"==a||\"keyword\"==z.style?(z.marked=\"property\",\"get\"==b||\"set\"==b?B(Y):B(Z)):\"number\"==a||\"string\"==a?(z.marked=f?\"property\":z.style+\" property\",B(Z)):\"jsonld-keyword\"==a?B(Z):\"[\"==a?B(K,I(\"]\"),Z):void 0}function Y(a){return\"variable\"!=a?A(Z):(z.marked=\"property\",B(ob))}function Z(a){return\":\"==a?B(L):\"(\"==a?A(ob):void 0}function $(a,b){function c(d){if(\",\"==d){var e=z.state.lexical;return\"call\"==e.info&&(e.pos=(e.pos||0)+1),B(a,c)}return d==b?B():B(I(b))}return function(d){return d==b?B():A(a,c)}}function _(a,b,c){for(var d=3;d<arguments.length;d++)z.cc.push(arguments[d]);return B(G(b,c),$(a,b),H)}function ab(a){return\"}\"==a?B():A(J,ab)}function bb(a){return h&&\":\"==a?B(cb):void 0}function cb(a){return\"variable\"==a?(z.marked=\"variable-3\",B()):void 0}function db(){return A(eb,bb,gb,hb)}function eb(a,b){return\"variable\"==a?(C(b),B()):\"[\"==a?_(eb,\"]\"):\"{\"==a?_(fb,\"}\"):void 0}function fb(a,b){return\"variable\"!=a||z.stream.match(/^\\s*:/,!1)?(\"variable\"==a&&(z.marked=\"property\"),B(I(\":\"),eb,gb)):(C(b),B(gb))}function gb(a,b){return\"=\"==b?B(L):void 0}function hb(a){return\",\"==a?B(db):void 0}function ib(a,b){return\"keyword b\"==a&&\"else\"==b?B(G(\"form\",\"else\"),J,H):void 0}function jb(a){return\"(\"==a?B(G(\")\"),kb,I(\")\"),H):void 0}function kb(a){return\"var\"==a?B(db,I(\";\"),mb):\";\"==a?B(mb):\"variable\"==a?B(lb):A(K,I(\";\"),mb)}function lb(a,b){return\"in\"==b||\"of\"==b?(z.marked=\"keyword\",B(K)):B(P,mb)}function mb(a,b){return\";\"==a?B(nb):\"in\"==b||\"of\"==b?(z.marked=\"keyword\",B(K)):A(K,I(\";\"),nb)}function nb(a){\")\"!=a&&B(K)}function ob(a,b){return\"*\"==b?(z.marked=\"keyword\",B(ob)):\"variable\"==a?(C(b),B(ob)):\"(\"==a?B(E,G(\")\"),$(pb,\")\"),H,J,F):void 0}function pb(a){return\"spread\"==a?B(pb):A(eb,bb)}function qb(a,b){return\"variable\"==a?(C(b),B(rb)):void 0}function rb(a,b){return\"extends\"==b?B(K,rb):\"{\"==a?B(G(\"}\"),sb,H):void 0}function sb(a,b){return\"variable\"==a||\"keyword\"==z.style?(z.marked=\"property\",\"get\"==b||\"set\"==b?B(tb,ob,sb):B(ob,sb)):\"*\"==b?(z.marked=\"keyword\",B(sb)):\";\"==a?B(sb):\"}\"==a?B():void 0}function tb(a){return\"variable\"!=a?A():(z.marked=\"property\",B())}function ub(a,b){return\"string\"==a?B(J):\"variable\"==a?(C(b),B(yb)):void 0}function vb(a,b){return\"*\"==b?(z.marked=\"keyword\",B(yb,I(\";\"))):\"default\"==b?(z.marked=\"keyword\",B(K,I(\";\"))):A(J)}function wb(a){return\"string\"==a?B():A(xb,yb)}function xb(a,b){return\"{\"==a?_(xb,\"}\"):(\"variable\"==a&&C(b),B())}function yb(a,b){return\"from\"==b?(z.marked=\"keyword\",B(K)):void 0}function zb(a){return\"]\"==a?B():A(L,Ab)}function Ab(a){return\"for\"==a?A(Bb,I(\"]\")):\",\"==a?B($(L,\"]\")):A($(L,\"]\"))}function Bb(a){return\"for\"==a?B(jb,Bb):\"if\"==a?B(K,Bb):void 0}var m,n,d=b.indentUnit,e=c.statementIndent,f=c.jsonld,g=c.json||f,h=c.typescript,i=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\"},g={\"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(h){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)g[k]=j[k]}return g}(),j=/[+\\-*&%=<>!?|~^]/,k=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)\"/,t=\"([{}])\",v={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,\"this\":!0,\"jsonld-keyword\":!0},z={state:null,column:null,marked:null,cc:null},D={name:\"this\",next:{name:\"arguments\"}};return H.lex=!0,{startState:function(a){var b={tokenize:p,lastType:\"sof\",cc:[],lexical:new w((a||0)-d,0,\"block\",!1),localVars:c.localVars,context:c.localVars&&{vars:c.localVars},indented:0};return c.globalVars&&\"object\"==typeof c.globalVars&&(b.globalVars=c.globalVars),b},token:function(a,b){if(a.sol()&&(b.lexical.hasOwnProperty(\"align\")||(b.lexical.align=!1),b.indented=a.indentation(),u(a,b)),b.tokenize!=r&&a.eatSpace())return null;var c=b.tokenize(a,b);return\"comment\"==m?c:(b.lastType=\"operator\"!=m||\"++\"!=n&&\"--\"!=n?m:\"incdec\",y(b,c,m,n,a))},indent:function(b,f){if(b.tokenize==r)return a.Pass;if(b.tokenize!=p)return 0;var g=f&&f.charAt(0),h=b.lexical;if(!/^\\s*else\\b/.test(f))for(var i=b.cc.length-1;i>=0;--i){var j=b.cc[i];if(j==H)h=h.prev;else if(j!=ib)break}\"stat\"==h.type&&\"}\"==g&&(h=h.prev),e&&\")\"==h.type&&\"stat\"==h.prev.type&&(h=h.prev);var k=h.type,l=g==k;return\"vardef\"==k?h.indented+(\"operator\"==b.lastType||\",\"==b.lastType?h.info+1:0):\"form\"==k&&\"{\"==g?h.indented:\"form\"==k?h.indented+d:\"stat\"==k?h.indented+(\"operator\"==b.lastType||\",\"==b.lastType?e||d:0):\"switch\"!=h.info||l||0==c.doubleIndentSwitch?h.align?h.column+(l?0:1):h.indented+(l?0:d):h.indented+(/^(?:case|default)\\b/.test(f)?d:2*d)},electricChars:\":{}\",blockCommentStart:g?null:\"/*\",blockCommentEnd:g?null:\"*/\",lineComment:g?null:\"//\",fold:\"brace\",helperType:g?\"json\":\"javascript\",jsonldMode:f,jsonMode:g}}),a.registerHelper(\"wordChars\",\"javascript\",/[\\\\w$]/),a.defineMIME(\"text/javascript\",\"javascript\"),a.defineMIME(\"text/ecmascript\",\"javascript\"),a.defineMIME(\"application/javascript\",\"javascript\"),a.defineMIME(\"application/x-javascript\",\"javascript\"),a.defineMIME(\"application/ecmascript\",\"javascript\"),a.defineMIME(\"application/json\",{name:\"javascript\",json:!0}),a.defineMIME(\"application/x-json\",{name:\"javascript\",json:!0}),a.defineMIME(\"application/ld+json\",{name:\"javascript\",jsonld:!0}),a.defineMIME(\"text/typescript\",{name:\"javascript\",typescript:!0}),a.defineMIME(\"application/typescript\",{name:\"javascript\",typescript:!0})});"
  },
  {
    "path": "togetherjs/tests/doctestjs/.gitignore",
    "content": ".resources/_build\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.gitmodules",
    "content": "[submodule \".resources/esprima\"]\n\tpath = .resources/esprima\n\turl = https://github.com/ariya/esprima.git\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.hgignore",
    "content": "syntax:glob\n.svn\n.hgsvn\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/CNAME",
    "content": "doctestjs.org\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/boilerplate/404.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"utf-8\">\n        <title>Page Not Found :(</title>\n        <style>\n            ::-moz-selection {\n                background: #b3d4fc;\n                text-shadow: none;\n            }\n\n            ::selection {\n                background: #b3d4fc;\n                text-shadow: none;\n            }\n\n            html {\n                padding: 30px 10px;\n                font-size: 20px;\n                line-height: 1.4;\n                color: #737373;\n                background: #f0f0f0;\n                -webkit-text-size-adjust: 100%;\n                -ms-text-size-adjust: 100%;\n            }\n\n            html,\n            input {\n                font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n            }\n\n            body {\n                max-width: 500px;\n                _width: 500px;\n                padding: 30px 20px 50px;\n                border: 1px solid #b3b3b3;\n                border-radius: 4px;\n                margin: 0 auto;\n                box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n                background: #fcfcfc;\n            }\n\n            h1 {\n                margin: 0 10px;\n                font-size: 50px;\n                text-align: center;\n            }\n\n            h1 span {\n                color: #bbb;\n            }\n\n            h3 {\n                margin: 1.5em 0 0.5em;\n            }\n\n            p {\n                margin: 1em 0;\n            }\n\n            ul {\n                padding: 0 0 0 40px;\n                margin: 1em 0;\n            }\n\n            .container {\n                max-width: 380px;\n                _width: 380px;\n                margin: 0 auto;\n            }\n\n            /* google search */\n\n            #goog-fixurl ul {\n                list-style: none;\n                padding: 0;\n                margin: 0;\n            }\n\n            #goog-fixurl form {\n                margin: 0;\n            }\n\n            #goog-wm-qt,\n            #goog-wm-sb {\n                border: 1px solid #bbb;\n                font-size: 16px;\n                line-height: normal;\n                vertical-align: top;\n                color: #444;\n                border-radius: 2px;\n            }\n\n            #goog-wm-qt {\n                width: 220px;\n                height: 20px;\n                padding: 5px;\n                margin: 5px 10px 0 0;\n                box-shadow: inset 0 1px 1px #ccc;\n            }\n\n            #goog-wm-sb {\n                display: inline-block;\n                height: 32px;\n                padding: 0 10px;\n                margin: 5px 0 0;\n                white-space: nowrap;\n                cursor: pointer;\n                background-color: #f5f5f5;\n                background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n                -webkit-appearance: none;\n                -moz-appearance: none;\n                appearance: none;\n                *overflow: visible;\n                *display: inline;\n                *zoom: 1;\n            }\n\n            #goog-wm-sb:hover,\n            #goog-wm-sb:focus {\n                border-color: #aaa;\n                box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n                background-color: #f8f8f8;\n            }\n\n            #goog-wm-qt:hover,\n            #goog-wm-qt:focus {\n                border-color: #105cb6;\n                outline: 0;\n                color: #222;\n            }\n\n            input::-moz-focus-inner {\n                padding: 0;\n                border: 0;\n            }\n        </style>\n    </head>\n    <body>\n        <div class=\"container\">\n            <h1>Not found <span>:(</span></h1>\n            <p>Sorry, but the page you were trying to view does not exist.</p>\n            <p>It looks like this was the result of either:</p>\n            <ul>\n                <li>a mistyped address</li>\n                <li>an out-of-date link</li>\n            </ul>\n            <script>\n                var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;\n            </script>\n            <script src=\"http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js\"></script>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/boilerplate/css/main.css",
    "content": "/* ==========================================================================\n   HTML5 Boilerplate styles - h5bp.com (generated via initializr.com)\n   ========================================================================== */\n\nhtml,\nbutton,\ninput,\nselect,\ntextarea {\n    color: #222;\n}\n\nbody {\n    font-size: 1em;\n    line-height: 1.4;\n}\n\n::-moz-selection {\n    background: #b3d4fc;\n    text-shadow: none;\n}\n\n::selection {\n    background: #b3d4fc;\n    text-shadow: none;\n}\n\nhr {\n    display: block;\n    height: 1px;\n    border: 0;\n    border-top: 1px solid #ccc;\n    margin: 1em 0;\n    padding: 0;\n}\n\nimg {\n    vertical-align: middle;\n}\n\nfieldset {\n    border: 0;\n    margin: 0;\n    padding: 0;\n}\n\ntextarea {\n    resize: vertical;\n}\n\n.chromeframe {\n    margin: 0.2em 0;\n    background: #ccc;\n    color: #000;\n    padding: 0.2em 0;\n}\n\n\n/* ===== Initializr Styles ==================================================\n   Author: Jonathan Verrecchia - verekia.com/initializr/responsive-template\n   ========================================================================== */\n\nbody {\n    font: 16px/26px Helvetica, Helvetica Neue, Arial;\n}\n\n.wrapper {\n    width: 90%;\n    margin: 0 5%;\n}\n\n/* ===================\n    ALL: Orange Theme\n   =================== */\n\n.header-container {\n    border-bottom: 20px solid #e44d26;\n}\n\n.footer-container,\n.main aside {\n    border-top: 20px solid #e44d26;\n}\n\n.header-container,\n.footer-container,\n.main aside {\n    background: #f16529;\n}\n\n.title {\n    color: white;\n}\n\n/* ==============\n    MOBILE: Menu\n   ============== */\n\nnav ul {\n    margin: 0;\n    padding: 0;\n}\n\nnav a {\n    display: block;\n    margin-bottom: 10px;\n    padding: 15px 0;\n\n    text-align: center;\n    text-decoration: none;\n    font-weight: bold;\n\n    color: white;\n    background: #e44d26;\n}\n\nnav a:hover,\nnav a:visited {\n    color: white;\n}\n\nnav a:hover {\n    text-decoration: underline;\n}\n\n/* ==============\n    MOBILE: Main\n   ============== */\n\n.main {\n    padding: 30px 0;\n}\n\n.main article h1 {\n    font-size: 2em;\n}\n\n.main aside {\n    color: white;\n    padding: 0px 5% 10px;\n}\n\n.footer-container footer {\n    color: white;\n    padding: 20px 0;\n}\n\n/* ===============\n    ALL: IE Fixes\n   =============== */\n\n.ie7 .title {\n    padding-top: 20px;\n}\n\n/* ==========================================================================\n   Author's custom styles\n   ========================================================================== */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* ==========================================================================\n   Media Queries\n   ========================================================================== */\n\n@media only screen and (min-width: 480px) {\n\n/* ====================\n    INTERMEDIATE: Menu\n   ==================== */\n\n    nav a {\n        float: left;\n        width: 27%;\n        margin: 0 1.7%;\n        padding: 25px 2%;\n        margin-bottom: 0;\n    }\n\n    nav li:first-child a {\n        margin-left: 0;\n    }\n\n    nav li:last-child a {\n        margin-right: 0;\n    }\n\n/* ========================\n    INTERMEDIATE: IE Fixes\n   ======================== */\n\n    nav ul li {\n        display: inline;\n    }\n\n    .oldie nav a {\n        margin: 0 0.7%;\n    }\n}\n\n@media only screen and (min-width: 768px) {\n\n/* ====================\n    WIDE: CSS3 Effects\n   ==================== */\n\n    .header-container,\n    .main aside {\n        -webkit-box-shadow: 0 5px 10px #aaa;\n           -moz-box-shadow: 0 5px 10px #aaa;\n                box-shadow: 0 5px 10px #aaa;\n    }\n\n/* ============\n    WIDE: Menu\n   ============ */\n\n    .title {\n        float: left;\n    }\n\n    nav {\n        float: right;\n        width: 38%;\n    }\n\n/* ============\n    WIDE: Main\n   ============ */\n\n    .main article {\n        float: left;\n        width: 57%;\n    }\n\n    .main aside {\n        float: right;\n        width: 28%;\n    }\n}\n\n@media only screen and (min-width: 1140px) {\n\n/* ===============\n    Maximal Width\n   =============== */\n\n    .wrapper {\n        width: 1026px; /* 1140px - 10% for margins */\n        margin: 0 auto;\n    }\n}\n\n/* ==========================================================================\n   Helper classes\n   ========================================================================== */\n\n.ir {\n    background-color: transparent;\n    border: 0;\n    overflow: hidden;\n    *text-indent: -9999px;\n}\n\n.ir:before {\n    content: \"\";\n    display: block;\n    width: 0;\n    height: 100%;\n}\n\n.hidden {\n    display: none !important;\n    visibility: hidden;\n}\n\n.visuallyhidden {\n    border: 0;\n    clip: rect(0 0 0 0);\n    height: 1px;\n    margin: -1px;\n    overflow: hidden;\n    padding: 0;\n    position: absolute;\n    width: 1px;\n}\n\n.visuallyhidden.focusable:active,\n.visuallyhidden.focusable:focus {\n    clip: auto;\n    height: auto;\n    margin: 0;\n    overflow: visible;\n    position: static;\n    width: auto;\n}\n\n.invisible {\n    visibility: hidden;\n}\n\n.clearfix:before,\n.clearfix:after {\n    content: \" \";\n    display: table;\n}\n\n.clearfix:after {\n    clear: both;\n}\n\n.clearfix {\n    *zoom: 1;\n}\n\n/* ==========================================================================\n   Print styles\n   ========================================================================== */\n\n@media print {\n    * {\n        background: transparent !important;\n        color: #000 !important; /* Black prints faster: h5bp.com/s */\n        box-shadow:none !important;\n        text-shadow: none !important;\n    }\n\n    a,\n    a:visited {\n        text-decoration: underline;\n    }\n\n    a[href]:after {\n        content: \" (\" attr(href) \")\";\n    }\n\n    abbr[title]:after {\n        content: \" (\" attr(title) \")\";\n    }\n\n    /*\n     * Don't show links for images, or javascript/internal links\n     */\n\n    .ir a:after,\n    a[href^=\"javascript:\"]:after,\n    a[href^=\"#\"]:after {\n        content: \"\";\n    }\n\n    pre,\n    blockquote {\n        border: 1px solid #999;\n        page-break-inside: avoid;\n    }\n\n    thead {\n        display: table-header-group; /* h5bp.com/t */\n    }\n\n    tr,\n    img {\n        page-break-inside: avoid;\n    }\n\n    img {\n        max-width: 100% !important;\n    }\n\n    @page {\n        margin: 0.5cm;\n    }\n\n    p,\n    h2,\n    h3 {\n        orphans: 3;\n        widows: 3;\n    }\n\n    h2,\n    h3 {\n        page-break-after: avoid;\n    }\n}"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/boilerplate/css/normalize.css",
    "content": "/*! normalize.css v1.0.1 | MIT License | git.io/normalize */\n\n/* ==========================================================================\n   HTML5 display definitions\n   ========================================================================== */\n\n/*\n * Corrects `block` display not defined in IE 6/7/8/9 and Firefox 3.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection,\nsummary {\n    display: block;\n}\n\n/*\n * Corrects `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.\n */\n\naudio,\ncanvas,\nvideo {\n    display: inline-block;\n    *display: inline;\n    *zoom: 1;\n}\n\n/*\n * Prevents modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\n\naudio:not([controls]) {\n    display: none;\n    height: 0;\n}\n\n/*\n * Addresses styling for `hidden` attribute not present in IE 7/8/9, Firefox 3,\n * and Safari 4.\n * Known issue: no IE 6 support.\n */\n\n[hidden] {\n    display: none;\n}\n\n/* ==========================================================================\n   Base\n   ========================================================================== */\n\n/*\n * 1. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using\n *    `em` units.\n * 2. Prevents iOS text size adjust after orientation change, without disabling\n *    user zoom.\n */\n\nhtml {\n    font-size: 100%; /* 1 */\n    -webkit-text-size-adjust: 100%; /* 2 */\n    -ms-text-size-adjust: 100%; /* 2 */\n}\n\n/*\n * Addresses `font-family` inconsistency between `textarea` and other form\n * elements.\n */\n\nhtml,\nbutton,\ninput,\nselect,\ntextarea {\n    font-family: sans-serif;\n}\n\n/*\n * Addresses margins handled incorrectly in IE 6/7.\n */\n\nbody {\n    margin: 0;\n}\n\n/* ==========================================================================\n   Links\n   ========================================================================== */\n\n/*\n * Addresses `outline` inconsistency between Chrome and other browsers.\n */\n\na:focus {\n    outline: thin dotted;\n}\n\n/*\n * Improves readability when focused and also mouse hovered in all browsers.\n */\n\na:active,\na:hover {\n    outline: 0;\n}\n\n/* ==========================================================================\n   Typography\n   ========================================================================== */\n\n/*\n * Addresses font sizes and margins set differently in IE 6/7.\n * Addresses font sizes within `section` and `article` in Firefox 4+, Safari 5,\n * and Chrome.\n */\n\nh1 {\n    font-size: 2em;\n    margin: 0.67em 0;\n}\n\nh2 {\n    font-size: 1.5em;\n    margin: 0.83em 0;\n}\n\nh3 {\n    font-size: 1.17em;\n    margin: 1em 0;\n}\n\nh4 {\n    font-size: 1em;\n    margin: 1.33em 0;\n}\n\nh5 {\n    font-size: 0.83em;\n    margin: 1.67em 0;\n}\n\nh6 {\n    font-size: 0.75em;\n    margin: 2.33em 0;\n}\n\n/*\n * Addresses styling not present in IE 7/8/9, Safari 5, and Chrome.\n */\n\nabbr[title] {\n    border-bottom: 1px dotted;\n}\n\n/*\n * Addresses style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.\n */\n\nb,\nstrong {\n    font-weight: bold;\n}\n\nblockquote {\n    margin: 1em 40px;\n}\n\n/*\n * Addresses styling not present in Safari 5 and Chrome.\n */\n\ndfn {\n    font-style: italic;\n}\n\n/*\n * Addresses styling not present in IE 6/7/8/9.\n */\n\nmark {\n    background: #ff0;\n    color: #000;\n}\n\n/*\n * Addresses margins set differently in IE 6/7.\n */\n\np,\npre {\n    margin: 1em 0;\n}\n\n/*\n * Corrects font family set oddly in IE 6, Safari 4/5, and Chrome.\n */\n\ncode,\nkbd,\npre,\nsamp {\n    font-family: monospace, serif;\n    _font-family: 'courier new', monospace;\n    font-size: 1em;\n}\n\n/*\n * Improves readability of pre-formatted text in all browsers.\n */\n\npre {\n    white-space: pre;\n    white-space: pre-wrap;\n    word-wrap: break-word;\n}\n\n/*\n * Addresses CSS quotes not supported in IE 6/7.\n */\n\nq {\n    quotes: none;\n}\n\n/*\n * Addresses `quotes` property not supported in Safari 4.\n */\n\nq:before,\nq:after {\n    content: '';\n    content: none;\n}\n\n/*\n * Addresses inconsistent and variable font size in all browsers.\n */\n\nsmall {\n    font-size: 80%;\n}\n\n/*\n * Prevents `sub` and `sup` affecting `line-height` in all browsers.\n */\n\nsub,\nsup {\n    font-size: 75%;\n    line-height: 0;\n    position: relative;\n    vertical-align: baseline;\n}\n\nsup {\n    top: -0.5em;\n}\n\nsub {\n    bottom: -0.25em;\n}\n\n/* ==========================================================================\n   Lists\n   ========================================================================== */\n\n/*\n * Addresses margins set differently in IE 6/7.\n */\n\ndl,\nmenu,\nol,\nul {\n    margin: 1em 0;\n}\n\ndd {\n    margin: 0 0 0 40px;\n}\n\n/*\n * Addresses paddings set differently in IE 6/7.\n */\n\nmenu,\nol,\nul {\n    padding: 0 0 0 40px;\n}\n\n/*\n * Corrects list images handled incorrectly in IE 7.\n */\n\nnav ul,\nnav ol {\n    list-style: none;\n    list-style-image: none;\n}\n\n/* ==========================================================================\n   Embedded content\n   ========================================================================== */\n\n/*\n * 1. Removes border when inside `a` element in IE 6/7/8/9 and Firefox 3.\n * 2. Improves image quality when scaled in IE 7.\n */\n\nimg {\n    border: 0; /* 1 */\n    -ms-interpolation-mode: bicubic; /* 2 */\n}\n\n/*\n * Corrects overflow displayed oddly in IE 9.\n */\n\nsvg:not(:root) {\n    overflow: hidden;\n}\n\n/* ==========================================================================\n   Figures\n   ========================================================================== */\n\n/*\n * Addresses margin not present in IE 6/7/8/9, Safari 5, and Opera 11.\n */\n\nfigure {\n    margin: 0;\n}\n\n/* ==========================================================================\n   Forms\n   ========================================================================== */\n\n/*\n * Corrects margin displayed oddly in IE 6/7.\n */\n\nform {\n    margin: 0;\n}\n\n/*\n * Define consistent border, margin, and padding.\n */\n\nfieldset {\n    border: 1px solid #c0c0c0;\n    margin: 0 2px;\n    padding: 0.35em 0.625em 0.75em;\n}\n\n/*\n * 1. Corrects color not being inherited in IE 6/7/8/9.\n * 2. Corrects text not wrapping in Firefox 3.\n * 3. Corrects alignment displayed oddly in IE 6/7.\n */\n\nlegend {\n    border: 0; /* 1 */\n    padding: 0;\n    white-space: normal; /* 2 */\n    *margin-left: -7px; /* 3 */\n}\n\n/*\n * 1. Corrects font size not being inherited in all browsers.\n * 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5,\n *    and Chrome.\n * 3. Improves appearance and consistency in all browsers.\n */\n\nbutton,\ninput,\nselect,\ntextarea {\n    font-size: 100%; /* 1 */\n    margin: 0; /* 2 */\n    vertical-align: baseline; /* 3 */\n    *vertical-align: middle; /* 3 */\n}\n\n/*\n * Addresses Firefox 3+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\n\nbutton,\ninput {\n    line-height: normal;\n}\n\n/*\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n *    and `video` controls.\n * 2. Corrects inability to style clickable `input` types in iOS.\n * 3. Improves usability and consistency of cursor style between image-type\n *    `input` and others.\n * 4. Removes inner spacing in IE 7 without affecting normal text inputs.\n *    Known issue: inner spacing remains in IE 6.\n */\n\nbutton,\nhtml input[type=\"button\"], /* 1 */\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n    -webkit-appearance: button; /* 2 */\n    cursor: pointer; /* 3 */\n    *overflow: visible;  /* 4 */\n}\n\n/*\n * Re-set default cursor for disabled elements.\n */\n\nbutton[disabled],\ninput[disabled] {\n    cursor: default;\n}\n\n/*\n * 1. Addresses box sizing set to content-box in IE 8/9.\n * 2. Removes excess padding in IE 8/9.\n * 3. Removes excess padding in IE 7.\n *    Known issue: excess padding remains in IE 6.\n */\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n    box-sizing: border-box; /* 1 */\n    padding: 0; /* 2 */\n    *height: 13px; /* 3 */\n    *width: 13px; /* 3 */\n}\n\n/*\n * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.\n * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome\n *    (include `-moz` to future-proof).\n */\n\ninput[type=\"search\"] {\n    -webkit-appearance: textfield; /* 1 */\n    -moz-box-sizing: content-box;\n    -webkit-box-sizing: content-box; /* 2 */\n    box-sizing: content-box;\n}\n\n/*\n * Removes inner padding and search cancel button in Safari 5 and Chrome\n * on OS X.\n */\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n    -webkit-appearance: none;\n}\n\n/*\n * Removes inner padding and border in Firefox 3+.\n */\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n    border: 0;\n    padding: 0;\n}\n\n/*\n * 1. Removes default vertical scrollbar in IE 6/7/8/9.\n * 2. Improves readability and alignment in all browsers.\n */\n\ntextarea {\n    overflow: auto; /* 1 */\n    vertical-align: top; /* 2 */\n}\n\n/* ==========================================================================\n   Tables\n   ========================================================================== */\n\n/*\n * Remove most spacing between table cells.\n */\n\ntable {\n    border-collapse: collapse;\n    border-spacing: 0;\n}\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/boilerplate/index.html",
    "content": "<!DOCTYPE html>\n<html class=\"no-js\">\n    <head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n        <title></title>\n        <meta name=\"description\" content=\"\">\n        <meta name=\"viewport\" content=\"width=device-width\">\n\n        <link rel=\"stylesheet\" href=\"css/normalize.min.css\">\n        <link rel=\"stylesheet\" href=\"css/main.css\">\n\n        <script src=\"js/vendor/modernizr-2.6.1.min.js\"></script>\n    </head>\n    <body>\n\n        <div class=\"header-container\">\n            <header class=\"wrapper clearfix\">\n                <h1 class=\"title\">h1.title</h1>\n                <nav>\n                    <ul>\n                        <li><a href=\"#\">nav ul li a</a></li>\n                        <li><a href=\"#\">nav ul li a</a></li>\n                        <li><a href=\"#\">nav ul li a</a></li>\n                    </ul>\n                </nav>\n            </header>\n        </div>\n\n        <div class=\"main-container\">\n            <div class=\"main wrapper clearfix\">\n\n                <article>\n                    <header>\n                        <h1>article header h1</h1>\n                        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec.</p>\n                    </header>\n                    <section>\n                        <h2>article section h2</h2>\n                        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor. Etiam ullamcorper lorem dapibus velit suscipit ultrices. Proin in est sed erat facilisis pharetra.</p>\n                    </section>\n                    <section>\n                        <h2>article section h2</h2>\n                        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor. Etiam ullamcorper lorem dapibus velit suscipit ultrices. Proin in est sed erat facilisis pharetra.</p>\n                    </section>\n                    <footer>\n                        <h3>article footer h3</h3>\n                        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor.</p>\n                    </footer>\n                </article>\n\n                <aside>\n                    <h3>aside</h3>\n                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor. Etiam ullamcorper lorem dapibus velit suscipit ultrices.</p>\n                </aside>\n\n            </div> <!-- #main -->\n        </div> <!-- #main-container -->\n\n        <div class=\"footer-container\">\n            <footer class=\"wrapper\">\n                <h3>footer</h3>\n            </footer>\n        </div>\n\n        <script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js\"></script>\r\n        <script>window.jQuery || document.write('<script src=\"js/vendor/jquery-1.8.1.min.js\"><\\/script>')</script>\r\n\r\n        <script src=\"js/main.js\"></script>\n\n        <script>\n            var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];\n            (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];\n            g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';\n            s.parentNode.insertBefore(g,s)}(document,'script'));\n        </script>\n    </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/boilerplate/js/main.js",
    "content": "\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/doc.css",
    "content": "i, em {\n    font-family: serif;\n}\n\n#contents ul {\n    margin-bottom: 0;\n    margin-top: 0;\n}\n\n#contents > ul {\n    padding-left: 0;\n}\n\n#contents li {\n    list-style: none;\n}\n\n#contents {\n    border-bottom: 1px solid #999;\n    padding-left: 1em;\n}\n\n.header-container header {\n    width: 98%;\n}\n\ncode {\n    color: #288;\n}\n\naside code {\n    color: #9ff;\n}\n\nsection:target h1, section:target h2, section:target h3, section:target h4,\nsection:target h5, section:target h6, h3:target, h4:target {\n    border-bottom: 3px solid #f90;\n}\n\nfooter a:link, footer a:visited,\naside a:link, aside a:visited {\n    text-decoration: none;\n    color: #fd1;\n}\n\nsection header h1, section header h2, section header h3, section header h4,\nsection header h5, section header h6 {\n    margin-left: -1em;\n    margin-top: 1.75em;\n    border-bottom: 1px solid #000;\n}\n\npre {\n    font-size: 90%;\n    line-height: 1.3;\n    border: 1px solid #999;\n    border-radius: 4px;\n}\n\n@media only screen and (min-width: 768px) {\n\n    .main aside {\n        position: absolute;\n        right: 1em;\n    }\n\n}\n\n.header-container header {\n    margin-left: 1em;\n}\n\nh1.title a:link, h1.title a:visited {\n    text-decoration: none;\n    color: #fff;\n}\n\nh1.title a:hover {\n    text-decoration: underline;\n}\n\n\ndd p {\n    margin-top: 0;\n}\n\ndd p:last-child {\n    margin-bottom: 0;\n}"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/example.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\">\n\n\t<title>Example Feed</title>\n\t<subtitle>A subtitle.</subtitle>\n\t<link href=\"http://example.org/feed/\" rel=\"self\" />\n\t<link href=\"http://example.org/\" />\n\t<id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id>\n\t<updated>2003-12-13T18:30:02Z</updated>\n\t<author>\n\t\t<name>John Doe</name>\n\t\t<email>johndoe@example.com</email>\n\t</author>\n\n\t<entry>\n\t\t<title>Atom-Powered Robots Run Amok</title>\n\t\t<link href=\"http://example.org/2003/12/13/atom03\" />\n\t\t<link rel=\"alternate\" type=\"text/html\" href=\"http://example.org/2003/12/13/atom03.html\"/>\n\t\t<link rel=\"edit\" href=\"http://example.org/2003/12/13/atom03/edit\"/>\n\t\t<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>\n\t\t<updated>2003-12-13T18:30:02Z</updated>\n\t\t<summary>Some text.</summary>\n\t</entry>\n\n</feed>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/footer.html",
    "content": "</div>\n\n<h3>Download</h3>\n<p>\n You can download this project in either\n <a href=\"http://github.com/ianb/doctestjs/zipball/master\">zip</a> or\n <a href=\"http://github.com/ianb/doctestjs/tarball/master\">tar</a> formats.\n</p>\n\n<p>You can also clone the project with <a href=\"http://git-scm.com\">Git</a>\n by running:\n <pre>$ git clone git://github.com/ianb/doctestjs</pre>\n</p>\n\n<div class=\"footer\">\n get the source code on GitHub:\n <a href=\"http://github.com/ianb/doctestjs\">ianb/doctestjs</a>\n</div>\n\n</div>\n\n<script type=\"text/javascript\">\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n</script>\n<script type=\"text/javascript\">\ntry {\nvar pageTracker = _gat._getTracker(\"UA-6731441-12\");\npageTracker._trackPageview();\n} catch(err) {}</script>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/header.html",
    "content": "<!DOCTYPE html>\n<html class=\"no-js\">\n  <head>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" href=\"doctest.css\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <title>__TITLE__</title>\n    <meta name=\"description\" content=\"__DESCRIPTION__\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/normalize.min.css\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/main.css\">\n    <link rel=\"stylesheet\" href=\".resources/doc.css\">\n    <script src=\".resources/boilerplate/js/vendor/modernizr-2.6.1.min.js\"></script>\n    <script src=\"doctest.js\"></script>\n  </head>\n  <body class=\"autodoctest\">\n\n    <a href=\"http://github.com/ianb/doctestjs\"><img\nstyle=\"position: absolute; top: 0; right: 0; border: 0;\"\nsrc=\"http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png\"\nalt=\"Fork me on GitHub\"></a>\n\n    <div class=\"header-container\">\n      <header class=\"wrapper clearfix\">\n        <h1 class=\"title\"><a href=\"/\">Doctest.js</a>: <!-- TITLE --><!-- /TITLE --></h1>\n\n        <!--\n          <nav>\n            <ul>\n              <li><a href=\"#\">nav ul li a</a></li>\n              <li><a href=\"#\">nav ul li a</a></li>\n              <li><a href=\"#\">nav ul li a</a></li>\n            </ul>\n          </nav>\n          -->\n\n      </header>\n    </div>\n\n    <div class=\"main-container\">\n      <div class=\"main wrapper clearfix\">\n\n\n     <!-- BODY -->\n\n      __BODY__\n\n     <!-- /BODY -->\n\n      </div> <!-- #main -->\n\n    </div> <!-- #main-container -->\n\n    <div class=\"footer-container\">\n      <footer class=\"wrapper\">\n        <h3>doctest.js is by <a href=\"http://ianbicking.org\">Ian Bicking</a>.\n          It's on <a href=\"https://github.com/ianb/doctestjs\">github</a>!</h3>\n      </footer>\n    </div>\n\n<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js\"></script>\n<script>\nwindow.jQuery || document.write('<script src=\".resources/boilerplate/js/vendor/jquery-1.8.1.min.js\"><\\/script>')\n</script>\n\n<script src=\".resources/boilerplate/js/main.js\"></script>\n\n<script type=\"text/javascript\">\n\n  var _gaq = _gaq || [];\n  _gaq.push(['_setAccount', 'UA-34921728-1']);\n  _gaq.push(['_trackPageview']);\n\n  (function() {\n    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n  })();\n\n</script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/include-scripts.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nbase=\"$(python -c 'import sys, os; print os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[1])))' \"$BASH_SOURCE\")\"\n\nif [ ! -f $base/doctest.js ] ; then\n    echo \"Could not find $base/doctest.js\"\n    exit 1\nfi\n\nif [ ! -d $base/.resources/jshint ] ; then\n    echo \"Could not find $base/.resources/jshint\"\n    echo \"Try:\"\n    echo \"  git clone https://github.com/jshint/jshint.git .resources/jshint\"\n    exit 2\nfi\n\nif [ ! -d $base/.resources/esprima ] ; then\n    echo \"Could not find $base/.resources/esprima\"\n    echo \"Try:\"\n    echo \"  git clone https://github.com/ariya/esprima.git .resources/esprima\"\n    exit 3\nfi\n\necho \"Substituting $base/doctest.js\"\n\npython -c '\nimport os, sys, re, subprocess\nos.chdir(sys.argv[1])\nwith open(\"doctest.js\", \"rb\") as fp:\n    content = fp.read()\nnames = {}\nfor arg in sys.argv[2:]:\n    name, rest = arg.split(\"=\", 1)\n    names[name] = rest\nregex = re.compile(r\"\\/\\*\\s+INSERT\\s+(.*?)\\s+\\*\\/\\s*\\n(.*?)\\/*\\s+END\\s+INSERT\\s+\\*\\/\", re.S)\ndef repl(match):\n    print \"Replacing %s\" % match.group(1)\n    filename = names.get(match.group(1))\n    # I do not understand why --ascii needs an option\n    output = subprocess.check_output(\n      [\"uglifyjs\", \"--no-copyright\", \"--max-line-len\", \"200\", \"-b\", \"max-line-len=200,ascii-only=true,beautify=false\", filename])\n    return \"/* INSERT %s */\\n%s\\n/* END INSERT */\" % (\n        match.group(1), output)\nnew_content = regex.sub(repl, content)\nwith open(\"doctest.js\", \"wb\") as fp:\n    fp.write(new_content)\nprint \"wrote doctest.js\"\n' \"$base\" esprima.js=$base/.resources/esprima/esprima.js jshint.js=$base/.resources/jshint/jshint.js\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/retemplate.py",
    "content": "#!/usr/bin/env python\nimport re\n\nsection_re = re.compile(r'''\n(?P<front1><!--\\s*)\n  (?P<name>[A-Z_]+)\n(?P<front2>\\s*-->)\n  (?P<value>[^\\000]*)\n(?P<back1><!--\\s*)\n  /(?P=name)\n(?P<back2>\\s*-->)\n''', re.VERBOSE | re.MULTILINE)\n\nvalue_sub_re = re.compile(r'(?P<front><[^>]*\")(?:__)(?P<name>[A-Z_]+)(?:__)(?P<back>\"[^>]*>)')\n\ntitle_sub_re = re.compile(r'<title>(.*?)</title>', re.I)\n\n\ndef get_variables(content, value_matches):\n    vars = {}\n    for match in section_re.finditer(content):\n        vars[match.group('name')] = match.group('value')\n    for name, value_match_start, value_match_end in value_matches:\n        regex = re.escape(value_match_start) + '([^\"]*)' + re.escape(value_match_end)\n        regex = re.compile(regex)\n        for match in regex.finditer(content):\n            vars[name] = match.group(1)\n    match = title_sub_re.search(content)\n    if match:\n        vars['PAGE_TITLE'] = match.group(1)\n    else:\n        print 'No <title> found'\n    return vars\n\n\ndef get_value_matches(template):\n    matches = []\n    for match in value_sub_re.finditer(template):\n        matches.append((\n                match.group('name'),\n                match.group('front'),\n                match.group('back')))\n    return matches\n\n\ndef sub_template(template, content):\n    matches = get_value_matches(template)\n    content_vars = get_variables(content, matches)\n\n    def sub_section(match):\n        if match.group('name') not in content_vars:\n            # Failure, needs to be fixed\n            raise Exception('Must have section <!-- %s -->' % match.group('name'))\n        return (\n            match.group('front1') + match.group('name') + match.group('front2')\n            + content_vars.get(match.group('name'), '')\n            + match.group('back1') + '/' + match.group('name') + match.group('back2')\n            )\n\n    new_content = section_re.sub(sub_section, template)\n\n    def sub_variable(match):\n        if match.group('name') not in content_vars:\n            print 'Missing tag: __%s__' % match.group('name')\n            return '<!-- ' + match.group(0) + ' -->'\n        return (\n            match.group('front')\n            + content_vars[match.group('name')]\n            + match.group('back'))\n\n    new_content = value_sub_re.sub(sub_variable, new_content)\n\n    def sub_title(match):\n        if 'PAGE_TITLE' in content_vars:\n            return '<title>' + content_vars['PAGE_TITLE'] + '</title>'\n        else:\n            return match.group(0)\n\n    new_content = title_sub_re.sub(sub_title, new_content)\n\n    return new_content\n\n\ndef rewrite_page(page_name, template_name):\n    with open(template_name) as fp:\n        template = fp.read()\n    with open(page_name) as fp:\n        content = fp.read()\n    try:\n        new_content = sub_template(template, content)\n    except:\n        print 'Error in page:', page_name\n        raise\n    with open(page_name, 'w') as fp:\n        fp.write(new_content)\n\nif __name__ == '__main__':\n    import sys\n    if len(sys.argv) < 3:\n        print 'Usage: retemplate.py TEMPLATE_FILE CONTENT_FILE [...CONTENT_FILE2...]'\n        sys.exit(2)\n    template_name = sys.argv[1]\n    for filename in sys.argv[2:]:\n        rewrite_page(filename, template_name)\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/template.html",
    "content": "<!DOCTYPE html>\n<html class=\"no-js\">\n  <head>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" href=\"doctest.css\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <title></title>\n    <meta name=\"description\" content=\"__DESCRIPTION__\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/normalize.min.css\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/main.css\">\n    <link rel=\"stylesheet\" href=\".resources/doc.css\">\n    <script src=\".resources/boilerplate/js/vendor/modernizr-2.6.1.min.js\"></script>\n    <script src=\"doctest.js\"></script>\n    <!-- EXTRA_HEAD -->\n    <!-- /EXTRA_HEAD -->\n  </head>\n  <body class=\"autodoctest\">\n\n    <div class=\"header-container\">\n      <header class=\"wrapper clearfix\">\n        <h1 class=\"title\"><a href=\"/\">Doctest.js</a>: <!-- TITLE --><!-- /TITLE --></h1>\n\n        <nav>\n          <ul>\n            <li><a href=\"https://github.com/ianb/doctestjs\">Github</a></li>\n            <li><a href=\"/reference.html\">Reference</a></li>\n            <li><a href=\"/tutorial.html\">Tutorial</a></li>\n          </ul>\n        </nav>\n\n      </header>\n    </div>\n\n    <div class=\"main-container\">\n      <div class=\"main wrapper clearfix\">\n\n\n     <!-- BODY -->\n\n      __BODY__\n\n     <!-- /BODY -->\n\n      </div> <!-- #main -->\n\n    </div> <!-- #main-container -->\n\n    <div class=\"footer-container\">\n      <footer class=\"wrapper\">\n        <h3 class=\"no-toc\">doctest.js is by <a href=\"http://ianbicking.org\">Ian Bicking</a>.\n          It's on <a href=\"https://github.com/ianb/doctestjs\">github</a>!</h3>\n      </footer>\n    </div>\n\n<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js\"></script>\n<script>\nwindow.jQuery || document.write('<script src=\".resources/boilerplate/js/vendor/jquery-1.8.1.min.js\"><\\/script>')\n</script>\n\n<script src=\".resources/boilerplate/js/main.js\"></script>\n\n<script type=\"text/javascript\">\n\n  var _gaq = _gaq || [];\n  _gaq.push(['_setAccount', 'UA-34921728-1']);\n  _gaq.push(['_trackPageview']);\n\n  (function() {\n    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n  })();\n\n</script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/toc.js",
    "content": "function contentsOnLoad() {\n    if (contentsOnLoad.hasRun) {\n      return;\n    }\n    contentsOnLoad.hasRun = true;\n    var dest = document.getElementById('contents');\n    var toc = [document.createElement('ul')];\n    var generatedIds = [];\n    dest.appendChild(toc[0]);\n    var els = document.querySelectorAll('h3, h4, h5, h6');\n    for (var i=0; i<els.length; i++) {\n        var el = els[i];\n        if (el.className.indexOf('no-toc') != -1) {\n          continue;\n        }\n        var elDepth = ['H3', 'H4', 'H5', 'H6'].indexOf(el.tagName);\n        while (elDepth < toc.length-1) {\n          toc.splice(toc.length-1, 1);\n        }\n        while (elDepth >= toc.length) {\n          var ul = document.createElement('ul');\n          var container = document.createElement('li');\n          container.appendChild(ul);\n          toc[toc.length-1].appendChild(container);\n          toc.push(ul);\n        }\n        var name = el.getAttribute('id');\n        if (! name) {\n          name = 'header-'+(i+1);\n          generatedIds.push(name);\n          el.setAttribute('id', name);\n        }\n        var li = document.createElement('li');\n        var anchor = document.createElement('a');\n        if (el.getAttribute('href')) {\n          anchor.setAttribute('href', el.getAttribute('href'));\n          el.style.display = 'none';\n        } else {\n          anchor.setAttribute('href', '#'+name);\n        }\n        li.appendChild(anchor);\n        anchor.innerHTML = el.innerHTML;\n        toc[toc.length-1].appendChild(li);\n    }\n    // Re-scroll:\n    if (location.hash && generatedIds.indexOf(location.hash.substr(1)) != -1) {\n      location.hash = location.hash;\n    }\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", contentsOnLoad, false);\nwindow.addEventListener(\"load\", contentsOnLoad, false);\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.resources/try.js",
    "content": "window.addEventListener('load', function () {\n  var innerHTML = $('#display').html();\n  if (localStorage.editText) {\n    $('#editor').val(localStorage.editText);\n  }\n  $('#editor').change(function () {\n    localStorage.editText = $('#editor').val();\n  });\n  $('#testit').click(function () {\n    $('#display').html(innerHTML);\n    $('#editit').click(function () {\n      $('#edit').show();\n      $('#display').hide();\n      $('#editor').focus();\n      $('#doctest-output').hide();\n    });\n    $('#test-location').addClass('test').text($('#editor').val());\n    console.log($('#test-location').text());\n    var runner = new doctest.Runner();\n    var parser = new doctest.HTMLParser(runner, $('#display')[0], 'pre#test-location');\n    runner.init();\n    parser.parse();\n    runner.run();\n  });\n}, false);\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/.syncignore",
    "content": "\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/README.md",
    "content": "## doctest.js\n\nFor a more complete description please [read the main\npage](http://doctestjs.org).\n\n`doctest.js` is a test runner for Javascript, organized around *examples* and *expected result*.  Tests look like this:\n\n```javascript\n// Simple stuff:\nprint(3 * 4);\n// => 12\n\n// Or complicated stuff:\nvar complete = false;\nvar savedResult = null;\n$.ajax({\n  url: \"/test\",\n  dataType: \"json\",\n  success: function (result) {\n    complete = true;\n    savedResult = result;\n  }\n});\nwait(function () {return complete;});\nprint(savedResult);\n// => {value1: \"something\", value2: true}\n```\n\nAnd a bunch more features: check out the [tutorial](http://doctestjs.org/tutorial.html) to get started, or read the [reference](http://doctestjs.org/reference.html) for more detail.\n\n## License\n\nDoctest.js is released under an MIT-style license.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/bin/doctest",
    "content": "#!/usr/bin/env node\n\nvar path = require('path');\nvar fs = require('fs');\nvar root = path.join(path.dirname(fs.realpathSync(__filename)), '..');\n\n// FIXME: Not sure this is the best way to go about this, or if we should\n// just require(\"doctest\")?\nvar doctest = require(root + '/doctest');\n\nfunction main(filename) {\n  var runner = new doctest.Runner({Reporter: doctest.ConsoleReporter});\n  runner.globs = runner.evalInit();\n  var parser = new doctest.TextParser.fromFile(runner, process.argv[2]);\n  parser.parse();\n  runner.run();\n\n  var reporter = runner.reporter;\n  return reporter;\n}\n\nfunction showReport(reporter) {\n  console.log('Successes:', reporter.successes);\n  console.log('Failures:', reporter.failures);\n  if ((! reporter.successes) || reporter.failures) {\n    // Set exit code to number of failures (if any). It gives a nice failures\n    // summary when running under make. E.g.: `make: *** [doctest] Error 2`\n    process.exit(reporter.failures || 1);\n  }\n}\n\nvar filename = process.argv[2];\nif (! filename) {\n  console.log(\"Error: you did not give a filename\");\n  console.log(\"Usage:\", process.argv[1], \"FILENAME\");\n  process.exit(500);\n}\nshowReport(main(filename));\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/doctest.css",
    "content": "/* Basic styling: */\n\nbody {\n    font-family: sans-serif;\n}\n\npre {\n    padding: 0.3em;\n}\n\n/* Test block formatting: */\n\npre.doctest, pre.commenttest, pre.test {\n    border: 1px solid #999;\n    border-radius: 4px;\n}\n\npre.doctest.doctest-some-failure, pre.commenttest.doctest-some-failure, pre.test.doctest-some-failure {\n    border: 1px solid #f00;\n}\n\n/* FIXME: it would be nice if this was more obviously styled to show that there\n   was more content */\npre.doctest.expand-on-failure, pre.commenttest.expand-on-failure, pre.test.expand-on-failure {\n    max-height: 3em;\n    overflow-y: auto;\n}\n\npre.doctest.expand-on-failure.doctest-some-failure, pre.commenttest.expand-on-failure.doctest-some-failure, pre.test.expand-on-failure.doctest-some-failure {\n    max-height: none;\n}\n\n/* Individual example formatting: */\n\n.doctest-example:target {\n    border-left: 4px solid #f00;\n    padding-left: 4px;\n}\n\n.doctest-example {\n}\n\n.doctest-example.doctest-success {\n    color: #060;\n}\n\n.doctest-example.doctest-failure {\n    color: #900;\n}\n\n.doctest-example .doctest-actual-output {\n    color: #066;\n    /*padding-left: 1em;*/\n}\n\n.doctest-example.doctest-failure .doctest-output {\n    padding-left: 1em;\n}\n\n.doctest-example .doctest-output {\n    font-weight: bold;\n}\n\n.doctest-example .doctest-description {\n    color: #000;\n    font-weight: bold;\n}\n\n.doctest-example .doctest-console {\n    color: #009;\n    padding-left: 1em;\n}\n\n/* Reporter formatting: */\n\n#doctest-success-count.doctest-nonzero {\n    color: #0f0;\n}\n\n#doctest-failure-count.doctest-nonzero {\n    color: #f00;\n}\n\n#doctest-aborted {\n    background-color: #900;\n    color: #fff;\n}\n\n.doctest-report-table th {\n    font-weight: normal;\n    text-align: left;\n}\n\n.doctest-report-table td {\n    padding: 0 1em;\n}\n\na.doctest-failure-link {\n    color: #00f;\n    text-decoration: none;\n    padding: 0 1em 0 0;\n}\n\na.doctest-failure-link:visited {\n    color: #00f;\n}\n\na.doctest-failure-link:hover {\n    text-decoration: underline;\n}\n\n/* Comparison table */\n\n.doctest-comparison-table {\n    border: 1px solid #000;\n    /* FIXME: not sure why this doesn't keep the table limited to 100% */\n    width: 100%;\n}\n\n.doctest-comparison-table td {\n    overflow: auto;\n}\n\n.doctest-comparison-header th {\n    background-color: #000;\n    color: #fff;\n}\n\n.doctest-comparison-error td {\n    background-color: #fdd;\n}\n\ntd.doctest-comparison-got {\n    padding-right: 1em;\n    color: #060;\n}\n\ntd.doctest-comparison-expected {\n    color: #900;\n}\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/doctest.js",
    "content": "(function (exports) {\n\n// Some Node.js globals:\n/*global global, require, exports */\n// Some browser globals:\n/*global console */\n// Some doctest.js globals:\n/*global writeln, wait, doctest:true, doctestReporterHook, esprima:true, JSHINT:true */\n\nvar globalObject;\nif (typeof window == 'undefined') {\n  if (typeof global == 'undefined') {\n    globalObject = (function () {return this;})();\n  } else {\n    globalObject = global;\n  }\n} else {\n  globalObject = window;\n}\n\nvar doc;\nif (typeof document != 'undefined') {\n  doc = document;\n} else {\n  doc = null;\n}\n\nexports.setDocument = function (newDocument) {\n  doc = newDocument;\n};\n\nvar Example = exports.Example = function (runner, expr, expected, attrs) {\n  this.runner = runner;\n  this.expr = expr;\n  if (typeof expected != \"string\") {\n    throw \"Bad value for expected: \" + expected;\n  }\n  this.expected = expected;\n  if (attrs) {\n    for (var i in attrs) {\n      if (attrs.hasOwnProperty(i)) {\n        this[i] = attrs[i];\n      }\n    }\n  }\n};\n\nExample.prototype = {\n  run: function () {\n    this.output = [];\n    this.consoleOutput = [];\n    var globs = this.runner.evalInit();\n    try {\n      this.result = this.runner.evaller(this.expr, globs, this.filename);\n    } catch (e) {\n      if (e && e['doctest.abort']) {\n        return;\n      }\n      this.write('Error: ' + e + '\\n');\n      // FIXME: doesn't format nicely:\n      if (e && e.stack) {\n        console.log('Exception Stack:');\n        console.log(e.stack);\n      }\n    }\n  },\n  check: function () {\n    var output = this.output.join('');\n    // FIXME: consider using this.result\n    this.runner.matcher.match(this, output, this.expected);\n  },\n  write: function (text) {\n    this.output.push(text);\n  },\n  writeConsole: function (message) {\n    this.consoleOutput.push(message);\n  },\n  clearConsole: function () {\n    this.consoleOutput = [];\n  },\n  timeout: function (passed) {\n    this.runner.reporter.logFailure(this, \"Error: wait timed out after \" + passed + \" milliseconds\");\n  },\n  textSummary: function () {\n    return strip(strip(this.expr).substr(0, 20)) + '...';\n  }\n};\n\nvar Matcher = exports.Matcher = function (runner) {\n  this.runner = runner;\n};\n\nMatcher.prototype = {\n  match: function (example, got, expected) {\n    var cleanGot = this.clean(got);\n    var cleanExpected = this.clean(expected);\n    var regexp = this.makeRegex(cleanExpected);\n    if (cleanGot.search(regexp) != -1) {\n      this.runner.reporter.logSuccess(example, got);\n      return;\n    }\n    var comparisonTable = this.makeComparisonTable(cleanGot, cleanExpected);\n    this.runner.reporter.logFailure(example, got, comparisonTable);\n  },\n\n  makeComparisonTable: function (cleanGot, cleanExpected) {\n    var gotLines = this.splitLines(cleanGot);\n    var expectedLines = this.splitLines(cleanExpected);\n    if (gotLines.length <= 1 || expectedLines.length <= 1) {\n      return null;\n    }\n    var comparisonTable = [];\n    comparisonTable.push({header: 'Details of mismatch:'});\n    var shownTrailing = false;\n    var matching = 0;\n    for (var i=0; i<gotLines.length; i++) {\n      if (i >= expectedLines.length) {\n        if (! shownTrailing) {\n          comparisonTable.push({header: 'Trailing lines in got:'});\n          shownTrailing = true;\n        }\n        comparisonTable.push({got: gotLines[i], error: true});\n      } else {\n        var regexp = this.makeRegex(expectedLines[i]);\n        var error = gotLines[i].search(regexp) == -1;\n        comparisonTable.push({got: gotLines[i], expected: expectedLines[i], error: error});\n        if (! error) {\n          matching++;\n        }\n      }\n    }\n    if (matching <= 1) {\n      return null;\n    }\n    if (expectedLines.length > gotLines.length) {\n      comparisonTable.push({header: 'Trailing expected line(s):'});\n      for (i=gotLines.length; i<expectedLines.length; i++) {\n        comparisonTable.push({expected: expectedLines[i], error: true});\n      }\n    }\n    return comparisonTable;\n  },\n\n  makeRegex: function (pattern) {\n    var re = RegExpEscape(pattern);\n    re = '^' + re + '$';\n    re = re.replace(/\\\\\\.\\\\\\.\\\\\\./g, \"[\\\\S\\\\s\\\\r\\\\n]*\");\n    re = re.replace(/\\\\\\?/g, \"[a-zA-Z0-9_.\\\\?]+\");\n    re = re.replace(/[ \\t]+/g, \" +\");\n    re = re.replace(/[\"']/g, \"['\\\"]\");\n    return new RegExp(re);\n  },\n\n  clean: function (s) {\n    var lines = this.splitLines(s);\n    var result = [];\n    for (var i=0; i<lines.length; i++) {\n      var line = strip(lines[i]);\n      if (line) {\n        result.push(line);\n      }\n    }\n    return result.join('\\n');\n  },\n\n  splitLines: function (s) {\n    return s.split(/(?:\\r\\n|\\r|\\n)/);\n  }\n};\n\nvar HTMLReporter = exports.HTMLReporter = function (runner, containerEl) {\n  this.runner = runner;\n  if (! containerEl) {\n    if (doc.getElementById('doctest-output')) {\n      containerEl = 'doctest-output';\n    } else {\n      containerEl = makeElement('div');\n      doc.body.insertBefore(containerEl, doc.body.childNodes[0]);\n    }\n  }\n  if (typeof containerEl == 'string') {\n    containerEl = doc.getElementById(containerEl);\n  }\n  addClass(containerEl, 'doctest-report');\n  this.containerEl = containerEl;\n  this.containerEl.innerHTML = (\n    '<table class=\"doctest-report-table\">' +\n    '<tr><th>Passed:</th>' +\n    '<td id=\"doctest-success-count\">0</td></tr>' +\n    '<tr><th>Failures:</th>' +\n    '<td id=\"doctest-failure-count\">0</td>' +\n    '<td><button id=\"doctest-reload\">reload/retest</button></td></tr>' +\n    '<tr id=\"doctest-abort-row\" style=\"display: none\"><th>Aborted:</th>' +\n    '<td id=\"doctest-aborted\"></td></tr>' +\n    '<tr><th></th>' +\n    '<td colspan=2 id=\"doctest-failure-links\"></td></tr>' +\n    '</table>'\n    );\n  this.successEl = doc.getElementById('doctest-success-count');\n  this.failureEl = doc.getElementById('doctest-failure-count');\n  this.failureLinksEl = doc.getElementById('doctest-failure-links');\n  var button = doc.getElementById('doctest-reload');\n  // Sometimes this is sticky:\n  button.disabled = false;\n  button.addEventListener('click', function (ev) {\n    button.innerHTML = 'reloading...';\n    button.disabled = true;\n    location.reload();\n  }, false);\n};\n\nHTMLReporter.prototype = {\n\n  logSuccess: function (example, got) {\n    var num = parseInt(this.successEl.innerHTML.split('/')[0], 10);\n    num++;\n    this.successEl.innerHTML = num+' / '+this.runner.examples.length;\n    addClass(this.successEl, 'doctest-nonzero');\n    if (example.htmlSpan) {\n      addClass(example.htmlSpan, 'doctest-success');\n      if (example.expected.indexOf('...') != -1 ||\n          example.expected.indexOf('?') != -1) {\n        this.addExampleNote(example, 'Output:', 'doctest-actual-output', got || '(none)');\n      }\n    }\n    this.showConsoleOutput(example, false);\n    this.runner._hook('reportSuccess', example, got);\n  },\n\n  logFailure: function (example, got, comparisonTable) {\n    this.addFailure();\n    if (example.htmlSpan) {\n      addClass(example.htmlSpan, 'doctest-failure');\n      var showGot = got || '(nothing output)';\n      var expectedSpan = makeElement('span', {className: 'doctest-description'}, ['Expected:\\n']);\n      example.htmlSpan.insertBefore(expectedSpan, example.htmlSpan.querySelector('.doctest-output'));\n      if (! example.expected) {\n        example.htmlSpan.querySelector('.doctest-output').innerHTML = '(nothing expected)\\n';\n      }\n      this.addExampleNote(example, 'Got:', 'doctest-actual-output', showGot);\n    }\n    if (comparisonTable) {\n      this.addComparisonTable(example, comparisonTable);\n    }\n    if (example.blockEl) {\n      addClass(example.blockEl, 'doctest-some-failure');\n    }\n    if (example.htmlID) {\n      var anchor = makeElement('a', {href: '#' + example.htmlID, className: 'doctest-failure-link'}, [example.textSummary()]);\n      this.failureLinksEl.appendChild(anchor);\n      if (example.htmlID == positionOnFailure) {\n        location.hash = '#' + example.htmlID;\n      }\n    }\n    this.showConsoleOutput(example, true);\n    this.runner._hook('reportFailure', example, got);\n  },\n\n  logAbort: function (example, abortMessage) {\n    this.addFailure();\n    this.addAborted(abortMessage);\n    if (example.htmlSpan) {\n      addClass(example.htmlSpan, 'doctest-failure');\n    }\n    if (example.blockEl) {\n      addClass(example.blockEl, 'doctest-some-failure');\n    }\n    this.addExampleNote(example, 'Aborted:', 'doctest-actual-output', abortMessage);\n    this.runner._hook('reportAbort', example, abortMessage);\n  },\n\n  addFailure: function () {\n    var num = parseInt(this.failureEl.innerHTML, 10);\n    num++;\n    this.failureEl.innerHTML = num+'';\n    addClass(this.failureEl, 'doctest-nonzero');\n  },\n\n  addAborted: function (message) {\n    doc.getElementById('doctest-abort-row').style.display = '';\n    var td = doc.getElementById('doctest-aborted');\n    td.appendChild(doc.createTextNode(message));\n  },\n\n  showConsoleOutput: function (example, error) {\n    if (! example.consoleOutput.length) {\n      return;\n    }\n    if (! example.htmlSpan) {\n      return;\n    }\n    var text = example.consoleOutput.join('\\n');\n    this.addExampleNote(example, 'Console:', 'doctest-console', text);\n  },\n\n  addExampleNote: function (example, description, className, text) {\n    if (! example.htmlSpan) {\n      return;\n    }\n    example.htmlSpan.appendChild(makeElement('span', {className: 'doctest-description'}, [description + '\\n']));\n    example.htmlSpan.appendChild(makeElement('span', {className: className}, [text + '\\n']));\n  },\n\n  addComparisonTable: function (example, comparisonTable) {\n    if (! example.htmlSpan) {\n      // FIXME; should display text table\n      return;\n    }\n    var table = makeElement('table', {className: 'doctest-comparison-table'});\n    for (var i=0; i<comparisonTable.length; i++) {\n      var line = comparisonTable[i];\n      if (line.header) {\n        table.appendChild(makeElement('tr', {className: 'doctest-comparison-header'}, [\n          makeElement('th', {colspan: 2}, [line.header])\n        ]));\n      } else {\n        table.appendChild(makeElement('tr', {className: line.error ? 'doctest-comparison-error' : null}, [\n          makeElement('td', {className: 'doctest-comparison-got'}, [line.got || '']),\n          makeElement('td', {className: 'doctest-comparison-expected'}, [line.expected || ''])\n        ]));\n      }\n    }\n    example.htmlSpan.appendChild(table);\n  }\n};\n\nvar ConsoleReporter = exports.ConsoleReporter = function (runner) {\n  this.runner = runner;\n  this.successes = this.failures = 0;\n};\n\nConsoleReporter.prototype = {\n  logSuccess: function (example, got) {\n    this.successes++;\n    console.log('Passed:', example.textSummary());\n  },\n  logFailure: function (example, got) {\n    this.failures++;\n    console.log('Failed:', example.expr);\n    console.log('Expected:');\n    console.log(example.expected);\n    console.log('Got:');\n    console.log(got);\n  }\n};\n\n\nvar repr = exports.repr = function (o, indentString, maxLen) {\n  /* Taken from MochiKit, with an addition to print objects */\n  var reprMaker = new repr.ReprClass(indentString, maxLen);\n  return reprMaker.repr(o);\n};\n\nrepr.ReprClass = function (indentString, maxLen) {\n  this.indentString = indentString || '';\n  if (maxLen === undefined) {\n    maxLen = this.defaultMaxLen;\n  }\n  this.maxLen = maxLen;\n  this.tracker = [];\n};\n\nrepr.ReprClass.prototype = {\n  defaultMaxLen: 80,\n\n  repr: function reprFunc(o, indentString) {\n    if (indentString === undefined) {\n      indentString = this.indentString;\n    }\n    if (this.seenObject(o)) {\n      return '..recursive..';\n    }\n    if (o === undefined) {\n      return 'undefined';\n    } else if (o === null) {\n      return \"null\";\n    }\n    try {\n      if (typeof o.__repr__ == 'function') {\n        return o.__repr__(indentString, this.maxLen);\n      } else if (typeof o.repr == 'function' && o.repr != reprFunc &&\n                 o.repr != repr) {\n        return o.repr(indentString, this.maxLen);\n      }\n      for (var i=0; i<this.registry.length; i++) {\n        var item = this.registry[i];\n        if (item[0].call(this, o)) {\n          var func = item[1];\n          if (typeof func == \"string\") {\n            func = this[func];\n          }\n          return func.call(this, o, indentString);\n        }\n      }\n    } catch (e) {\n      // FIXME: unclear what purpose this serves:\n      console.warn('Error stringifying object:', e);\n      if (typeof(o.NAME) == 'string' && (\n            o.toString == Function.prototype.toString ||\n            o.toString == Object.prototype.toString)) {\n        return o.NAME;\n      }\n    }\n    var ostring;\n    try {\n      ostring = (o + \"\");\n      if (ostring == '[object Object]' || ostring == '[object]') {\n        ostring = this.objRepr(o, indentString);\n      }\n    } catch (e) {\n      return \"[\" + (typeof o) + \"]\";\n    }\n    if (typeof o == \"function\") {\n      ostring = ostring.replace(/^\\s+/, \"\").replace(/\\s+/g, \" \");\n      var idx = ostring.indexOf(\"{\");\n      if (idx != -1) {\n        ostring = ostring.substr(o, idx) + \"{...}\";\n      }\n    }\n    return ostring;\n  },\n\n  seenObject: function (obj) {\n    if (typeof obj != 'object' || obj === null) {\n      return false;\n    }\n    for (var i=0; i<this.tracker.length; i++) {\n      if (this.tracker[i] === obj) {\n        return true;\n      }\n    }\n    this.tracker.push(obj);\n    return false;\n  },\n\n  seenPosition: function () {\n    return this.tracker.length-1;\n  },\n\n  popSeen: function (point) {\n    this.tracker.splice(point, this.tracker.length - point);\n  },\n\n  objRepr: function (obj, indentString) {\n    var seenPosition = this.seenPosition();\n    var ostring = '{';\n    var keys = sortedKeys(obj);\n    for (var i=0; i<keys.length; i++) {\n      if (ostring != '{') {\n        ostring += ', ';\n      }\n      ostring += this.keyRepr(keys[i]) + ': ' + this.repr(obj[keys[i]]);\n    }\n    ostring += '}';\n    if (ostring.length > (this.maxLen - indentString.length)) {\n      this.popSeen(seenPosition);\n      ostring = this.multilineObjRepr(obj, indentString);\n    }\n    this.popSeen(seenPosition);\n    return ostring;\n  },\n\n  multilineObjRepr: function (obj, indentString) {\n    var keys = sortedKeys(obj);\n    var ostring = '{\\n';\n    for (var i=0; i<keys.length; i++) {\n      ostring += indentString + '  ' + this.keyRepr(keys[i]) + ': ';\n      ostring += this.repr(obj[keys[i]], indentString+'  ');\n      if (i != keys.length - 1) {\n        ostring += ',';\n      }\n      ostring += '\\n';\n    }\n    ostring += indentString + '}';\n    return ostring;\n  },\n\n  keyRepr: function (key) {\n    if (key.search(/^[a-zA-Z_][a-zA-Z0-9_]*$/) === 0) {\n      return key;\n    } else {\n      return this.repr(key);\n    }\n  },\n\n  arrayRepr: function (obj, indentString) {\n    var seenPosition = this.seenPosition();\n    var s = \"[\";\n    for (var i=0; i<obj.length; i++) {\n      s += this.repr(obj[i], indentString, this.maxLen);\n      if (i != obj.length-1) {\n        s += \", \";\n      }\n    }\n    s += \"]\";\n    if (s.length > (this.maxLen + indentString.length)) {\n      this.popSeen(seenPosition);\n      s = this.multilineArrayRepr(obj, indentString);\n    }\n    this.popSeen(seenPosition);\n    return s;\n  },\n\n  multilineArrayRepr: function (obj, indentString) {\n    var s = \"[\\n\";\n    for (var i=0; i<obj.length; i++) {\n      s += indentString + '  ' + this.repr(obj[i], indentString+'  ');\n      if (i != obj.length - 1) {\n        s += ',';\n      }\n      s += '\\n';\n    }\n    s += indentString + ']';\n    return s;\n  },\n\n  xmlRepr: function (el, indentString) {\n    var i;\n    if (el.nodeType == el.DOCUMENT_NODE) {\n      return \"<document \" + el.location.href + \">\";\n    }\n    if (el.nodeType == el.DOCUMENT_TYPE_NODE) {\n      return \"<!DOCTYPE \" + el.name + \">\";\n    }\n    var tagName = el.tagName || \"(no tag)\";\n    var s = '<' + tagName.toLowerCase();\n    var attrs = [];\n    if (el.attributes && el.attributes.length) {\n      for (i=0; i<el.attributes.length; i++) {\n        attrs.push(el.attributes[i].nodeName);\n      }\n      attrs.sort();\n      for (i=0; i<attrs.length; i++) {\n        s += ' ' + attrs[i] + '=\"';\n        var value = el.getAttribute(attrs[i]);\n        value = value.replace(/&/g, '&amp;');\n        value = value.replace(/\"/g, '&quot;');\n        s += value;\n        s += '\"';\n      }\n    }\n    if (! el.childNodes.length) {\n      s += ' />';\n      return s;\n    } else {\n      s += '>';\n    }\n    var hasNewline = false;\n    for (i=0; i<el.childNodes.length; i++) {\n      var child = el.childNodes[i];\n      if (child.nodeType == child.TEXT_NODE) {\n        s += strip(child.textContent);\n      } else {\n        if (! hasNewline) {\n          s += '\\n' + indentString;\n          hasNewline = true;\n        }\n        s += '  ' + this.xmlRepr(child, indentString + '  ');\n        s += '\\n' + indentString;\n      }\n    }\n    s += '</' + el.tagName.toLowerCase() + '>';\n    return s;\n  },\n\n  xhrRepr: function (req, indentString) {\n    var s = '[XMLHttpRequest ';\n    var states = {\n      0: 'UNSENT',\n      1: 'OPENED',\n      2: 'HEADERS_RECEIVED',\n      3: 'LOADING',\n      4: 'DONE'\n    };\n    s += states[req.readyState];\n    if (req.readyState == 4) {\n      s += ' ' + req.status + ' ' + req.statusText;\n    }\n    return s + ']';\n  },\n\n  registry: [\n    [function (o) {\n       return typeof o == 'string';\n     },\n     function (o) {\n       o = '\"' + o.replace(/([\\\"\\\\])/g, '\\\\$1') + '\"';\n       o = o.replace(/[\\f]/g, \"\\\\f\")\n       .replace(/[\\b]/g, \"\\\\b\")\n       .replace(/[\\n]/g, \"\\\\n\")\n       .replace(/[\\t]/g, \"\\\\t\")\n       .replace(/[\\r]/g, \"\\\\r\");\n       return o;\n     }\n    ],\n    [function (o) {\n       return typeof o == 'number';\n     },\n     function (o) {\n         return o + \"\";\n     }\n    ],\n    [function (o) {\n       return typeof o == 'object' && o.nodeType;\n     },\n     \"xmlRepr\"\n    ],\n    [function (o) {\n       var typ = typeof o;\n       if ((typ != 'object' && ! (typ == 'function' && typeof o.item == 'function')) ||\n           o === null ||\n           typeof o.length != 'number' ||\n           o.nodeType === 3) {\n           return false;\n       }\n       return true;\n     },\n     \"arrayRepr\"\n    ],\n    [function (o) {\n       return typeof XMLHttpRequest !== 'undefined' && o instanceof XMLHttpRequest;\n\n     },\n     'xhrRepr'\n    ]\n  ]\n\n};\n\nrepr.register = function (condition, reprFunc) {\n  repr.ReprClass.prototype.registry.push([condition, reprFunc]);\n};\n\nvar Runner = exports.Runner = function (options) {\n  this.examples = [];\n  options = options || {};\n  for (var i in options) {\n    if (options.hasOwnProperty(i)) {\n      if (this[i] === undefined) {\n        throw 'Unexpected option: ' + i;\n      }\n      this[i] = options[i];\n    }\n  }\n};\n\nRunner.prototype = {\n\n  init: function () {\n    if (this.matcher === null) {\n      this.matcher = this.makeMatcher();\n    }\n    if (this.reporter === null) {\n      this.reporter = this.makeReporter();\n    }\n    if (this.repr === null) {\n      this.repr = this.makeRepr();\n    }\n    this._hook('init', this);\n  },\n\n  run: function () {\n    this.init();\n    if (! this.examples.length) {\n      throw 'No examples have been added';\n    }\n    this._exampleIndex = 0;\n    this._runExample();\n  },\n\n  evalInit: function () {\n    if (typeof this.globs != \"undefined\") {\n      return this.globs;\n    }\n    this.logGrouped = false;\n    this._abortCalled = false;\n    var globs = {\n      write: this.write.bind(this),\n      writeln: this.writeln.bind(this),\n      printResolved: this.printResolved.bind(this),\n      wait: this.wait.bind(this),\n      Abort: this.Abort.bind(this),\n      repr: repr,\n      Spy: Spy,\n      jshint: jshint\n    };\n    globs.print = globs.writeln;\n    var consoleOverwrites = {\n      log: this.logFactory(null, console.log),\n      warn: this.logFactory(null, console.warn),\n      error: this.logFactory(null, console.error),\n      info: this.logFactory(null, console.info),\n      clear: this.clearLogs.bind(this)\n    };\n    if (typeof window == 'undefined') {\n      // Can't just overwrite the console object\n      globs.console = consoleOverwrites;\n      for (var i in console) {\n        if (console.hasOwnProperty(i) && (! globs.console.hasOwnProperty(i))) {\n          if (console[i].bind) {\n            globs.console[i] = console[i].bind(console);\n          } else {\n            globs.console[i] = console[i];\n          }\n        }\n      }\n      var context = require('vm').Script.createContext();\n      extend(context, globs);\n      return context;\n    } else {\n      extend(console, consoleOverwrites);\n      window.onerror = this.windowOnerror;\n      extend(window, globs);\n      return null;\n    }\n  },\n\n  write: function (text) {\n    this._currentExample.write(text);\n  },\n\n  writeln: function () {\n    for (var i=0; i<arguments.length; i++) {\n      if (i) {\n        this.write(' ');\n      }\n      if (typeof arguments[i] == \"string\") {\n        this.write(arguments[i]);\n      } else {\n        this.write(this.repr(arguments[i]));\n      }\n    }\n    this.write('\\n');\n  },\n\n  printResolved: function () {\n    // We used finished to signal that nothing should be printed, even when\n    // waiting is 0, as there are more arguments still to collect:\n    var finished = false;\n    var waiting = 0;\n    var fullValues = [];\n    var args = Array.prototype.slice.call(arguments);\n\n    // This function is called as each promise is resolved, to see if it\n    // was the last promise:\n    var check = (function (dec) {\n      waiting -= dec;\n      if (waiting || ! finished) {\n        return;\n      }\n      var flattened = [];\n      fullValues.forEach(function (items) {\n        items.forEach(function (item) {\n          flattened.push(item);\n        });\n      });\n      this.writeln.apply(this, flattened);\n    }).bind(this);\n\n    args.forEach(function (value, index) {\n      if (value.then) {\n        // It's a promise\n        waiting++;\n        value.then(\n          (function () {\n            var values = Array.prototype.slice.call(arguments);\n            if ((! values.length) || (values.length === 1 && values[0] === undefined)) {\n              values = [\"(resolved)\"];\n            }\n            fullValues[index] = values;\n            check(1);\n          }).bind(this),\n          (function () {\n            var errs = Array.prototype.slice.call(arguments);\n            if ((! errs.length) || (errs.length === 1 && errs[0] === undefined)) {\n              errs = [\"(error)\"];\n            }\n            errs = [\"Error:\"].concat(errs);\n            fullValues[index] = errs;\n            check(1);\n          }).bind(this));\n      } else {\n        fullValues[index] = [value];\n      }\n    }, this);\n    finished = true;\n    if (waiting) {\n      this.wait(function () {\n        return ! waiting;\n      });\n    }\n    check(0);\n  },\n\n  wait: function (conditionOrTime, hardTimeout) {\n    // FIXME: should support a timeout even with a condition\n    if (conditionOrTime === undefined ||\n        conditionOrTime === null) {\n      // same as wait-some-small-amount-of-time\n      conditionOrTime = 0;\n    }\n    this._waitCondition = conditionOrTime;\n    if (typeof conditionOrTime == \"number\") {\n      if (((! hardTimeout) && this._defaultWaitTimeout < conditionOrTime) ||\n          hardTimeout < conditionOrTime) {\n        hardTimeout = conditionOrTime + 10;\n      }\n    }\n    this._waitTimeout = hardTimeout;\n    this._exampleWait = true;\n  },\n\n  // FIXME: maybe this should be set more carefully just during the tests?\n  windowOnerror: function (message, filename, lineno) {\n    var m = message;\n    if (filename || lineno) {\n      m += ' (';\n      if (filename) {\n        m += filename;\n        if (lineno) {\n          m += ':' + lineno;\n        }\n      } else {\n        m += 'line ' + lineno;\n      }\n      m += ')';\n    }\n    writeln('Error: ' + m);\n  },\n\n  logFactory: function (prefix, origFunc) {\n    var self = this;\n    var logFunc = origFunc || console.log.origFunc || console.log;\n\n    var func = function () {\n      if (console.group && (! self.logGrouped)) {\n        self.logGrouped = true;\n        console.group('Output from example:');\n      }\n      logFunc.apply(console, arguments);\n      var s = prefix || '';\n      for (var i=0; i<arguments.length; i++) {\n        var text = arguments[i];\n        if (i) {\n          s += ' ';\n        }\n        if (typeof text == \"string\") {\n          s += text;\n        } else {\n          s += repr(text);\n        }\n      }\n      self._currentExample.writeConsole(s);\n    };\n    func.origFunc = origFunc;\n    return func;\n  },\n\n  clearLogs: function () {\n    this._currentExample.clearConsole();\n    if (console.clear.origFunc) {\n      console.clear.origFunc.call(console);\n    }\n  },\n\n  Abort: function (message) {\n    this._abortCalled = message || 'aborted';\n    return {\n      \"doctest.abort\": true,\n      toString: function () {return 'Abort(' + message + ')';}\n    };\n  },\n\n  evalUninit: function () {\n    if (this.logGrouped) {\n      if (console.groupEnd) {\n        console.groupEnd();\n      } else if (console.endGroup) {\n        console.endGroup();\n      }\n    }\n    this.logGrouped = false;\n    if (typeof window != 'undefined') {\n      window.write = undefined;\n      window.writeln = undefined;\n      window.printResolved = undefined;\n      window.print = undefined;\n      window.wait = undefined;\n      window.onerror = undefined;\n      window.jshint = undefined;\n      window.console.log = window.console.log.origFunc;\n      window.console.warn = window.console.warn.origFunc;\n      window.console.error = window.console.error.origFunc;\n      window.console.info = window.console.info.origFunc;\n      window.console.clear = window.console.clear.origFunc;\n    }\n  },\n\n  evaller: function (expr, context, filename) {\n    var e = eval;\n    var result;\n    if (context) {\n      if (typeof window == \"undefined\") {\n        var vm = require('vm');\n\n        if (! (context instanceof vm.Script.createContext().constructor)) {\n            throw \"context must be created with vm.Script.createContext()\";\n        }\n\n        // Prepare context to evaluate `expr` in. Mostly follows CoffeeScript\n        // [eval function](http://git.io/coffee-script-eval).\n        context.global = context.root = context.GLOBAL = context;\n        context.__filename = typeof filename != \"undefined\" ? filename : __filename;\n        context.__dirname = require('path').dirname(context.__filename);\n        context.module = module;\n        context.require = require;\n\n        // Set `module.filename` to script file name and evaluate the script.\n        // Now, if the script executes `require('./something')`, it will look\n        // up `'./something'` relative to script path.\n        //\n        // We restore `module.filename` afterwards, because `module` object\n        // is reused. The other approach is to create a new `module` instance.\n        // CoffeeScript [eval][1] [works this way][2]. Unfortunately it\n        // [uses private Node API][3] to do it.\n        //\n        // [1]: http://git.io/coffee-script-eval\n        // [2]: https://github.com/jashkenas/coffee-script/pull/1487\n        // [3]: http://git.io/coffee-script-eval-comment\n        var prevfilename = module.filename;\n        module.filename = context.__filename;\n        try {\n          vm.runInContext(expr, context, context.__filename);\n        } finally {\n            module.filename = prevfilename;\n        }\n\n      } else {\n        with (context) {\n          result = eval(expr);\n        }\n      }\n    } else {\n      result = e(expr);\n    }\n    return result;\n  },\n\n  _runExample: function () {\n    if (this._abortCalled) {\n      return;\n    }\n    while (true) {\n      if (this._exampleIndex >= this.examples.length) {\n        this._finish();\n        break;\n      }\n      this._currentExample = this.examples[this._exampleIndex];\n      this._exampleIndex++;\n      this._currentExample.run();\n      if (this._exampleWait && ! this._abortCalled) {\n        this._runWait();\n        break;\n      }\n      this.evalUninit();\n      this._currentExample.check();\n      if (this._abortCalled) {\n        // FIXME: this should show that while finished, and maybe successful,\n        // the tests were aborted\n        this.reporter.logAbort(this._currentExample, this._abortCalled);\n        this._finish();\n        break;\n      }\n      this._currentExample = null;\n    }\n  },\n\n  _runWait: function () {\n    var start = Date.now();\n    var waitTimeout = this._waitTimeout || this._defaultWaitTimeout;\n    this._waitTimeout = null;\n    var self = this;\n    function poll() {\n      var now = Date.now();\n      var cond = self._waitCondition;\n      if (typeof cond == \"number\") {\n        if (now - start >= cond) {\n          self._exampleWait = false;\n        }\n      } else if (cond) {\n        if (cond()) {\n          self._exampleWait = false;\n        }\n      }\n      if (self._exampleWait) {\n        if (now - start > waitTimeout) {\n          self._currentExample.timeout(now - start);\n        } else {\n          setTimeout(poll, self._waitPollTime);\n          return;\n        }\n      }\n      self.evalUninit();\n      self._currentExample.check();\n      self._currentExample = null;\n      self._runExample();\n    }\n    // FIXME: instead of the poll time, cond could be used if it is a number\n    setTimeout(poll, this._waitPollTime);\n  },\n\n  _hook: function (method) {\n    if (typeof doctestReporterHook == \"undefined\") {\n      return null;\n    } else if (method && arguments.length > 1 && doctestReporterHook[method]) {\n      var args = argsToArray(arguments).slice(1);\n      return doctestReporterHook[method].apply(doctestReporterHook, args);\n    } else if (method) {\n      return doctestReporterHook[method];\n    } else {\n      return doctestReporterHook;\n    }\n  },\n\n  _finish: function () {\n    if (attemptedHash && location.hash == attemptedHash) {\n      // This fixes up the anchor position after tests have run.\n      // FIXME: would be nice to detect if the user has scrolled between\n      // page load and the current moment\n      location.hash = '';\n      location.hash = attemptedHash;\n    }\n    this._hook('finish', this);\n  },\n\n  _waitPollTime: 100,\n  _waitTimeout: null,\n  _waitCondition: null,\n  _defaultWaitTimeout: 5000,\n\n  /* Dependency Injection, yay! */\n  examples: null,\n  Example: Example,\n  exampleOptions: null,\n  makeExample: function (text, expected, filename) {\n    var options = {filename: filename};\n    extend(options, this.exampleOptions);\n    return new this.Example(this, text, expected, options);\n  },\n  matcher: null,\n  Matcher: Matcher,\n  matcherOptions: null,\n  makeMatcher: function () {\n    return new this.Matcher(this, this.matcherOptions);\n  },\n  reporter: null,\n  Reporter: HTMLReporter,\n  reporterOptions: null,\n  makeReporter: function () {\n    return new this.Reporter(this, this.reporterOptions);\n  },\n  repr: repr\n};\n\nvar HTMLParser = exports.HTMLParser = function (runner, containerEl, selector) {\n  this.runner = runner;\n  containerEl = containerEl || doc.body;\n  if (typeof containerEl == 'string') {\n    containerEl = doc.getElementById(containerEl);\n  }\n  if (! containerEl) {\n    throw 'Bad/null/missing containerEl';\n  }\n  this.containerEl = containerEl;\n  this.selector = selector || 'pre.doctest, pre.commenttest, pre.test';\n};\n\nHTMLParser.prototype = {\n  parse: function () {\n    var els = this.findEls();\n    for (var i=0; i<els.length; i++) {\n      try {\n        this.parseEl(els[i]);\n      } catch (e) {\n        addClass(els[i], 'doctest-some-failure');\n        this.runner.reporter.addFailure();\n        var failed = makeElement('span', {className: 'doctest-example doctest-failure'}, ['Exception parsing element: ', e+'\\n']);\n        els[i].insertBefore(failed, els[i].childNodes[0]);\n        throw e;\n      }\n    }\n  },\n\n  findEls: function () {\n    return this.containerEl.querySelectorAll(this.selector);\n  },\n\n  parseEl: function (el) {\n    var examples;\n    if (hasClass(el, 'doctest')) {\n      examples = this.parseDoctestEl(el);\n    } else if (hasClass(el, 'commenttest') || hasClass(el, 'test')) {\n      examples = this.parseCommentEl(el);\n    } else {\n      throw 'Unknown element class/type';\n    }\n    var newChildren = [];\n    for (var i=0; i<examples.length; i++) {\n      var example = examples[i][0];\n      var output = examples[i][1];\n      var rawExample = examples[i][2];\n      var rawOutput = examples[i][3];\n      var ex = this.runner.makeExample(example, output);\n      this.runner.examples.push(ex);\n      ex.blockEl = el;\n      ex.htmlID = genID('example');\n      var span = makeElement('span', {id: ex.htmlID, className: 'doctest-example'}, [\n        makeElement('div', {className: 'doctest-expr'}, [rawExample]),\n        makeElement('div', {className: 'doctest-output'}, [rawOutput])\n        ]);\n      ex.htmlSpan = span;\n      newChildren.push(span);\n    }\n    el.innerHTML = '';\n    for (var i=0; i<newChildren.length; i++) {\n      el.appendChild(newChildren[i]);\n    }\n  },\n\n  parseDoctestEl: function (el) {\n    var result = [];\n    var text = getElementText(el);\n    var lines = text.split(/(?:\\r\\n|\\r|\\n)/);\n    var exampleLines = [];\n    var rawExample = [];\n    var outputLines = [];\n    var rawOutput = [];\n    for (var i=0; i<lines.length; i++) {\n      var line = lines[i];\n      if (line.search(/^\\s*[$]/) != -1 || i==lines.length-1) {\n        if (exampleLines.length) {\n          result.push([\n            exampleLines.join('\\n'), outputLines.join('\\n'),\n            rawExample.join('\\n'), rawOutput.join('\\n')]);\n        }\n        exampleLines = [];\n        outputLines = [];\n        rawExample = [];\n        rawOutput = [];\n        rawExample.push(line);\n        line = line.replace(/^ *[$] ?/, '');\n        exampleLines.push(line);\n      } else if (/^>/.test(line)) {\n        if (! exampleLines.length) {\n          throw ('Bad example: ' + this.runner.repr(line) + '\\n' +\n            '> line not preceded by $');\n        }\n        rawExample.push(line);\n        line = line.replace(/^ *> ?/, '');\n        exampleLines.push(line);\n      } else {\n        rawOutput.push(line);\n        outputLines.push(line);\n      }\n    }\n    return result;\n  },\n\n  parseCommentEl: function (el) {\n    if (typeof esprima == \"undefined\") {\n      if (typeof require != \"undefined\") {\n        esprima = require(\"./esprima/esprima.js\");\n      } else {\n        throw 'You must install or include esprima.js';\n      }\n    }\n    var contents = getElementText(el);\n    var ast = esprima.parse(contents, {\n      range: true,\n      comment: true\n    });\n    var pos = 0;\n    var result = [];\n    for (var i=0; i<ast.comments.length; i++) {\n      var comment = ast.comments[i];\n      if (comment.value.search(/^\\s*==?>/) == -1) {\n        // Not a comment we care about\n        continue;\n      }\n      var start = comment.range[0];\n      var end = comment.range[1];\n      var example = contents.substr(pos, start-pos);\n      var output = comment.value.replace(/^\\s*=> ?/, '');\n      var orig = comment.type == 'Block' ? '/*' + comment.value + '*/' : '//' + comment.value;\n      if (example === '') {\n          result[result.length-1][1] += '\\n'+output;\n          result[result.length-1][3] += '\\n'+orig;\n      }\n      else {\n        result.push([example, output, example, orig]);\n      }\n      pos = end;\n    }\n    var last = contents.substr(pos, contents.length-pos);\n    if (strip(last)) {\n      result.push([last, '', last, '']);\n    }\n    return result;\n  },\n\n  loadRemotes: function (callback, selector) {\n    var els;\n    if (! selector) {\n      els = this.findEls();\n    } else {\n      els = document.querySelectorAll(selector);\n    }\n    var pending = 0;\n    argsToArray(els).forEach(function (el) {\n      var href = el.getAttribute('data-href-pattern');\n      if (href) {\n        try {\n          href = this.fillPattern(href);\n        } catch (e) {\n          var text = '// Error resolving data-href-pattern \"' + href + '\":\\n';\n          text += '// ' + e;\n          el.innerHTML = '';\n          el.appendChild(document.createTextNode(text));\n          return;\n        }\n      }\n      if (! href) {\n        href = el.getAttribute('href');\n      }\n      if (! href) {\n        href = el.getAttribute('src');\n      }\n      if (! href) {\n        return;\n      }\n      pending++;\n      var req = new XMLHttpRequest();\n      if (href.indexOf('?') == -1) {\n        // Try to stop some caching:\n        href += '?nocache=' + Date.now();\n      }\n      req.open('GET', href);\n      req.setRequestHeader('Cache-Control', 'no-cache, max-age=0');\n      req.onreadystatechange = (function () {\n        if (req.readyState != 4) {\n          return;\n        }\n        if (req.status != 200 && !(req.status === 0 && document.location.protocol == \"file:\")) {\n          el.appendChild(doc.createTextNode('\\n// Error fetching ' + href + ' status: ' + req.status));\n        } else {\n          this.fillElement(el, req.responseText);\n        }\n        pending--;\n        if (! pending) {\n          callback();\n        }\n      }).bind(this);\n      req.send();\n    }, this);\n    if (! pending) {\n      callback();\n    }\n  },\n\n  fillPattern: function (pattern) {\n    var regex = /\\{([^\\}]+)\\}/;\n    var result = '';\n    while (true) {\n      var match = regex.exec(pattern);\n      if (! match) {\n        result += pattern;\n        break;\n      }\n      result += pattern.substr(0, match.index);\n      pattern = pattern.substr(match.index + match[0].length);\n      var name = match[1];\n      var restriction = \"^[\\\\w_\\\\-\\\\.]+$\";\n      var defaultValue = '';\n      if (name.lastIndexOf('|') != -1) {\n        defaultValue = name.substr(name.lastIndexOf('|')+1);\n        name = name.substr(0, name.lastIndexOf('|'));\n      }\n      if (name.indexOf(':') != -1) {\n        restriction = name.substr(name.indexOf(':')+1);\n        name = name.substr(0, name.indexOf(':'));\n      }\n      var value = params[name];\n      if (! value) {\n        value = defaultValue;\n      }\n      if (restriction && value.search(new RegExp(restriction)) == -1) {\n        throw 'Bad substitution for {' + name + ':' + restriction + '}: \"' + value + '\"';\n      }\n      result += value;\n    }\n    return result;\n  },\n\n  fillElement: function (el, text) {\n    el.innerHTML = '';\n    if (hasClass(el, 'commenttest') || hasClass(el, 'test')) {\n      var texts = this.splitText(text);\n      console.log(\"filling in tests\", texts, el);\n      if (texts && texts.length == 1 && ! texts[0].header) {\n        el.appendChild(document.createTextNode(texts[0].body));\n      } else if (texts && texts.length) {\n        for (var i=0; i<texts.length; i++) {\n          if (texts[i].header) {\n            var h3 = document.createElement('h3');\n            h3.className = 'doctest-section-header';\n            h3.appendChild(document.createTextNode(texts[i].header));\n            el.parentNode.insertBefore(h3, null);\n          }\n          var pre = document.createElement('pre');\n          pre.className = el.className;\n          pre.appendChild(document.createTextNode(texts[i].body));\n          if (texts[i].expandOnFailure) {\n            pre.className += \" expand-on-failure\";\n          }\n          el.parentNode.insertBefore(pre, null);\n        }\n        el.parentNode.removeChild(el);\n      }\n    }\n  },\n\n  splitText: function (text) {\n    var ast;\n    try {\n      ast = esprima.parse(text, {\n        range: true,\n        comment: true\n      });\n    } catch (e) {\n      // The error will get reported later on, so we'll just ignore it here\n      return [{header: null, body: text}];\n    }\n    // FIXME: check if it didn't parse\n    var result = [];\n    var pos = 0;\n    for (var i=0; i<ast.comments.length; i++) {\n      var comment = ast.comments[i];\n      if (comment.value.search(/^\\s*=+\\s*SECTION/) == -1) {\n        // Not a section comment\n        continue;\n      }\n      var start = comment.range[0];\n      var end = comment.range[1];\n      var body = text.substr(pos, start-pos);\n      var header = strip(comment.value.replace(/^\\s*=+\\s*SECTION\\s*/, ''));\n      var expandOnFailure = false;\n      if (header.search(/expand-on-failure/i) !== -1) {\n        expandOnFailure = true;\n        header = header.replace(/\\s*expand-on-failure/i, \"\");\n      }\n      if (! result.length) {\n        if (strip(body)) {\n          result.push({header: null, body: body});\n        }\n      } else {\n        result[result.length-1].body = body;\n      }\n      result.push({header: header, body: null, expandOnFailure: expandOnFailure});\n      pos = end;\n    }\n    if (! result.length) {\n      // No sections\n      return [{header: '', body: text}];\n    }\n    var last = text.substr(pos, text.length-pos);\n    result[result.length-1].body = last;\n    return result;\n  }\n\n};\n\nvar TextParser = exports.TextParser = function (runner, text, filename) {\n  if (typeof esprima == \"undefined\") {\n    if (typeof require != \"undefined\") {\n      esprima = require(\"./esprima/esprima.js\");\n    } else {\n      throw 'You must install or include esprima.js';\n    }\n  }\n  this.runner = runner;\n  this.text = text;\n  this.filename = filename;\n};\n\nTextParser.fromFile = function (runner, filename) {\n  if (typeof filename != \"string\") {\n    throw \"You did not give a filename for the second argument: \" + filename;\n  }\n  if (typeof require == \"undefined\") {\n    throw \"This method only works in Node, with the presence of require()\";\n  }\n  var fs = require('fs');\n  var text = fs.readFileSync(filename, 'UTF-8');\n  return new TextParser(runner, text, filename);\n};\n\nTextParser.prototype = {\n  parse: function () {\n    var ast = esprima.parse(this.text, {\n      range: true,\n      comment: true\n    });\n    // FIXME: check if text didn't parse\n    var pos = 0;\n    for (var i=0; i<ast.comments.length; i++) {\n      var comment = ast.comments[i];\n      if (comment.value.search(/^\\s*==?>/) == -1) {\n        // Not a comment we care about\n        continue;\n      }\n      var start = comment.range[0];\n      var end = comment.range[1];\n      var example = this.text.substr(pos, start-pos);\n      var output = comment.value.replace(/^\\s*=>\\s*/, '');\n      var ex = this.runner.makeExample(example, output, this.filename);\n      this.runner.examples.push(ex);\n      pos = end;\n    }\n    var last = this.text.substr(pos, this.text.length-pos);\n    if (strip(last)) {\n      this.runner.examples.push(this.runner.makeExample(last, '', this.filename));\n    }\n  }\n};\n\nvar strip = exports.strip = function (str) {\n  str = str + \"\";\n  return str.replace(/\\s+$/, \"\").replace(/^\\s+/, \"\");\n};\n\nvar rstrip = exports.rstrip = function (str) {\n  str = str + \"\";\n  return str.replace(/\\s+$/, \"\");\n};\n\nvar argsToArray = exports.argToArray = function (args) {\n  var array = [];\n  for (var i=0; i<args.length; i++) {\n    array.push(args[i]);\n  }\n  return array;\n};\n\nvar extend = exports.extend = function (obj, extendWith) {\n  for (var i in extendWith) {\n    if (extendWith.hasOwnProperty(i)) {\n      obj[i] = extendWith[i];\n    }\n  }\n  return obj;\n};\n\nvar extendDefault = exports.extendDefault = function (obj, extendWith) {\n  for (var i in extendWith) {\n    if (extendWith.hasOwnProperty(i) && obj[i] === undefined) {\n      obj[i] = extendWith[i];\n    }\n  }\n  return obj;\n};\n\nvar genID = exports.genID = function (prefix) {\n  prefix = prefix || 'generic-doctest';\n  var id = arguments.callee._idGen++;\n  return prefix + '-' + id;\n};\ngenID._idGen = 1;\n\nfunction deIndent(text) {\n    var minimum_spaces = 10000;\n    var foo = text.split('\\n');\n    var i = 0;\n    var j = 0;\n    var result = '';\n    for (i=0; i < foo.length; i++) {\n        for (j=0; j < foo[i].length && j < minimum_spaces; j++) {\n            if (foo[i][j] != ' ') {\n                if (j < minimum_spaces) {\n                    minimum_spaces = j;\n                }\n                break;\n            }\n        }\n    }\n    if (minimum_spaces == 0) {\n        return text.replace(/^\\s+|\\s+$/g, '');\n    }\n    for (i=0; i < foo.length; i++) {\n        if (strip(foo[i].substr(0, minimum_spaces)) !== '') {\n            throw 'Deindent failed';\n        }\n        result += foo[i].substr(minimum_spaces) + '\\n';\n    }\n    return strip(result);\n}\n\nvar getElementText = exports.getElementText = function (el) {\n  if (! el) {\n    throw('You must pass in an element');\n  }\n  var text = '';\n  for (var i=0; i<el.childNodes.length; i++) {\n    var sub = el.childNodes[i];\n    if (sub.nodeType == 3) {\n      // TEXT_NODE\n      text += sub.nodeValue;\n    } else if (sub.childNodes) {\n      text += getElementText(sub);\n    }\n  }\n\n  return deIndent(text);\n};\n\nvar makeElement = exports.makeElement = function (tagName, attrs, children) {\n  var el = doc.createElement(tagName);\n  if (attrs) {\n    for (var i in attrs) {\n      if (attrs.hasOwnProperty(i)) {\n        if (i == 'className') {\n          el.className = attrs[i];\n        } else {\n          el.setAttribute(i, attrs[i]);\n        }\n      }\n    }\n  }\n  if (children) {\n    for (var i=0; i<children.length; i++) {\n      if (typeof children[i] == 'string') {\n        el.appendChild(doc.createTextNode(children[i]));\n      } else {\n        el.appendChild(children[i]);\n      }\n    }\n  }\n  return el;\n};\n\nvar addClass = exports.addClass = function (el, className) {\n  if (! el.className) {\n    el.className = className;\n  } else if (! hasClass(el, className)) {\n    el.className += ' ' + className;\n  }\n};\n\nvar hasClass = exports.hasClass = function (el, className) {\n  return (' ' + el.className + ' ').indexOf(' ' + className + ' ') != -1;\n};\n\nvar RegExpEscape = exports.RegExpEscape = function (text) {\n  if (! arguments.callee.sRE) {\n    var specials = [\n      '/', '.', '*', '+', '?', '|', '$',\n      '(', ')', '[', ']', '{', '}', '\\\\'\n    ];\n    arguments.callee.sRE = new RegExp(\n      '(\\\\' + specials.join('|\\\\') + ')', 'g'\n    );\n  }\n  return text.replace(arguments.callee.sRE, '\\\\$1');\n};\n\nvar objDiff = exports.objDiff = function (orig, current) {\n  var result = {\n    added: {},\n    removed: {},\n    changed: {},\n    same: {}\n  };\n  for (var i in orig) {\n    if (! (i in current)) {\n      result.removed[i] = orig[i];\n    } else if (orig[i] !== current[i]) {\n      result.changed[i] = [orig[i], current[i]];\n    } else {\n      result.same[i] = orig[i];\n    }\n  }\n  for (i in current) {\n    if (! (i in orig)) {\n      result.added[i] = current[i];\n    }\n  }\n  return result;\n};\n\nvar writeDiff = exports.writeDiff = function (orig, current, indentString) {\n  if (typeof orig != 'object' || typeof current != 'object') {\n    print(indentString + repr(orig, indentString) + ' -> ' + repr(current, indentString));\n    return;\n  }\n  indentString = indentString || '';\n  var diff = objDiff(orig, current);\n  var i, keys;\n  var any = false;\n  keys = sortedKeys(diff.added);\n  for (i=0; i<keys.length; i++) {\n    any = true;\n    print(indentString + '+' + keys[i] + ': '\n          + repr(diff.added[keys[i]], indentString));\n  }\n  keys = sortedKeys(diff.removed);\n  for (i=0; i<keys.length; i++) {\n    any = true;\n    print(indentString + '-' + keys[i] + ': '\n          + repr(diff.removed[keys[i]], indentString));\n  }\n  keys = sortedKeys(diff.changed);\n  for (i=0; i<keys.length; i++) {\n    any = true;\n    print(indentString + keys[i] + ': '\n          + repr(diff.changed[keys[i]][0], indentString)\n          + ' -> '\n          + repr(diff.changed[keys[i]][1], indentString));\n  }\n  if (! any) {\n    print(indentString + '(no changes)');\n  }\n};\n\nvar sortedKeys = exports.sortedKeys = function (obj) {\n  var keys = [];\n  for (var i in obj) {\n    if (obj.hasOwnProperty(i)) {\n      keys.push(i);\n    }\n  }\n  keys.sort();\n  return keys;\n};\n\nvar Spy = exports.Spy = function (name, options, extraOptions) {\n  var self;\n  name = name || 'spy';\n  if (Spy.spies[name]) {\n     self = Spy.spies[name];\n     if ((! options) && ! extraOptions) {\n       return self;\n     }\n  } else {\n    self = function () {\n      return self.func.apply(this, arguments);\n    };\n  }\n  options = options || {};\n  if (typeof options == 'function') {\n    options = {applies: options};\n  }\n  if (extraOptions) {\n    extendDefault(options, extraOptions);\n  }\n  extendDefault(options, Spy.defaultOptions);\n  self._name = name;\n  self.options = options;\n  self.called = false;\n  self.calledWait = false;\n  self.args = null;\n  self.self = null;\n  self.argList = [];\n  self.selfList = [];\n  self.writes = options.writes || false;\n  self.returns = options.returns || undefined;\n  self.applies = options.applies || null;\n  self.throwError = options.throwError || null;\n  self.ignoreThis = options.ignoreThis || false;\n  self.wrapArgs = options.wrapArgs || false;\n  self.func = function () {\n    self.called = true;\n    self.calledWait = true;\n    self.args = argsToArray(arguments);\n    self.self = this;\n    self.argList.push(self.args);\n    self.selfList.push(this);\n    // It might be possible to get the caller?\n    if (self.writes) {\n      if (typeof writeln == \"undefined\") {\n        console.warn(\"Spy writing outside of test:\", self.formatCall());\n      } else {\n        writeln(self.formatCall());\n      }\n    }\n    if (self.throwError) {\n      var throwError = self.throwError;\n      if (typeof throwError == \"function\") {\n        throwError = self.throwError.apply(this, arguments);\n      }\n      throw throwError;\n    }\n    if (self.applies) {\n      try {\n        return self.applies.apply(this, arguments);\n      } catch (e) {\n        console.error('Error in ' + self.repr() + '.applies:', e);\n        throw e;\n      }\n    }\n    return self.returns;\n  };\n  self.func.toString = function () {\n    return \"Spy('\" + self._name + \"').func\";\n  };\n\n  // Method definitions:\n  self.formatCall = function () {\n    var s = '';\n    if ((! self.ignoreThis) && self.self !== globalObject && self.self !== self) {\n      s += repr(self.self) + '.';\n    }\n    s += self._name;\n    if (self.args === null) {\n      return s + ':never called';\n    }\n    s += '(';\n    // This eliminates trailing undefined arguments:\n    var length = self.args.length;\n    while (length && self.args[length-1] === undefined) {\n      length--;\n    }\n    for (var i=0; i<length; i++) {\n      if (i) {\n        s += ', ';\n      }\n      var maxLen;\n      if (self.wrapArgs) {\n        maxLen = 10;\n      } else {\n        maxLen = undefined;\n      }\n      s += repr(self.args[i], '', maxLen);\n    }\n    s += ')';\n    return s;\n  };\n\n  self.method = function (name, options, extraOptions) {\n    var desc = self._name + '.' + name;\n    var newSpy = Spy(desc, options, extraOptions);\n    self[name] = self.func[name] = newSpy.func;\n    return newSpy;\n  };\n\n  self.methods = function (props) {\n    for (var i in props) {\n      if (props.hasOwnProperty(i)) {\n        var prop = props[i];\n        if (prop === true || prop === false || prop === null) {\n          prop = {};\n        }\n        self.method(i, props[i]);\n      }\n    }\n    return self;\n  };\n\n  self.wait = function (timeout) {\n    var func = function () {\n      var value = self.calledWait;\n      if (value) {\n        self.calledWait = false;\n      }\n      return value;\n    };\n    func.repr = function () {\n      return 'called:'+repr(self);\n    };\n    wait(func, timeout);\n  };\n\n  self.repr = function () {\n    return \"Spy('\" + self._name + \"')\";\n  };\n\n  if (options.methods) {\n    self.methods(options.methods);\n  }\n  Spy.spies[name] = self;\n  if (options.wait) {\n    if (typeof options.wait == 'number') {\n      self.wait(options.wait);\n    } else {\n      self.wait();\n    }\n  }\n  return self;\n};\n\nSpy.spies = {};\nSpy.defaultOptions = {writes: true};\n\nSpy.on = function (obj, attrOrOptions, options) {\n  if (typeof obj == \"string\") {\n    var name = obj;\n    if (obj.indexOf('.') == -1) {\n      throw 'You must provide an object name with a .attribute (not: \"' + obj + '\")';\n    }\n    var attr = obj.substr(obj.lastIndexOf('.')+1);\n    var objName = obj.substr(0, obj.lastIndexOf('.'));\n    var e = eval;\n    try {\n      var obj = eval(objName);\n    } catch (e) {\n      throw 'Could not get object \"' + obj + '\": ' + e + ' (maybe you are not referring to a global variable?)';\n    }\n    if (obj === undefined || obj === null) {\n      throw 'Object \"' + objName + '\" is ' + obj;\n    }\n    options = attrOrOptions;\n  } else {\n    var name = attrOrOptions;\n    if (name.indexOf('.') == -1) {\n      throw 'You must provide an object name with a .attribute (not: \"' + obj + '\")';\n    }\n    attr = attrOrOptions.substr(attrOrOptions.lastIndexOf('.')+1);\n  }\n  var spy = Spy(name, options);\n  spy.overriding = obj[attr];\n  spy.onAttribute = attr;\n  spy.onObject = obj;\n  obj[attr] = spy;\n  return spy;\n};\n\nvar params = exports.params = {};\n\nfunction jshint(src, options) {\n  if (typeof JSHINT == 'undefined') {\n    throw 'jshint.js is not included';\n  }\n  if (! src) {\n    throw 'You must call jshint(src) with a src (got ' + src + ')';\n  }\n  var url = src;\n  if (typeof document != 'undefined') {\n    var scripts = document.getElementsByTagName('script');\n    for (var i=0; i<scripts.length; i++) {\n      var scriptSrc = scripts[i].src;\n      if (scriptSrc.indexOf(src) != -1) {\n        url = scriptSrc;\n        break;\n      }\n    }\n  }\n  var req = new XMLHttpRequest();\n  req.open('GET', url);\n  var done = false;\n  req.onreadystatechange = function () {\n    if (req.readyState != 4) {\n      return;\n    }\n    if (req.status != 200) {\n      if (req.status === 0) {\n        print('Error: request to', url, 'failed with no status (cross-origin problem?');\n      } else {\n        print('Error: request to', url, 'failed with status:', req.status);\n      }\n    } else {\n      var text = req.responseText;\n      text = _removeJshintSections(text);\n      var result = JSHINT(text, options);\n      if (result) {\n        print('Script passed:', url);\n      } else {\n        print('Script failed:', repr(url));\n        for (var i=0; i<JSHINT.errors.length; i++) {\n          var error = JSHINT.errors[i];\n          if (error === null) {\n            print('Fatal error; jshint could not continue');\n          } else {\n            print('  ' + (error.line) + ':' + (error.character) + ' ' + error.reason);\n            print('    ' + error.evidence);\n          }\n        }\n      }\n      /*  Doesn't seem helpful:\n      var report = JSHINT.report();\n      report = report.replace(/<br>(<(div|p)[^>]*>)?/g, '\\n');\n      report = report.replace(/<(div|p)[^>]*>/g, '\\n');\n      report = report.replace(/<[^>]*>/g, ' ');\n      report = report.replace(/  +/g, ' ');\n      console.log('Report:', report);\n      */\n    }\n    done = true;\n  };\n  req.send();\n  wait(function () {return done;});\n}\n\nfunction _removeJshintSections(text) {\n  /* Removes anything surrounded with a comment like:\n     // jshint-ignore\n     ...\n     // jshint-endignore\n\n     It replaces these with whitespace so character and line counts still work.\n  */\n  var result = '';\n  var start = /(\\/\\/|\\/\\*)\\s*jshint-ignore/i;\n  var end = /jshint-endignore\\s*(\\*\\/)?/i;\n  while (true) {\n    var match = text.search(start);\n    if (match == -1) {\n      result += text;\n      break;\n    }\n    result += text.substr(0, match);\n    text = text.substr(match);\n    match = end.exec(text);\n    if (! match) {\n      // throw everything left away.  Warn?\n      break;\n    }\n    var endPos = match.index + match[0].length;\n    var skipped = text.substr(0, endPos);\n    text = text.substr(endPos);\n    // Maintain line numbers:\n    skipped = skipped.replace(/[^\\n]/g, ' ');\n    result += skipped;\n  }\n  return result;\n}\n\n\nexports.jshint = jshint;\n\nfunction NosyXMLHttpRequest(name, req) {\n  if (this === globalObject) {\n    throw 'You forgot *new* NosyXMLHttpRequest(' + repr(name) + ')';\n  }\n  if (! name) {\n    throw 'The name argument is required';\n  }\n  if (typeof name != \"string\") {\n    throw 'Wrong type of argument for name: ' + name;\n  }\n  if (! req) {\n    req = new NosyXMLHttpRequest.realXMLHttpRequest();\n  }\n  this._name = name;\n  this._req = req;\n  this._method = null;\n  this._data = null;\n  this._url = null;\n  this._headers = {};\n  this.abort = printWrap(this._req, 'abort', this._name);\n  this.getAllResponseHeaders = this._req.getAllResponseHeaders.bind(this._req);\n  this.getResponseHeader = this._req.getResponseHeader.bind(this._req);\n  this.open = printWrap(this._req, 'open', this._name, (function (method, url) {\n    this._method = method;\n    this._url = url;\n  }).bind(this));\n  this.overrideMimeType = printWrap(this._req, 'overrideMimeType', this._name);\n  this.send = printWrap(this._req, 'send', this._name, (function (data) {\n    if (this.timeout !== undefined) {\n      this._req.timeout = this.timeout;\n    }\n    if (this.withCredentials !== undefined) {\n      this._req.withCredentials = this.withCredentials;\n    }\n    this._data = data;\n  }).bind(this));\n  this.setRequestHeader = printWrap(this._req, 'setRequestHeader', this._name, (function (name, value) {\n    this._headers[name] = value;\n  }).bind(this));\n  this.onreadystatechange = null;\n  this._req.onreadystatechange = (function () {\n    this.readyState = this._req.readyState;\n    if (this.readyState >= this.HEADERS_RECEIVED) {\n      var props = ['response', 'responseText', 'responseType',\n                   'responseXML', 'status', 'statusText', 'upload'];\n\n      for (var i=0; i<props.length; i++) {\n        this[props[i]] = this._req[props[i]];\n      }\n    }\n    if (this.onreadystatechange) {\n      this.onreadystatechange();\n    }\n  }).bind(this);\n  this.UNSENT = 0;\n  this.OPENED = 1;\n  this.HEADERS_RECEIVED = 2;\n  this.LOADING = 3;\n  this.DONE = 4;\n  this.readyState = this.UNSENT;\n  this.toString = function () {\n    var s = 'NosyXMLHttpRequest ';\n    s += {0: 'UNSENT', 1: 'OPENED', 2: 'HEADERS_RECEIVED', 3: 'LOADING', 4: 'DONE'}[this.readyState];\n    if (this._method) {\n      s += '\\n' + this._method + ' ' + this._url;\n    }\n    for (var i in this._headers) {\n      if (this._headers.hasOwnProperty(i)) {\n        s += '\\n' + i + ': ' + this._headers[i];\n      }\n    }\n    if (this._data) {\n      s += '\\n\\n' + this._data;\n    }\n    s += '\\n';\n    return s;\n  };\n}\n\nNosyXMLHttpRequest.realXMLHttpRequest = typeof XMLHttpRequest == \"undefined\" ? undefined : XMLHttpRequest;\n\nNosyXMLHttpRequest.factory = function (name) {\n  return function () {\n    return new NosyXMLHttpRequest(name);\n  };\n};\n\nexports.NosyXMLHttpRequest = NosyXMLHttpRequest;\n\nfunction printWrap(realObject, methodName, objectName, before) {\n  return function () {\n    var r = objectName + '.' + methodName + '(';\n    var length = arguments.length;\n    while (length && arguments[length-1] === undefined) {\n      length--;\n    }\n    for (var i=0; i<length; i++) {\n      if (i) {\n        r += ', ';\n      }\n      r += repr(arguments[i]);\n    }\n    r += ')';\n    print(r);\n    if (before) {\n      before.apply(realObject, arguments);\n    }\n    return realObject[methodName].apply(realObject, arguments);\n  };\n}\n\nvar positionOnFailure = null;\n\nvar attemptedHash = null;\n\nif (typeof location != 'undefined') {\n\n  (function (params) {\n    var url = location.href + '';\n    if (url.indexOf('#') != -1) {\n      url = url.substr(0, url.indexOf('#'));\n    }\n    if (url.indexOf('?') == -1) {\n      return;\n    }\n    var qs = url.substr(url.indexOf('?')+1);\n    var parts = qs.split('&');\n    for (var i=0; i<parts.length; i++) {\n      var name, value;\n      if (parts[i].indexOf('=') == -1) {\n        name = decodeURIComponent(parts[i]);\n        value = null;\n      } else {\n        name = decodeURIComponent(parts[i].substr(0, parts[i].indexOf('=')));\n        value = decodeURIComponent(parts[i].substr(parts[i].indexOf('=')+1));\n      }\n      if (params.hasOwnProperty(name)) {\n        if (params[name] === null || typeof params[name] == 'string') {\n          params[name] = [params[name], value];\n        } else {\n          params[name].push(value);\n        }\n      } else {\n        params[name] = value;\n      }\n    }\n  })(params);\n\n  if (location.hash.indexOf('#example') === 0) {\n    positionOnFailure = location.hash.substr(1);\n    location.hash = '';\n  } else if (location.hash) {\n    // Anchors get all mixed up because we move content around on the page\n    attemptedHash = location.hash;\n  }\n}\n\nif (typeof window != 'undefined') {\n  window.addEventListener('load', function () {\n    if (hasClass(doc.body, 'autodoctest')) {\n      var runner = new Runner();\n      var parser = new HTMLParser(runner);\n      parser.loadRemotes(function () {\n        runner.init();\n        parser.parse();\n        runner.run();\n      },\n      hasClass(doc.body, 'load-all-remotes') ? 'pre' : null);\n    }\n  }, false);\n}\n\n// jshint-ignore\n/* Includes a minified esprima: http://esprima.org/ */\n// Avoid clobbering:\nvar realExports = exports;\nexports = {};\n\n/* INSERT esprima.js */\n(function(root,factory){\"use strict\";if(typeof define===\"function\"&&define.amd){define([\"exports\"],factory)}else if(typeof exports!==\"undefined\"){factory(exports)}else{factory(root.esprima={})}})(this,function(exports){\"use strict\";\nvar Token,TokenName,FnExprTokens,Syntax,PropertyKind,Messages,Regex,SyntaxTreeDelegate,source,strict,index,lineNumber,lineStart,length,delegate,lookahead,state,extra;Token={BooleanLiteral:1,EOF:2,Identifier:3,Keyword:4,NullLiteral:5,NumericLiteral:6,Punctuator:7,StringLiteral:8,RegularExpression:9};\nTokenName={};TokenName[Token.BooleanLiteral]=\"Boolean\";TokenName[Token.EOF]=\"<end>\";TokenName[Token.Identifier]=\"Identifier\";TokenName[Token.Keyword]=\"Keyword\";TokenName[Token.NullLiteral]=\"Null\";TokenName[Token.NumericLiteral]=\"Numeric\";\nTokenName[Token.Punctuator]=\"Punctuator\";TokenName[Token.StringLiteral]=\"String\";TokenName[Token.RegularExpression]=\"RegularExpression\";FnExprTokens=[\"(\",\"{\",\"[\",\"in\",\"typeof\",\"instanceof\",\"new\",\"return\",\"case\",\"delete\",\"throw\",\"void\",\"=\",\"+=\",\"-=\",\"*=\",\"/=\",\"%=\",\"<<=\",\">>=\",\">>>=\",\"&=\",\"|=\",\"^=\",\",\",\"+\",\"-\",\"*\",\"/\",\"%\",\"++\",\"--\",\"<<\",\">>\",\">>>\",\"&\",\"|\",\"^\",\"!\",\"~\",\"&&\",\"||\",\"?\",\":\",\"===\",\"==\",\">=\",\"<=\",\"<\",\">\",\"!=\",\"!==\"];\nSyntax={AssignmentExpression:\"AssignmentExpression\",ArrayExpression:\"ArrayExpression\",BlockStatement:\"BlockStatement\",BinaryExpression:\"BinaryExpression\",BreakStatement:\"BreakStatement\",CallExpression:\"CallExpression\",CatchClause:\"CatchClause\",ConditionalExpression:\"ConditionalExpression\",ContinueStatement:\"ContinueStatement\",DoWhileStatement:\"DoWhileStatement\",DebuggerStatement:\"DebuggerStatement\",EmptyStatement:\"EmptyStatement\",ExpressionStatement:\"ExpressionStatement\",ForStatement:\"ForStatement\",ForInStatement:\"ForInStatement\",FunctionDeclaration:\"FunctionDeclaration\",FunctionExpression:\"FunctionExpression\",Identifier:\"Identifier\",IfStatement:\"IfStatement\",Literal:\"Literal\",LabeledStatement:\"LabeledStatement\",LogicalExpression:\"LogicalExpression\",MemberExpression:\"MemberExpression\",NewExpression:\"NewExpression\",ObjectExpression:\"ObjectExpression\",Program:\"Program\",Property:\"Property\",ReturnStatement:\"ReturnStatement\",SequenceExpression:\"SequenceExpression\",SwitchStatement:\"SwitchStatement\",SwitchCase:\"SwitchCase\",ThisExpression:\"ThisExpression\",ThrowStatement:\"ThrowStatement\",TryStatement:\"TryStatement\",UnaryExpression:\"UnaryExpression\",UpdateExpression:\"UpdateExpression\",VariableDeclaration:\"VariableDeclaration\",VariableDeclarator:\"VariableDeclarator\",WhileStatement:\"WhileStatement\",WithStatement:\"WithStatement\"};\nPropertyKind={Data:1,Get:2,Set:4};Messages={UnexpectedToken:\"Unexpected token %0\",UnexpectedNumber:\"Unexpected number\",UnexpectedString:\"Unexpected string\",UnexpectedIdentifier:\"Unexpected identifier\",UnexpectedReserved:\"Unexpected reserved word\",UnexpectedEOS:\"Unexpected end of input\",NewlineAfterThrow:\"Illegal newline after throw\",InvalidRegExp:\"Invalid regular expression\",UnterminatedRegExp:\"Invalid regular expression: missing /\",InvalidLHSInAssignment:\"Invalid left-hand side in assignment\",InvalidLHSInForIn:\"Invalid left-hand side in for-in\",MultipleDefaultsInSwitch:\"More than one default clause in switch statement\",NoCatchOrFinally:\"Missing catch or finally after try\",UnknownLabel:\"Undefined label '%0'\",Redeclaration:\"%0 '%1' has already been declared\",IllegalContinue:\"Illegal continue statement\",IllegalBreak:\"Illegal break statement\",IllegalReturn:\"Illegal return statement\",StrictModeWith:\"Strict mode code may not include a with statement\",StrictCatchVariable:\"Catch variable may not be eval or arguments in strict mode\",StrictVarName:\"Variable name may not be eval or arguments in strict mode\",StrictParamName:\"Parameter name eval or arguments is not allowed in strict mode\",StrictParamDupe:\"Strict mode function may not have duplicate parameter names\",StrictFunctionName:\"Function name may not be eval or arguments in strict mode\",StrictOctalLiteral:\"Octal literals are not allowed in strict mode.\",StrictDelete:\"Delete of an unqualified identifier in strict mode.\",StrictDuplicateProperty:\"Duplicate data property in object literal not allowed in strict mode\",AccessorDataProperty:\"Object literal may not have data and accessor property with the same name\",AccessorGetSet:\"Object literal may not have multiple get/set accessors with the same name\",StrictLHSAssignment:\"Assignment to eval or arguments is not allowed in strict mode\",StrictLHSPostfix:\"Postfix increment/decrement may not have eval or arguments operand in strict mode\",StrictLHSPrefix:\"Prefix increment/decrement may not have eval or arguments operand in strict mode\",StrictReservedWord:\"Use of future reserved word in strict mode\"};\nRegex={NonAsciiIdentifierStart:new RegExp(\"[\\u00aa\\u00b5\\u00ba\\u00c0-\\u00d6\\u00d8-\\u00f6\\u00f8-\\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]\"),NonAsciiIdentifierPart:new RegExp(\"[\\u00aa\\u00b5\\u00ba\\u00c0-\\u00d6\\u00d8-\\u00f6\\u00f8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0300-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u0483-\\u0487\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0610-\\u061a\\u0620-\\u0669\\u066e-\\u06d3\\u06d5-\\u06dc\\u06df-\\u06e8\\u06ea-\\u06fc\\u06ff\\u0710-\\u074a\\u074d-\\u07b1\\u07c0-\\u07f5\\u07fa\\u0800-\\u082d\\u0840-\\u085b\\u08a0\\u08a2-\\u08ac\\u08e4-\\u08fe\\u0900-\\u0963\\u0966-\\u096f\\u0971-\\u0977\\u0979-\\u097f\\u0981-\\u0983\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bc-\\u09c4\\u09c7\\u09c8\\u09cb-\\u09ce\\u09d7\\u09dc\\u09dd\\u09df-\\u09e3\\u09e6-\\u09f1\\u0a01-\\u0a03\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a59-\\u0a5c\\u0a5e\\u0a66-\\u0a75\\u0a81-\\u0a83\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abc-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ad0\\u0ae0-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3c-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5c\\u0b5d\\u0b5f-\\u0b63\\u0b66-\\u0b6f\\u0b71\\u0b82\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd0\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d-\\u0c44\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c58\\u0c59\\u0c60-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbc-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0cde\\u0ce0-\\u0ce3\\u0ce6-\\u0cef\\u0cf1\\u0cf2\\u0d02\\u0d03\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d-\\u0d44\\u0d46-\\u0d48\\u0d4a-\\u0d4e\\u0d57\\u0d60-\\u0d63\\u0d66-\\u0d6f\\u0d7a-\\u0d7f\\u0d82\\u0d83\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e01-\\u0e3a\\u0e40-\\u0e4e\\u0e50-\\u0e59\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb9\\u0ebb-\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0edc-\\u0edf\\u0f00\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f3e-\\u0f47\\u0f49-\\u0f6c\\u0f71-\\u0f84\\u0f86-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1049\\u1050-\\u109d\\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\\u135d-\\u135f\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176c\\u176e-\\u1770\\u1772\\u1773\\u1780-\\u17d3\\u17d7\\u17dc\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1920-\\u192b\\u1930-\\u193b\\u1946-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19b0-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a1b\\u1a20-\\u1a5e\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1aa7\\u1b00-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1b80-\\u1bf3\\u1c00-\\u1c37\\u1c40-\\u1c49\\u1c4d-\\u1c7d\\u1cd0-\\u1cd2\\u1cd4-\\u1cf6\\u1d00-\\u1de6\\u1dfc-\\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\\u200c\\u200d\\u203f\\u2040\\u2054\\u2071\\u207f\\u2090-\\u209c\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\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-\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d7f-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2de0-\\u2dff\\u2e2f\\u3005-\\u3007\\u3021-\\u302f\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u3099\\u309a\\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-\\ua62b\\ua640-\\ua66f\\ua674-\\ua67d\\ua67f-\\ua697\\ua69f-\\ua6f1\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua827\\ua840-\\ua873\\ua880-\\ua8c4\\ua8d0-\\ua8d9\\ua8e0-\\ua8f7\\ua8fb\\ua900-\\ua92d\\ua930-\\ua953\\ua960-\\ua97c\\ua980-\\ua9c0\\ua9cf-\\ua9d9\\uaa00-\\uaa36\\uaa40-\\uaa4d\\uaa50-\\uaa59\\uaa60-\\uaa76\\uaa7a\\uaa7b\\uaa80-\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaef\\uaaf2-\\uaaf6\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabea\\uabec\\uabed\\uabf0-\\uabf9\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff10-\\uff19\\uff21-\\uff3a\\uff3f\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc]\")};\nfunction assert(condition,message){if(!condition){throw new Error(\"ASSERT: \"+message)}}function isDecimalDigit(ch){return ch>=48&&ch<=57}function isHexDigit(ch){return\"0123456789abcdefABCDEF\".indexOf(ch)>=0\n}function isOctalDigit(ch){return\"01234567\".indexOf(ch)>=0}function isWhiteSpace(ch){return ch===32||ch===9||ch===11||ch===12||ch===160||ch>=5760&&\"\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\ufeff\".indexOf(String.fromCharCode(ch))>0\n}function isLineTerminator(ch){return ch===10||ch===13||ch===8232||ch===8233}function isIdentifierStart(ch){return ch===36||ch===95||ch>=65&&ch<=90||ch>=97&&ch<=122||ch===92||ch>=128&&Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))\n}function isIdentifierPart(ch){return ch===36||ch===95||ch>=65&&ch<=90||ch>=97&&ch<=122||ch>=48&&ch<=57||ch===92||ch>=128&&Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))}function isFutureReservedWord(id){switch(id){case\"class\":case\"enum\":case\"export\":case\"extends\":case\"import\":case\"super\":return true;\ndefault:return false}}function isStrictModeReservedWord(id){switch(id){case\"implements\":case\"interface\":case\"package\":case\"private\":case\"protected\":case\"public\":case\"static\":case\"yield\":case\"let\":return true;\ndefault:return false}}function isRestrictedWord(id){return id===\"eval\"||id===\"arguments\"}function isKeyword(id){if(strict&&isStrictModeReservedWord(id)){return true}switch(id.length){case 2:return id===\"if\"||id===\"in\"||id===\"do\";\ncase 3:return id===\"var\"||id===\"for\"||id===\"new\"||id===\"try\"||id===\"let\";case 4:return id===\"this\"||id===\"else\"||id===\"case\"||id===\"void\"||id===\"with\"||id===\"enum\";case 5:return id===\"while\"||id===\"break\"||id===\"catch\"||id===\"throw\"||id===\"const\"||id===\"yield\"||id===\"class\"||id===\"super\";\ncase 6:return id===\"return\"||id===\"typeof\"||id===\"delete\"||id===\"switch\"||id===\"export\"||id===\"import\";case 7:return id===\"default\"||id===\"finally\"||id===\"extends\";case 8:return id===\"function\"||id===\"continue\"||id===\"debugger\";\ncase 10:return id===\"instanceof\";default:return false}}function skipComment(){var ch,blockComment,lineComment;blockComment=false;lineComment=false;while(index<length){ch=source.charCodeAt(index);if(lineComment){++index;\nif(isLineTerminator(ch)){lineComment=false;if(ch===13&&source.charCodeAt(index)===10){++index}++lineNumber;lineStart=index}}else if(blockComment){if(isLineTerminator(ch)){if(ch===13&&source.charCodeAt(index+1)===10){++index\n}++lineNumber;++index;lineStart=index;if(index>=length){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}}else{ch=source.charCodeAt(index++);if(index>=length){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")\n}if(ch===42){ch=source.charCodeAt(index);if(ch===47){++index;blockComment=false}}}}else if(ch===47){ch=source.charCodeAt(index+1);if(ch===47){index+=2;lineComment=true}else if(ch===42){index+=2;blockComment=true;\nif(index>=length){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}}else{break}}else if(isWhiteSpace(ch)){++index}else if(isLineTerminator(ch)){++index;if(ch===13&&source.charCodeAt(index)===10){++index\n}++lineNumber;lineStart=index}else{break}}}function scanHexEscape(prefix){var i,len,ch,code=0;len=prefix===\"u\"?4:2;for(i=0;i<len;++i){if(index<length&&isHexDigit(source[index])){ch=source[index++];code=code*16+\"0123456789abcdef\".indexOf(ch.toLowerCase())\n}else{return\"\"}}return String.fromCharCode(code)}function getEscapedIdentifier(){var ch,id;ch=source.charCodeAt(index++);id=String.fromCharCode(ch);if(ch===92){if(source.charCodeAt(index)!==117){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")\n}++index;ch=scanHexEscape(\"u\");if(!ch||ch===\"\\\\\"||!isIdentifierStart(ch.charCodeAt(0))){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}id=ch}while(index<length){ch=source.charCodeAt(index);if(!isIdentifierPart(ch)){break\n}++index;id+=String.fromCharCode(ch);if(ch===92){id=id.substr(0,id.length-1);if(source.charCodeAt(index)!==117){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}++index;ch=scanHexEscape(\"u\");if(!ch||ch===\"\\\\\"||!isIdentifierPart(ch.charCodeAt(0))){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")\n}id+=ch}}return id}function getIdentifier(){var start,ch;start=index++;while(index<length){ch=source.charCodeAt(index);if(ch===92){index=start;return getEscapedIdentifier()}if(isIdentifierPart(ch)){++index\n}else{break}}return source.slice(start,index)}function scanIdentifier(){var start,id,type;start=index;id=source.charCodeAt(index)===92?getEscapedIdentifier():getIdentifier();if(id.length===1){type=Token.Identifier\n}else if(isKeyword(id)){type=Token.Keyword}else if(id===\"null\"){type=Token.NullLiteral}else if(id===\"true\"||id===\"false\"){type=Token.BooleanLiteral}else{type=Token.Identifier}return{type:type,value:id,lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}\n}function scanPunctuator(){var start=index,code=source.charCodeAt(index),code2,ch1=source[index],ch2,ch3,ch4;switch(code){case 46:case 40:case 41:case 59:case 44:case 123:case 125:case 91:case 93:case 58:case 63:case 126:++index;\nif(extra.tokenize){if(code===40){extra.openParenToken=extra.tokens.length}else if(code===123){extra.openCurlyToken=extra.tokens.length}}return{type:Token.Punctuator,value:String.fromCharCode(code),lineNumber:lineNumber,lineStart:lineStart,range:[start,index]};\ndefault:code2=source.charCodeAt(index+1);if(code2===61){switch(code){case 37:case 38:case 42:case 43:case 45:case 47:case 60:case 62:case 94:case 124:index+=2;return{type:Token.Punctuator,value:String.fromCharCode(code)+String.fromCharCode(code2),lineNumber:lineNumber,lineStart:lineStart,range:[start,index]};\ncase 33:case 61:index+=2;if(source.charCodeAt(index)===61){++index}return{type:Token.Punctuator,value:source.slice(start,index),lineNumber:lineNumber,lineStart:lineStart,range:[start,index]};default:break\n}}break}ch2=source[index+1];ch3=source[index+2];ch4=source[index+3];if(ch1===\">\"&&ch2===\">\"&&ch3===\">\"){if(ch4===\"=\"){index+=4;return{type:Token.Punctuator,value:\">>>=\",lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}\n}}if(ch1===\">\"&&ch2===\">\"&&ch3===\">\"){index+=3;return{type:Token.Punctuator,value:\">>>\",lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}}if(ch1===\"<\"&&ch2===\"<\"&&ch3===\"=\"){index+=3;return{type:Token.Punctuator,value:\"<<=\",lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}\n}if(ch1===\">\"&&ch2===\">\"&&ch3===\"=\"){index+=3;return{type:Token.Punctuator,value:\">>=\",lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}}if(ch1===ch2&&\"+-<>&|\".indexOf(ch1)>=0){index+=2;return{type:Token.Punctuator,value:ch1+ch2,lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}\n}if(\"<>=!+-*%&|^/\".indexOf(ch1)>=0){++index;return{type:Token.Punctuator,value:ch1,lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}}throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}function scanHexLiteral(start){var number=\"\";\nwhile(index<length){if(!isHexDigit(source[index])){break}number+=source[index++]}if(number.length===0){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}if(isIdentifierStart(source.charCodeAt(index))){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")\n}return{type:Token.NumericLiteral,value:parseInt(\"0x\"+number,16),lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}}function scanOctalLiteral(start){var number=\"0\"+source[index++];while(index<length){if(!isOctalDigit(source[index])){break\n}number+=source[index++]}if(isIdentifierStart(source.charCodeAt(index))||isDecimalDigit(source.charCodeAt(index))){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}return{type:Token.NumericLiteral,value:parseInt(number,8),octal:true,lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}\n}function scanNumericLiteral(){var number,start,ch;ch=source[index];assert(isDecimalDigit(ch.charCodeAt(0))||ch===\".\",\"Numeric literal must start with a decimal digit or a decimal point\");start=index;number=\"\";\nif(ch!==\".\"){number=source[index++];ch=source[index];if(number===\"0\"){if(ch===\"x\"||ch===\"X\"){++index;return scanHexLiteral(start)}if(isOctalDigit(ch)){return scanOctalLiteral(start)}if(ch&&isDecimalDigit(ch.charCodeAt(0))){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")\n}}while(isDecimalDigit(source.charCodeAt(index))){number+=source[index++]}ch=source[index]}if(ch===\".\"){number+=source[index++];while(isDecimalDigit(source.charCodeAt(index))){number+=source[index++]}ch=source[index]\n}if(ch===\"e\"||ch===\"E\"){number+=source[index++];ch=source[index];if(ch===\"+\"||ch===\"-\"){number+=source[index++]}if(isDecimalDigit(source.charCodeAt(index))){while(isDecimalDigit(source.charCodeAt(index))){number+=source[index++]\n}}else{throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}}if(isIdentifierStart(source.charCodeAt(index))){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}return{type:Token.NumericLiteral,value:parseFloat(number),lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}\n}function scanStringLiteral(){var str=\"\",quote,start,ch,code,unescaped,restore,octal=false;quote=source[index];assert(quote===\"'\"||quote==='\"',\"String literal must starts with a quote\");start=index;++index;\nwhile(index<length){ch=source[index++];if(ch===quote){quote=\"\";break}else if(ch===\"\\\\\"){ch=source[index++];if(!ch||!isLineTerminator(ch.charCodeAt(0))){switch(ch){case\"n\":str+=\"\\n\";break;case\"r\":str+=\"\\r\";\nbreak;case\"t\":str+=\"\t\";break;case\"u\":case\"x\":restore=index;unescaped=scanHexEscape(ch);if(unescaped){str+=unescaped}else{index=restore;str+=ch}break;case\"b\":str+=\"\\b\";break;case\"f\":str+=\"\\f\";break;case\"v\":str+=\"\u000b\";\nbreak;default:if(isOctalDigit(ch)){code=\"01234567\".indexOf(ch);if(code!==0){octal=true}if(index<length&&isOctalDigit(source[index])){octal=true;code=code*8+\"01234567\".indexOf(source[index++]);if(\"0123\".indexOf(ch)>=0&&index<length&&isOctalDigit(source[index])){code=code*8+\"01234567\".indexOf(source[index++])\n}}str+=String.fromCharCode(code)}else{str+=ch}break}}else{++lineNumber;if(ch===\"\\r\"&&source[index]===\"\\n\"){++index}}}else if(isLineTerminator(ch.charCodeAt(0))){break}else{str+=ch}}if(quote!==\"\"){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")\n}return{type:Token.StringLiteral,value:str,octal:octal,lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}}function scanRegExp(){var str,ch,start,pattern,flags,value,classMarker=false,restore,terminated=false;\nlookahead=null;skipComment();start=index;ch=source[index];assert(ch===\"/\",\"Regular expression literal must start with a slash\");str=source[index++];while(index<length){ch=source[index++];str+=ch;if(classMarker){if(ch===\"]\"){classMarker=false\n}}else{if(ch===\"\\\\\"){ch=source[index++];if(isLineTerminator(ch.charCodeAt(0))){throwError({},Messages.UnterminatedRegExp)}str+=ch}else if(ch===\"/\"){terminated=true;break}else if(ch===\"[\"){classMarker=true\n}else if(isLineTerminator(ch.charCodeAt(0))){throwError({},Messages.UnterminatedRegExp)}}}if(!terminated){throwError({},Messages.UnterminatedRegExp)}pattern=str.substr(1,str.length-2);flags=\"\";while(index<length){ch=source[index];\nif(!isIdentifierPart(ch.charCodeAt(0))){break}++index;if(ch===\"\\\\\"&&index<length){ch=source[index];if(ch===\"u\"){++index;restore=index;ch=scanHexEscape(\"u\");if(ch){flags+=ch;for(str+=\"\\\\u\";restore<index;++restore){str+=source[restore]\n}}else{index=restore;flags+=\"u\";str+=\"\\\\u\"}}else{str+=\"\\\\\"}}else{flags+=ch;str+=ch}}try{value=new RegExp(pattern,flags)}catch(e){throwError({},Messages.InvalidRegExp)}peek();if(extra.tokenize){return{type:Token.RegularExpression,value:value,lineNumber:lineNumber,lineStart:lineStart,range:[start,index]}\n}return{literal:str,value:value,range:[start,index]}}function isIdentifierName(token){return token.type===Token.Identifier||token.type===Token.Keyword||token.type===Token.BooleanLiteral||token.type===Token.NullLiteral\n}function advanceSlash(){var prevToken,checkToken;prevToken=extra.tokens[extra.tokens.length-1];if(!prevToken){return scanRegExp()}if(prevToken.type===\"Punctuator\"){if(prevToken.value===\")\"){checkToken=extra.tokens[extra.openParenToken-1];\nif(checkToken&&checkToken.type===\"Keyword\"&&(checkToken.value===\"if\"||checkToken.value===\"while\"||checkToken.value===\"for\"||checkToken.value===\"with\")){return scanRegExp()}return scanPunctuator()}if(prevToken.value===\"}\"){if(extra.tokens[extra.openCurlyToken-3]&&extra.tokens[extra.openCurlyToken-3].type===\"Keyword\"){checkToken=extra.tokens[extra.openCurlyToken-4];\nif(!checkToken){return scanPunctuator()}}else if(extra.tokens[extra.openCurlyToken-4]&&extra.tokens[extra.openCurlyToken-4].type===\"Keyword\"){checkToken=extra.tokens[extra.openCurlyToken-5];if(!checkToken){return scanRegExp()\n}}else{return scanPunctuator()}if(FnExprTokens.indexOf(checkToken.value)>=0){return scanPunctuator()}return scanRegExp()}return scanRegExp()}if(prevToken.type===\"Keyword\"){return scanRegExp()}return scanPunctuator()\n}function advance(){var ch;skipComment();if(index>=length){return{type:Token.EOF,lineNumber:lineNumber,lineStart:lineStart,range:[index,index]}}ch=source.charCodeAt(index);if(ch===40||ch===41||ch===58){return scanPunctuator()\n}if(ch===39||ch===34){return scanStringLiteral()}if(isIdentifierStart(ch)){return scanIdentifier()}if(ch===46){if(isDecimalDigit(source.charCodeAt(index+1))){return scanNumericLiteral()}return scanPunctuator()\n}if(isDecimalDigit(ch)){return scanNumericLiteral()}if(extra.tokenize&&ch===47){return advanceSlash()}return scanPunctuator()}function lex(){var token;token=lookahead;index=token.range[1];lineNumber=token.lineNumber;\nlineStart=token.lineStart;lookahead=advance();index=token.range[1];lineNumber=token.lineNumber;lineStart=token.lineStart;return token}function peek(){var pos,line,start;pos=index;line=lineNumber;start=lineStart;\nlookahead=advance();index=pos;lineNumber=line;lineStart=start}SyntaxTreeDelegate={name:\"SyntaxTree\",markStart:function(){},markEnd:function(node){return node},markGroupEnd:function(node){return node},postProcess:function(node){return node\n},createArrayExpression:function(elements){return{type:Syntax.ArrayExpression,elements:elements}},createAssignmentExpression:function(operator,left,right){return{type:Syntax.AssignmentExpression,operator:operator,left:left,right:right}\n},createBinaryExpression:function(operator,left,right){var type=operator===\"||\"||operator===\"&&\"?Syntax.LogicalExpression:Syntax.BinaryExpression;return{type:type,operator:operator,left:left,right:right}\n},createBlockStatement:function(body){return{type:Syntax.BlockStatement,body:body}},createBreakStatement:function(label){return{type:Syntax.BreakStatement,label:label}},createCallExpression:function(callee,args){return{type:Syntax.CallExpression,callee:callee,arguments:args}\n},createCatchClause:function(param,body){return{type:Syntax.CatchClause,param:param,body:body}},createConditionalExpression:function(test,consequent,alternate){return{type:Syntax.ConditionalExpression,test:test,consequent:consequent,alternate:alternate}\n},createContinueStatement:function(label){return{type:Syntax.ContinueStatement,label:label}},createDebuggerStatement:function(){return{type:Syntax.DebuggerStatement}},createDoWhileStatement:function(body,test){return{type:Syntax.DoWhileStatement,body:body,test:test}\n},createEmptyStatement:function(){return{type:Syntax.EmptyStatement}},createExpressionStatement:function(expression){return{type:Syntax.ExpressionStatement,expression:expression}},createForStatement:function(init,test,update,body){return{type:Syntax.ForStatement,init:init,test:test,update:update,body:body}\n},createForInStatement:function(left,right,body){return{type:Syntax.ForInStatement,left:left,right:right,body:body,each:false}},createFunctionDeclaration:function(id,params,defaults,body){return{type:Syntax.FunctionDeclaration,id:id,params:params,defaults:defaults,body:body,rest:null,generator:false,expression:false}\n},createFunctionExpression:function(id,params,defaults,body){return{type:Syntax.FunctionExpression,id:id,params:params,defaults:defaults,body:body,rest:null,generator:false,expression:false}},createIdentifier:function(name){return{type:Syntax.Identifier,name:name}\n},createIfStatement:function(test,consequent,alternate){return{type:Syntax.IfStatement,test:test,consequent:consequent,alternate:alternate}},createLabeledStatement:function(label,body){return{type:Syntax.LabeledStatement,label:label,body:body}\n},createLiteral:function(token){return{type:Syntax.Literal,value:token.value,raw:source.slice(token.range[0],token.range[1])}},createMemberExpression:function(accessor,object,property){return{type:Syntax.MemberExpression,computed:accessor===\"[\",object:object,property:property}\n},createNewExpression:function(callee,args){return{type:Syntax.NewExpression,callee:callee,arguments:args}},createObjectExpression:function(properties){return{type:Syntax.ObjectExpression,properties:properties}\n},createPostfixExpression:function(operator,argument){return{type:Syntax.UpdateExpression,operator:operator,argument:argument,prefix:false}},createProgram:function(body){return{type:Syntax.Program,body:body}\n},createProperty:function(kind,key,value){return{type:Syntax.Property,key:key,value:value,kind:kind}},createReturnStatement:function(argument){return{type:Syntax.ReturnStatement,argument:argument}},createSequenceExpression:function(expressions){return{type:Syntax.SequenceExpression,expressions:expressions}\n},createSwitchCase:function(test,consequent){return{type:Syntax.SwitchCase,test:test,consequent:consequent}},createSwitchStatement:function(discriminant,cases){return{type:Syntax.SwitchStatement,discriminant:discriminant,cases:cases}\n},createThisExpression:function(){return{type:Syntax.ThisExpression}},createThrowStatement:function(argument){return{type:Syntax.ThrowStatement,argument:argument}},createTryStatement:function(block,guardedHandlers,handlers,finalizer){return{type:Syntax.TryStatement,block:block,guardedHandlers:guardedHandlers,handlers:handlers,finalizer:finalizer}\n},createUnaryExpression:function(operator,argument){if(operator===\"++\"||operator===\"--\"){return{type:Syntax.UpdateExpression,operator:operator,argument:argument,prefix:true}}return{type:Syntax.UnaryExpression,operator:operator,argument:argument}\n},createVariableDeclaration:function(declarations,kind){return{type:Syntax.VariableDeclaration,declarations:declarations,kind:kind}},createVariableDeclarator:function(id,init){return{type:Syntax.VariableDeclarator,id:id,init:init}\n},createWhileStatement:function(test,body){return{type:Syntax.WhileStatement,test:test,body:body}},createWithStatement:function(object,body){return{type:Syntax.WithStatement,object:object,body:body}}};\nfunction peekLineTerminator(){var pos,line,start,found;pos=index;line=lineNumber;start=lineStart;skipComment();found=lineNumber!==line;index=pos;lineNumber=line;lineStart=start;return found}function throwError(token,messageFormat){var error,args=Array.prototype.slice.call(arguments,2),msg=messageFormat.replace(/%(\\d)/g,function(whole,index){assert(index<args.length,\"Message reference must be in range\");\nreturn args[index]});if(typeof token.lineNumber===\"number\"){error=new Error(\"Line \"+token.lineNumber+\": \"+msg);error.index=token.range[0];error.lineNumber=token.lineNumber;error.column=token.range[0]-lineStart+1\n}else{error=new Error(\"Line \"+lineNumber+\": \"+msg);error.index=index;error.lineNumber=lineNumber;error.column=index-lineStart+1}error.description=msg;throw error}function throwErrorTolerant(){try{throwError.apply(null,arguments)\n}catch(e){if(extra.errors){extra.errors.push(e)}else{throw e}}}function throwUnexpected(token){if(token.type===Token.EOF){throwError(token,Messages.UnexpectedEOS)}if(token.type===Token.NumericLiteral){throwError(token,Messages.UnexpectedNumber)\n}if(token.type===Token.StringLiteral){throwError(token,Messages.UnexpectedString)}if(token.type===Token.Identifier){throwError(token,Messages.UnexpectedIdentifier)}if(token.type===Token.Keyword){if(isFutureReservedWord(token.value)){throwError(token,Messages.UnexpectedReserved)\n}else if(strict&&isStrictModeReservedWord(token.value)){throwErrorTolerant(token,Messages.StrictReservedWord);return}throwError(token,Messages.UnexpectedToken,token.value)}throwError(token,Messages.UnexpectedToken,token.value)\n}function expect(value){var token=lex();if(token.type!==Token.Punctuator||token.value!==value){throwUnexpected(token)}}function expectKeyword(keyword){var token=lex();if(token.type!==Token.Keyword||token.value!==keyword){throwUnexpected(token)\n}}function match(value){return lookahead.type===Token.Punctuator&&lookahead.value===value}function matchKeyword(keyword){return lookahead.type===Token.Keyword&&lookahead.value===keyword}function matchAssign(){var op;\nif(lookahead.type!==Token.Punctuator){return false}op=lookahead.value;return op===\"=\"||op===\"*=\"||op===\"/=\"||op===\"%=\"||op===\"+=\"||op===\"-=\"||op===\"<<=\"||op===\">>=\"||op===\">>>=\"||op===\"&=\"||op===\"^=\"||op===\"|=\"\n}function consumeSemicolon(){var line;if(source.charCodeAt(index)===59){lex();return}line=lineNumber;skipComment();if(lineNumber!==line){return}if(match(\";\")){lex();return}if(lookahead.type!==Token.EOF&&!match(\"}\")){throwUnexpected(lookahead)\n}}function isLeftHandSide(expr){return expr.type===Syntax.Identifier||expr.type===Syntax.MemberExpression}function parseArrayInitialiser(){var elements=[];expect(\"[\");while(!match(\"]\")){if(match(\",\")){lex();\nelements.push(null)}else{elements.push(parseAssignmentExpression());if(!match(\"]\")){expect(\",\")}}}expect(\"]\");return delegate.createArrayExpression(elements)}function parsePropertyFunction(param,first){var previousStrict,body;\npreviousStrict=strict;delegate.markStart();body=parseFunctionSourceElements();if(first&&strict&&isRestrictedWord(param[0].name)){throwErrorTolerant(first,Messages.StrictParamName)}strict=previousStrict;\nreturn delegate.markEnd(delegate.createFunctionExpression(null,param,[],body))}function parseObjectPropertyKey(){var token;delegate.markStart();token=lex();if(token.type===Token.StringLiteral||token.type===Token.NumericLiteral){if(strict&&token.octal){throwErrorTolerant(token,Messages.StrictOctalLiteral)\n}return delegate.markEnd(delegate.createLiteral(token))}return delegate.markEnd(delegate.createIdentifier(token.value))}function parseObjectProperty(){var token,key,id,value,param;token=lookahead;delegate.markStart();\nif(token.type===Token.Identifier){id=parseObjectPropertyKey();if(token.value===\"get\"&&!match(\":\")){key=parseObjectPropertyKey();expect(\"(\");expect(\")\");value=parsePropertyFunction([]);return delegate.markEnd(delegate.createProperty(\"get\",key,value))\n}if(token.value===\"set\"&&!match(\":\")){key=parseObjectPropertyKey();expect(\"(\");token=lookahead;if(token.type!==Token.Identifier){throwUnexpected(lex())}param=[parseVariableIdentifier()];expect(\")\");value=parsePropertyFunction(param,token);\nreturn delegate.markEnd(delegate.createProperty(\"set\",key,value))}expect(\":\");value=parseAssignmentExpression();return delegate.markEnd(delegate.createProperty(\"init\",id,value))}if(token.type===Token.EOF||token.type===Token.Punctuator){throwUnexpected(token)\n}else{key=parseObjectPropertyKey();expect(\":\");value=parseAssignmentExpression();return delegate.markEnd(delegate.createProperty(\"init\",key,value))}}function parseObjectInitialiser(){var properties=[],property,name,key,kind,map={},toString=String;\nexpect(\"{\");while(!match(\"}\")){property=parseObjectProperty();if(property.key.type===Syntax.Identifier){name=property.key.name}else{name=toString(property.key.value)}kind=property.kind===\"init\"?PropertyKind.Data:property.kind===\"get\"?PropertyKind.Get:PropertyKind.Set;\nkey=\"$\"+name;if(Object.prototype.hasOwnProperty.call(map,key)){if(map[key]===PropertyKind.Data){if(strict&&kind===PropertyKind.Data){throwErrorTolerant({},Messages.StrictDuplicateProperty)}else if(kind!==PropertyKind.Data){throwErrorTolerant({},Messages.AccessorDataProperty)\n}}else{if(kind===PropertyKind.Data){throwErrorTolerant({},Messages.AccessorDataProperty)}else if(map[key]&kind){throwErrorTolerant({},Messages.AccessorGetSet)}}map[key]|=kind}else{map[key]=kind}properties.push(property);\nif(!match(\"}\")){expect(\",\")}}expect(\"}\");return delegate.createObjectExpression(properties)}function parseGroupExpression(){var expr;delegate.markStart();expect(\"(\");expr=parseExpression();expect(\")\");\nreturn delegate.markGroupEnd(expr)}function parsePrimaryExpression(){var type,token,expr;if(match(\"(\")){return parseGroupExpression()}type=lookahead.type;delegate.markStart();if(type===Token.Identifier){expr=delegate.createIdentifier(lex().value)\n}else if(type===Token.StringLiteral||type===Token.NumericLiteral){if(strict&&lookahead.octal){throwErrorTolerant(lookahead,Messages.StrictOctalLiteral)}expr=delegate.createLiteral(lex())}else if(type===Token.Keyword){if(matchKeyword(\"this\")){lex();\nexpr=delegate.createThisExpression()}else if(matchKeyword(\"function\")){expr=parseFunctionExpression()}}else if(type===Token.BooleanLiteral){token=lex();token.value=token.value===\"true\";expr=delegate.createLiteral(token)\n}else if(type===Token.NullLiteral){token=lex();token.value=null;expr=delegate.createLiteral(token)}else if(match(\"[\")){expr=parseArrayInitialiser()}else if(match(\"{\")){expr=parseObjectInitialiser()}else if(match(\"/\")||match(\"/=\")){expr=delegate.createLiteral(scanRegExp())\n}if(expr){return delegate.markEnd(expr)}throwUnexpected(lex())}function parseArguments(){var args=[];expect(\"(\");if(!match(\")\")){while(index<length){args.push(parseAssignmentExpression());if(match(\")\")){break\n}expect(\",\")}}expect(\")\");return args}function parseNonComputedProperty(){var token;delegate.markStart();token=lex();if(!isIdentifierName(token)){throwUnexpected(token)}return delegate.markEnd(delegate.createIdentifier(token.value))\n}function parseNonComputedMember(){expect(\".\");return parseNonComputedProperty()}function parseComputedMember(){var expr;expect(\"[\");expr=parseExpression();expect(\"]\");return expr}function parseNewExpression(){var callee,args;\ndelegate.markStart();expectKeyword(\"new\");callee=parseLeftHandSideExpression();args=match(\"(\")?parseArguments():[];return delegate.markEnd(delegate.createNewExpression(callee,args))}function parseLeftHandSideExpressionAllowCall(){var marker,expr,args,property;\nmarker=createLocationMarker();expr=matchKeyword(\"new\")?parseNewExpression():parsePrimaryExpression();while(match(\".\")||match(\"[\")||match(\"(\")){if(match(\"(\")){args=parseArguments();expr=delegate.createCallExpression(expr,args)\n}else if(match(\"[\")){property=parseComputedMember();expr=delegate.createMemberExpression(\"[\",expr,property)}else{property=parseNonComputedMember();expr=delegate.createMemberExpression(\".\",expr,property)\n}if(marker){marker.end();marker.apply(expr)}}return expr}function parseLeftHandSideExpression(){var marker,expr,property;marker=createLocationMarker();expr=matchKeyword(\"new\")?parseNewExpression():parsePrimaryExpression();\nwhile(match(\".\")||match(\"[\")){if(match(\"[\")){property=parseComputedMember();expr=delegate.createMemberExpression(\"[\",expr,property)}else{property=parseNonComputedMember();expr=delegate.createMemberExpression(\".\",expr,property)\n}if(marker){marker.end();marker.apply(expr)}}return expr}function parsePostfixExpression(){var marker,expr,token;marker=createLocationMarker();expr=parseLeftHandSideExpressionAllowCall();if(lookahead.type===Token.Punctuator){if((match(\"++\")||match(\"--\"))&&!peekLineTerminator()){if(strict&&expr.type===Syntax.Identifier&&isRestrictedWord(expr.name)){throwErrorTolerant({},Messages.StrictLHSPostfix)\n}if(!isLeftHandSide(expr)){throwError({},Messages.InvalidLHSInAssignment)}token=lex();expr=delegate.createPostfixExpression(token.value,expr)}}if(marker){marker.end();return marker.applyIf(expr)}return expr\n}function parseUnaryExpression(){var marker,token,expr;marker=createLocationMarker();if(lookahead.type!==Token.Punctuator&&lookahead.type!==Token.Keyword){expr=parsePostfixExpression()}else if(match(\"++\")||match(\"--\")){token=lex();\nexpr=parseUnaryExpression();if(strict&&expr.type===Syntax.Identifier&&isRestrictedWord(expr.name)){throwErrorTolerant({},Messages.StrictLHSPrefix)}if(!isLeftHandSide(expr)){throwError({},Messages.InvalidLHSInAssignment)\n}expr=delegate.createUnaryExpression(token.value,expr)}else if(match(\"+\")||match(\"-\")||match(\"~\")||match(\"!\")){token=lex();expr=parseUnaryExpression();expr=delegate.createUnaryExpression(token.value,expr)\n}else if(matchKeyword(\"delete\")||matchKeyword(\"void\")||matchKeyword(\"typeof\")){token=lex();expr=parseUnaryExpression();expr=delegate.createUnaryExpression(token.value,expr);if(strict&&expr.operator===\"delete\"&&expr.argument.type===Syntax.Identifier){throwErrorTolerant({},Messages.StrictDelete)\n}}else{expr=parsePostfixExpression()}if(marker){marker.end();expr=marker.applyIf(expr)}return expr}function binaryPrecedence(token,allowIn){var prec=0;if(token.type!==Token.Punctuator&&token.type!==Token.Keyword){return 0\n}switch(token.value){case\"||\":prec=1;break;case\"&&\":prec=2;break;case\"|\":prec=3;break;case\"^\":prec=4;break;case\"&\":prec=5;break;case\"==\":case\"!=\":case\"===\":case\"!==\":prec=6;break;case\"<\":case\">\":case\"<=\":case\">=\":case\"instanceof\":prec=7;\nbreak;case\"in\":prec=allowIn?7:0;break;case\"<<\":case\">>\":case\">>>\":prec=8;break;case\"+\":case\"-\":prec=9;break;case\"*\":case\"/\":case\"%\":prec=11;break;default:break}return prec}function parseBinaryExpression(){var expr,token,prec,previousAllowIn,stack,right,operator,left,i;\npreviousAllowIn=state.allowIn;state.allowIn=true;expr=parseUnaryExpression();token=lookahead;prec=binaryPrecedence(token,previousAllowIn);if(prec===0){return expr}token.prec=prec;lex();stack=[expr,token,parseUnaryExpression()];\nwhile((prec=binaryPrecedence(lookahead,previousAllowIn))>0){while(stack.length>2&&prec<=stack[stack.length-2].prec){right=stack.pop();operator=stack.pop().value;left=stack.pop();stack.push(delegate.createBinaryExpression(operator,left,right))\n}token=lex();token.prec=prec;stack.push(token);stack.push(parseUnaryExpression())}state.allowIn=previousAllowIn;i=stack.length-1;expr=stack[i];while(i>1){expr=delegate.createBinaryExpression(stack[i-1].value,stack[i-2],expr);\ni-=2}return expr}function parseConditionalExpression(){var expr,previousAllowIn,consequent,alternate;delegate.markStart();expr=parseBinaryExpression();if(match(\"?\")){lex();previousAllowIn=state.allowIn;\nstate.allowIn=true;consequent=parseAssignmentExpression();state.allowIn=previousAllowIn;expect(\":\");alternate=parseAssignmentExpression();expr=delegate.markEnd(delegate.createConditionalExpression(expr,consequent,alternate))\n}else{delegate.markEnd({})}return expr}function parseAssignmentExpression(){var token,marker,left,right,node;token=lookahead;marker=createLocationMarker();node=left=parseConditionalExpression();if(matchAssign()){if(!isLeftHandSide(left)){throwError({},Messages.InvalidLHSInAssignment)\n}if(strict&&left.type===Syntax.Identifier&&isRestrictedWord(left.name)){throwErrorTolerant(token,Messages.StrictLHSAssignment)}token=lex();right=parseAssignmentExpression();node=delegate.createAssignmentExpression(token.value,left,right)\n}if(marker){marker.end();return marker.applyIf(node)}return node}function parseExpression(){var marker,expr;marker=createLocationMarker();expr=parseAssignmentExpression();if(match(\",\")){expr=delegate.createSequenceExpression([expr]);\nwhile(index<length){if(!match(\",\")){break}lex();expr.expressions.push(parseAssignmentExpression())}}if(marker){marker.end();return marker.applyIf(expr)}return expr}function parseStatementList(){var list=[],statement;\nwhile(index<length){if(match(\"}\")){break}statement=parseSourceElement();if(typeof statement===\"undefined\"){break}list.push(statement)}return list}function parseBlock(){var block;delegate.markStart();expect(\"{\");\nblock=parseStatementList();expect(\"}\");return delegate.markEnd(delegate.createBlockStatement(block))}function parseVariableIdentifier(){var token;delegate.markStart();token=lex();if(token.type!==Token.Identifier){throwUnexpected(token)\n}return delegate.markEnd(delegate.createIdentifier(token.value))}function parseVariableDeclaration(kind){var init=null,id;delegate.markStart();id=parseVariableIdentifier();if(strict&&isRestrictedWord(id.name)){throwErrorTolerant({},Messages.StrictVarName)\n}if(kind===\"const\"){expect(\"=\");init=parseAssignmentExpression()}else if(match(\"=\")){lex();init=parseAssignmentExpression()}return delegate.markEnd(delegate.createVariableDeclarator(id,init))}function parseVariableDeclarationList(kind){var list=[];\ndo{list.push(parseVariableDeclaration(kind));if(!match(\",\")){break}lex()}while(index<length);return list}function parseVariableStatement(){var declarations;expectKeyword(\"var\");declarations=parseVariableDeclarationList();\nconsumeSemicolon();return delegate.createVariableDeclaration(declarations,\"var\")}function parseConstLetDeclaration(kind){var declarations;delegate.markStart();expectKeyword(kind);declarations=parseVariableDeclarationList(kind);\nconsumeSemicolon();return delegate.markEnd(delegate.createVariableDeclaration(declarations,kind))}function parseEmptyStatement(){expect(\";\");return delegate.createEmptyStatement()}function parseExpressionStatement(){var expr=parseExpression();\nconsumeSemicolon();return delegate.createExpressionStatement(expr)}function parseIfStatement(){var test,consequent,alternate;expectKeyword(\"if\");expect(\"(\");test=parseExpression();expect(\")\");consequent=parseStatement();\nif(matchKeyword(\"else\")){lex();alternate=parseStatement()}else{alternate=null}return delegate.createIfStatement(test,consequent,alternate)}function parseDoWhileStatement(){var body,test,oldInIteration;\nexpectKeyword(\"do\");oldInIteration=state.inIteration;state.inIteration=true;body=parseStatement();state.inIteration=oldInIteration;expectKeyword(\"while\");expect(\"(\");test=parseExpression();expect(\")\");\nif(match(\";\")){lex()}return delegate.createDoWhileStatement(body,test)}function parseWhileStatement(){var test,body,oldInIteration;expectKeyword(\"while\");expect(\"(\");test=parseExpression();expect(\")\");\noldInIteration=state.inIteration;state.inIteration=true;body=parseStatement();state.inIteration=oldInIteration;return delegate.createWhileStatement(test,body)}function parseForVariableDeclaration(){var token,declarations;\ndelegate.markStart();token=lex();declarations=parseVariableDeclarationList();return delegate.markEnd(delegate.createVariableDeclaration(declarations,token.value))}function parseForStatement(){var init,test,update,left,right,body,oldInIteration;\ninit=test=update=null;expectKeyword(\"for\");expect(\"(\");if(match(\";\")){lex()}else{if(matchKeyword(\"var\")||matchKeyword(\"let\")){state.allowIn=false;init=parseForVariableDeclaration();state.allowIn=true;if(init.declarations.length===1&&matchKeyword(\"in\")){lex();\nleft=init;right=parseExpression();init=null}}else{state.allowIn=false;init=parseExpression();state.allowIn=true;if(matchKeyword(\"in\")){if(!isLeftHandSide(init)){throwError({},Messages.InvalidLHSInForIn)\n}lex();left=init;right=parseExpression();init=null}}if(typeof left===\"undefined\"){expect(\";\")}}if(typeof left===\"undefined\"){if(!match(\";\")){test=parseExpression()}expect(\";\");if(!match(\")\")){update=parseExpression()\n}}expect(\")\");oldInIteration=state.inIteration;state.inIteration=true;body=parseStatement();state.inIteration=oldInIteration;return typeof left===\"undefined\"?delegate.createForStatement(init,test,update,body):delegate.createForInStatement(left,right,body)\n}function parseContinueStatement(){var label=null,key;expectKeyword(\"continue\");if(source.charCodeAt(index)===59){lex();if(!state.inIteration){throwError({},Messages.IllegalContinue)}return delegate.createContinueStatement(null)\n}if(peekLineTerminator()){if(!state.inIteration){throwError({},Messages.IllegalContinue)}return delegate.createContinueStatement(null)}if(lookahead.type===Token.Identifier){label=parseVariableIdentifier();\nkey=\"$\"+label.name;if(!Object.prototype.hasOwnProperty.call(state.labelSet,key)){throwError({},Messages.UnknownLabel,label.name)}}consumeSemicolon();if(label===null&&!state.inIteration){throwError({},Messages.IllegalContinue)\n}return delegate.createContinueStatement(label)}function parseBreakStatement(){var label=null,key;expectKeyword(\"break\");if(source.charCodeAt(index)===59){lex();if(!(state.inIteration||state.inSwitch)){throwError({},Messages.IllegalBreak)\n}return delegate.createBreakStatement(null)}if(peekLineTerminator()){if(!(state.inIteration||state.inSwitch)){throwError({},Messages.IllegalBreak)}return delegate.createBreakStatement(null)}if(lookahead.type===Token.Identifier){label=parseVariableIdentifier();\nkey=\"$\"+label.name;if(!Object.prototype.hasOwnProperty.call(state.labelSet,key)){throwError({},Messages.UnknownLabel,label.name)}}consumeSemicolon();if(label===null&&!(state.inIteration||state.inSwitch)){throwError({},Messages.IllegalBreak)\n}return delegate.createBreakStatement(label)}function parseReturnStatement(){var argument=null;expectKeyword(\"return\");if(!state.inFunctionBody){throwErrorTolerant({},Messages.IllegalReturn)}if(source.charCodeAt(index)===32){if(isIdentifierStart(source.charCodeAt(index+1))){argument=parseExpression();\nconsumeSemicolon();return delegate.createReturnStatement(argument)}}if(peekLineTerminator()){return delegate.createReturnStatement(null)}if(!match(\";\")){if(!match(\"}\")&&lookahead.type!==Token.EOF){argument=parseExpression()\n}}consumeSemicolon();return delegate.createReturnStatement(argument)}function parseWithStatement(){var object,body;if(strict){throwErrorTolerant({},Messages.StrictModeWith)}expectKeyword(\"with\");expect(\"(\");\nobject=parseExpression();expect(\")\");body=parseStatement();return delegate.createWithStatement(object,body)}function parseSwitchCase(){var test,consequent=[],statement;delegate.markStart();if(matchKeyword(\"default\")){lex();\ntest=null}else{expectKeyword(\"case\");test=parseExpression()}expect(\":\");while(index<length){if(match(\"}\")||matchKeyword(\"default\")||matchKeyword(\"case\")){break}statement=parseStatement();consequent.push(statement)\n}return delegate.markEnd(delegate.createSwitchCase(test,consequent))}function parseSwitchStatement(){var discriminant,cases,clause,oldInSwitch,defaultFound;expectKeyword(\"switch\");expect(\"(\");discriminant=parseExpression();\nexpect(\")\");expect(\"{\");if(match(\"}\")){lex();return delegate.createSwitchStatement(discriminant)}cases=[];oldInSwitch=state.inSwitch;state.inSwitch=true;defaultFound=false;while(index<length){if(match(\"}\")){break\n}clause=parseSwitchCase();if(clause.test===null){if(defaultFound){throwError({},Messages.MultipleDefaultsInSwitch)}defaultFound=true}cases.push(clause)}state.inSwitch=oldInSwitch;expect(\"}\");return delegate.createSwitchStatement(discriminant,cases)\n}function parseThrowStatement(){var argument;expectKeyword(\"throw\");if(peekLineTerminator()){throwError({},Messages.NewlineAfterThrow)}argument=parseExpression();consumeSemicolon();return delegate.createThrowStatement(argument)\n}function parseCatchClause(){var param,body;delegate.markStart();expectKeyword(\"catch\");expect(\"(\");if(match(\")\")){throwUnexpected(lookahead)}param=parseExpression();if(strict&&param.type===Syntax.Identifier&&isRestrictedWord(param.name)){throwErrorTolerant({},Messages.StrictCatchVariable)\n}expect(\")\");body=parseBlock();return delegate.markEnd(delegate.createCatchClause(param,body))}function parseTryStatement(){var block,handlers=[],finalizer=null;expectKeyword(\"try\");block=parseBlock();\nif(matchKeyword(\"catch\")){handlers.push(parseCatchClause())}if(matchKeyword(\"finally\")){lex();finalizer=parseBlock()}if(handlers.length===0&&!finalizer){throwError({},Messages.NoCatchOrFinally)}return delegate.createTryStatement(block,[],handlers,finalizer)\n}function parseDebuggerStatement(){expectKeyword(\"debugger\");consumeSemicolon();return delegate.createDebuggerStatement()}function parseStatement(){var type=lookahead.type,expr,labeledBody,key;if(type===Token.EOF){throwUnexpected(lookahead)\n}delegate.markStart();if(type===Token.Punctuator){switch(lookahead.value){case\";\":return delegate.markEnd(parseEmptyStatement());case\"{\":return delegate.markEnd(parseBlock());case\"(\":return delegate.markEnd(parseExpressionStatement());\ndefault:break}}if(type===Token.Keyword){switch(lookahead.value){case\"break\":return delegate.markEnd(parseBreakStatement());case\"continue\":return delegate.markEnd(parseContinueStatement());case\"debugger\":return delegate.markEnd(parseDebuggerStatement());\ncase\"do\":return delegate.markEnd(parseDoWhileStatement());case\"for\":return delegate.markEnd(parseForStatement());case\"function\":return delegate.markEnd(parseFunctionDeclaration());case\"if\":return delegate.markEnd(parseIfStatement());\ncase\"return\":return delegate.markEnd(parseReturnStatement());case\"switch\":return delegate.markEnd(parseSwitchStatement());case\"throw\":return delegate.markEnd(parseThrowStatement());case\"try\":return delegate.markEnd(parseTryStatement());\ncase\"var\":return delegate.markEnd(parseVariableStatement());case\"while\":return delegate.markEnd(parseWhileStatement());case\"with\":return delegate.markEnd(parseWithStatement());default:break}}expr=parseExpression();\nif(expr.type===Syntax.Identifier&&match(\":\")){lex();key=\"$\"+expr.name;if(Object.prototype.hasOwnProperty.call(state.labelSet,key)){throwError({},Messages.Redeclaration,\"Label\",expr.name)}state.labelSet[key]=true;\nlabeledBody=parseStatement();delete state.labelSet[key];return delegate.markEnd(delegate.createLabeledStatement(expr,labeledBody))}consumeSemicolon();return delegate.markEnd(delegate.createExpressionStatement(expr))\n}function parseFunctionSourceElements(){var sourceElement,sourceElements=[],token,directive,firstRestricted,oldLabelSet,oldInIteration,oldInSwitch,oldInFunctionBody;delegate.markStart();expect(\"{\");while(index<length){if(lookahead.type!==Token.StringLiteral){break\n}token=lookahead;sourceElement=parseSourceElement();sourceElements.push(sourceElement);if(sourceElement.expression.type!==Syntax.Literal){break}directive=source.slice(token.range[0]+1,token.range[1]-1);\nif(directive===\"use strict\"){strict=true;if(firstRestricted){throwErrorTolerant(firstRestricted,Messages.StrictOctalLiteral)}}else{if(!firstRestricted&&token.octal){firstRestricted=token}}}oldLabelSet=state.labelSet;\noldInIteration=state.inIteration;oldInSwitch=state.inSwitch;oldInFunctionBody=state.inFunctionBody;state.labelSet={};state.inIteration=false;state.inSwitch=false;state.inFunctionBody=true;while(index<length){if(match(\"}\")){break\n}sourceElement=parseSourceElement();if(typeof sourceElement===\"undefined\"){break}sourceElements.push(sourceElement)}expect(\"}\");state.labelSet=oldLabelSet;state.inIteration=oldInIteration;state.inSwitch=oldInSwitch;\nstate.inFunctionBody=oldInFunctionBody;return delegate.markEnd(delegate.createBlockStatement(sourceElements))}function parseParams(firstRestricted){var param,params=[],token,stricted,paramSet,key,message;\nexpect(\"(\");if(!match(\")\")){paramSet={};while(index<length){token=lookahead;param=parseVariableIdentifier();key=\"$\"+token.value;if(strict){if(isRestrictedWord(token.value)){stricted=token;message=Messages.StrictParamName\n}if(Object.prototype.hasOwnProperty.call(paramSet,key)){stricted=token;message=Messages.StrictParamDupe}}else if(!firstRestricted){if(isRestrictedWord(token.value)){firstRestricted=token;message=Messages.StrictParamName\n}else if(isStrictModeReservedWord(token.value)){firstRestricted=token;message=Messages.StrictReservedWord}else if(Object.prototype.hasOwnProperty.call(paramSet,key)){firstRestricted=token;message=Messages.StrictParamDupe\n}}params.push(param);paramSet[key]=true;if(match(\")\")){break}expect(\",\")}}expect(\")\");return{params:params,stricted:stricted,firstRestricted:firstRestricted,message:message}}function parseFunctionDeclaration(){var id,params=[],body,token,stricted,tmp,firstRestricted,message,previousStrict;\ndelegate.markStart();expectKeyword(\"function\");token=lookahead;id=parseVariableIdentifier();if(strict){if(isRestrictedWord(token.value)){throwErrorTolerant(token,Messages.StrictFunctionName)}}else{if(isRestrictedWord(token.value)){firstRestricted=token;\nmessage=Messages.StrictFunctionName}else if(isStrictModeReservedWord(token.value)){firstRestricted=token;message=Messages.StrictReservedWord}}tmp=parseParams(firstRestricted);params=tmp.params;stricted=tmp.stricted;\nfirstRestricted=tmp.firstRestricted;if(tmp.message){message=tmp.message}previousStrict=strict;body=parseFunctionSourceElements();if(strict&&firstRestricted){throwError(firstRestricted,message)}if(strict&&stricted){throwErrorTolerant(stricted,message)\n}strict=previousStrict;return delegate.markEnd(delegate.createFunctionDeclaration(id,params,[],body))}function parseFunctionExpression(){var token,id=null,stricted,firstRestricted,message,tmp,params=[],body,previousStrict;\ndelegate.markStart();expectKeyword(\"function\");if(!match(\"(\")){token=lookahead;id=parseVariableIdentifier();if(strict){if(isRestrictedWord(token.value)){throwErrorTolerant(token,Messages.StrictFunctionName)\n}}else{if(isRestrictedWord(token.value)){firstRestricted=token;message=Messages.StrictFunctionName}else if(isStrictModeReservedWord(token.value)){firstRestricted=token;message=Messages.StrictReservedWord\n}}}tmp=parseParams(firstRestricted);params=tmp.params;stricted=tmp.stricted;firstRestricted=tmp.firstRestricted;if(tmp.message){message=tmp.message}previousStrict=strict;body=parseFunctionSourceElements();\nif(strict&&firstRestricted){throwError(firstRestricted,message)}if(strict&&stricted){throwErrorTolerant(stricted,message)}strict=previousStrict;return delegate.markEnd(delegate.createFunctionExpression(id,params,[],body))\n}function parseSourceElement(){if(lookahead.type===Token.Keyword){switch(lookahead.value){case\"const\":case\"let\":return parseConstLetDeclaration(lookahead.value);case\"function\":return parseFunctionDeclaration();\ndefault:return parseStatement()}}if(lookahead.type!==Token.EOF){return parseStatement()}}function parseSourceElements(){var sourceElement,sourceElements=[],token,directive,firstRestricted;while(index<length){token=lookahead;\nif(token.type!==Token.StringLiteral){break}sourceElement=parseSourceElement();sourceElements.push(sourceElement);if(sourceElement.expression.type!==Syntax.Literal){break}directive=source.slice(token.range[0]+1,token.range[1]-1);\nif(directive===\"use strict\"){strict=true;if(firstRestricted){throwErrorTolerant(firstRestricted,Messages.StrictOctalLiteral)}}else{if(!firstRestricted&&token.octal){firstRestricted=token}}}while(index<length){sourceElement=parseSourceElement();\nif(typeof sourceElement===\"undefined\"){break}sourceElements.push(sourceElement)}return sourceElements}function parseProgram(){var body;delegate.markStart();strict=false;peek();body=parseSourceElements();\nreturn delegate.markEnd(delegate.createProgram(body))}function addComment(type,value,start,end,loc){assert(typeof start===\"number\",\"Comment must have valid position\");if(extra.comments.length>0){if(extra.comments[extra.comments.length-1].range[1]>start){return\n}}extra.comments.push({type:type,value:value,range:[start,end],loc:loc})}function scanComment(){var comment,ch,loc,start,blockComment,lineComment;comment=\"\";blockComment=false;lineComment=false;while(index<length){ch=source[index];\nif(lineComment){ch=source[index++];if(isLineTerminator(ch.charCodeAt(0))){loc.end={line:lineNumber,column:index-lineStart-1};lineComment=false;addComment(\"Line\",comment,start,index-1,loc);if(ch===\"\\r\"&&source[index]===\"\\n\"){++index\n}++lineNumber;lineStart=index;comment=\"\"}else if(index>=length){lineComment=false;comment+=ch;loc.end={line:lineNumber,column:length-lineStart};addComment(\"Line\",comment,start,length,loc)}else{comment+=ch\n}}else if(blockComment){if(isLineTerminator(ch.charCodeAt(0))){if(ch===\"\\r\"&&source[index+1]===\"\\n\"){++index;comment+=\"\\r\\n\"}else{comment+=ch}++lineNumber;++index;lineStart=index;if(index>=length){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")\n}}else{ch=source[index++];if(index>=length){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}comment+=ch;if(ch===\"*\"){ch=source[index];if(ch===\"/\"){comment=comment.substr(0,comment.length-1);blockComment=false;\n++index;loc.end={line:lineNumber,column:index-lineStart};addComment(\"Block\",comment,start,index,loc);comment=\"\"}}}}else if(ch===\"/\"){ch=source[index+1];if(ch===\"/\"){loc={start:{line:lineNumber,column:index-lineStart}};\nstart=index;index+=2;lineComment=true;if(index>=length){loc.end={line:lineNumber,column:index-lineStart};lineComment=false;addComment(\"Line\",comment,start,index,loc)}}else if(ch===\"*\"){start=index;index+=2;\nblockComment=true;loc={start:{line:lineNumber,column:index-lineStart-2}};if(index>=length){throwError({},Messages.UnexpectedToken,\"ILLEGAL\")}}else{break}}else if(isWhiteSpace(ch.charCodeAt(0))){++index\n}else if(isLineTerminator(ch.charCodeAt(0))){++index;if(ch===\"\\r\"&&source[index]===\"\\n\"){++index}++lineNumber;lineStart=index}else{break}}}function filterCommentLocation(){var i,entry,comment,comments=[];\nfor(i=0;i<extra.comments.length;++i){entry=extra.comments[i];comment={type:entry.type,value:entry.value};if(extra.range){comment.range=entry.range}if(extra.loc){comment.loc=entry.loc}comments.push(comment)\n}extra.comments=comments}function collectToken(){var start,loc,token,range,value;skipComment();start=index;loc={start:{line:lineNumber,column:index-lineStart}};token=extra.advance();loc.end={line:lineNumber,column:index-lineStart};\nif(token.type!==Token.EOF){range=[token.range[0],token.range[1]];value=source.slice(token.range[0],token.range[1]);extra.tokens.push({type:TokenName[token.type],value:value,range:range,loc:loc})}return token\n}function collectRegex(){var pos,loc,regex,token;skipComment();pos=index;loc={start:{line:lineNumber,column:index-lineStart}};regex=extra.scanRegExp();loc.end={line:lineNumber,column:index-lineStart};if(!extra.tokenize){if(extra.tokens.length>0){token=extra.tokens[extra.tokens.length-1];\nif(token.range[0]===pos&&token.type===\"Punctuator\"){if(token.value===\"/\"||token.value===\"/=\"){extra.tokens.pop()}}}extra.tokens.push({type:\"RegularExpression\",value:regex.literal,range:[pos,index],loc:loc})\n}return regex}function filterTokenLocation(){var i,entry,token,tokens=[];for(i=0;i<extra.tokens.length;++i){entry=extra.tokens[i];token={type:entry.type,value:entry.value};if(extra.range){token.range=entry.range\n}if(extra.loc){token.loc=entry.loc}tokens.push(token)}extra.tokens=tokens}function createLocationMarker(){if(!extra.loc&&!extra.range){return null}skipComment();return{range:[index,index],loc:{start:{line:lineNumber,column:index-lineStart},end:{line:lineNumber,column:index-lineStart}},end:function(){this.range[1]=index;\nthis.loc.end.line=lineNumber;this.loc.end.column=index-lineStart},apply:function(node){node.range=[this.range[0],this.range[1]];node.loc={start:{line:this.loc.start.line,column:this.loc.start.column},end:{line:this.loc.end.line,column:this.loc.end.column}};\nnode=delegate.postProcess(node)},applyIf:function(node){if(extra.range&&!node.range){this.apply(node)}if(extra.loc&&!node.loc){this.apply(node)}return node}}}function filterGroup(node){var name;delete node.groupRange;\ndelete node.groupLoc;for(name in node){if(node.hasOwnProperty(name)&&typeof node[name]===\"object\"&&node[name]){if(node[name].type||node[name].length&&!node[name].substr){filterGroup(node[name])}}}}function wrapTrackingFunction(range,loc){return function(parseFunction){function isBinary(node){return node.type===Syntax.LogicalExpression||node.type===Syntax.BinaryExpression\n}function visit(node){var start,end;if(isBinary(node.left)){visit(node.left)}if(isBinary(node.right)){visit(node.right)}if(range){if(node.left.groupRange||node.right.groupRange){start=node.left.groupRange?node.left.groupRange[0]:node.left.range[0];\nend=node.right.groupRange?node.right.groupRange[1]:node.right.range[1];node.range=[start,end]}else if(typeof node.range===\"undefined\"){start=node.left.range[0];end=node.right.range[1];node.range=[start,end]\n}}if(loc){if(node.left.groupLoc||node.right.groupLoc){start=node.left.groupLoc?node.left.groupLoc.start:node.left.loc.start;end=node.right.groupLoc?node.right.groupLoc.end:node.right.loc.end;node.loc={start:start,end:end};\nnode=delegate.postProcess(node)}else if(typeof node.loc===\"undefined\"){node.loc={start:node.left.loc.start,end:node.right.loc.end};node=delegate.postProcess(node)}}}return function(){var marker,node;marker=createLocationMarker();\nnode=parseFunction.apply(null,arguments);marker.end();if(range&&typeof node.range===\"undefined\"){marker.apply(node)}if(loc&&typeof node.loc===\"undefined\"){marker.apply(node)}if(isBinary(node)){visit(node)\n}return node}}}function patch(){var wrapTracking;if(extra.comments){extra.skipComment=skipComment;skipComment=scanComment}if(extra.range||extra.loc){wrapTracking=wrapTrackingFunction(extra.range,extra.loc);\nextra.parseBinaryExpression=parseBinaryExpression;parseBinaryExpression=wrapTracking(extra.parseBinaryExpression)}if(typeof extra.tokens!==\"undefined\"){extra.advance=advance;extra.scanRegExp=scanRegExp;\nadvance=collectToken;scanRegExp=collectRegex}}function unpatch(){if(typeof extra.skipComment===\"function\"){skipComment=extra.skipComment}if(extra.range||extra.loc){parseBinaryExpression=extra.parseBinaryExpression\n}if(typeof extra.scanRegExp===\"function\"){advance=extra.advance;scanRegExp=extra.scanRegExp}}function extend(object,properties){var entry,result={};for(entry in object){if(object.hasOwnProperty(entry)){result[entry]=object[entry]\n}}for(entry in properties){if(properties.hasOwnProperty(entry)){result[entry]=properties[entry]}}return result}function tokenize(code,options){var toString,token,tokens;toString=String;if(typeof code!==\"string\"&&!(code instanceof String)){code=toString(code)\n}delegate=SyntaxTreeDelegate;source=code;index=0;lineNumber=source.length>0?1:0;lineStart=0;length=source.length;lookahead=null;state={allowIn:true,labelSet:{},inFunctionBody:false,inIteration:false,inSwitch:false};\nextra={};options=options||{};options.tokens=true;extra.tokens=[];extra.tokenize=true;extra.openParenToken=-1;extra.openCurlyToken=-1;extra.range=typeof options.range===\"boolean\"&&options.range;extra.loc=typeof options.loc===\"boolean\"&&options.loc;\nif(typeof options.comment===\"boolean\"&&options.comment){extra.comments=[]}if(typeof options.tolerant===\"boolean\"&&options.tolerant){extra.errors=[]}if(length>0){if(typeof source[0]===\"undefined\"){if(code instanceof String){source=code.valueOf()\n}}}patch();try{peek();if(lookahead.type===Token.EOF){return extra.tokens}token=lex();while(lookahead.type!==Token.EOF){try{token=lex()}catch(lexError){token=lookahead;if(extra.errors){extra.errors.push(lexError);\nbreak}else{throw lexError}}}filterTokenLocation();tokens=extra.tokens;if(typeof extra.comments!==\"undefined\"){filterCommentLocation();tokens.comments=extra.comments}if(typeof extra.errors!==\"undefined\"){tokens.errors=extra.errors\n}}catch(e){throw e}finally{unpatch();extra={}}return tokens}function parse(code,options){var program,toString;toString=String;if(typeof code!==\"string\"&&!(code instanceof String)){code=toString(code)}delegate=SyntaxTreeDelegate;\nsource=code;index=0;lineNumber=source.length>0?1:0;lineStart=0;length=source.length;lookahead=null;state={allowIn:true,labelSet:{},inFunctionBody:false,inIteration:false,inSwitch:false};extra={};if(typeof options!==\"undefined\"){extra.range=typeof options.range===\"boolean\"&&options.range;\nextra.loc=typeof options.loc===\"boolean\"&&options.loc;if(typeof options.range===\"boolean\"&&options.range){state.rangeStack=[];delegate=extend(delegate,{markStart:function(){skipComment();state.rangeStack.push(index)\n}});delegate=extend(delegate,{markEnd:function(node){node.range=[state.rangeStack.pop(),index];return node}})}if(typeof options.loc===\"boolean\"&&options.loc){state.locStack=[];delegate=extend(delegate,{markStart:function(){skipComment();\nstate.locStack.push({line:lineNumber,column:index-lineStart});if(state.rangeStack){state.rangeStack.push(index)}}});delegate=extend(delegate,{markEnd:function(node){if(state.rangeStack){node.range=[state.rangeStack.pop(),index]\n}node.loc={};node.loc.start=state.locStack.pop();node.loc.end={line:lineNumber,column:index-lineStart};if(options.source!==null&&options.source!==undefined){node.loc.source=toString(options.source)}return node\n}});delegate=extend(delegate,{markGroupEnd:function(node){if(state.rangeStack){node.groupRange=[state.rangeStack.pop(),index]}node.groupLoc={};node.groupLoc.start=state.locStack.pop();node.groupLoc.end={line:lineNumber,column:index-lineStart};\nif(options.source!==null&&options.source!==undefined){node.groupLoc.source=toString(options.source)}return node}})}if(extra.loc&&options.source!==null&&options.source!==undefined){delegate=extend(delegate,{postProcess:function(node){node.loc.source=toString(options.source);\nreturn node}})}if(typeof options.tokens===\"boolean\"&&options.tokens){extra.tokens=[]}if(typeof options.comment===\"boolean\"&&options.comment){extra.comments=[]}if(typeof options.tolerant===\"boolean\"&&options.tolerant){extra.errors=[]\n}}if(length>0){if(typeof source[0]===\"undefined\"){if(code instanceof String){source=code.valueOf()}}}patch();try{program=parseProgram();if(typeof extra.comments!==\"undefined\"){filterCommentLocation();program.comments=extra.comments\n}if(typeof extra.tokens!==\"undefined\"){filterTokenLocation();program.tokens=extra.tokens}if(typeof extra.errors!==\"undefined\"){program.errors=extra.errors}if(extra.range||extra.loc){filterGroup(program.body)\n}}catch(e){throw e}finally{unpatch();extra={}}return program}exports.version=\"1.1.0-dev\";exports.tokenize=tokenize;exports.parse=parse;exports.Syntax=function(){var name,types={};if(typeof Object.create===\"function\"){types=Object.create(null)\n}for(name in Syntax){if(Syntax.hasOwnProperty(name)){types[name]=Syntax[name]}}if(typeof Object.freeze===\"function\"){Object.freeze(types)}return types}()});\n/* END INSERT */\n\nrealExports.esprima = exports;\nvar esprima = exports;\n/* Includes a minified jshint: http://www.jshint.com/ */\n// Avoid clobber:\nexports = {};\n\n/* INSERT jshint.js */\nvar JSHINT;(function(){var require=function(file,cwd){var resolved=require.resolve(file,cwd||\"/\");var mod=require.modules[resolved];if(!mod)throw new Error(\"Failed to resolve module \"+file+\", tried \"+resolved);\nvar cached=require.cache[resolved];var res=cached?cached.exports:mod();return res};require.paths=[];require.modules={};require.cache={};require.extensions=[\".js\",\".coffee\",\".json\"];require._core={assert:true,events:true,fs:true,path:true,vm:true};\nrequire.resolve=function(){return function(x,cwd){if(!cwd)cwd=\"/\";if(require._core[x])return x;var path=require.modules.path();cwd=path.resolve(\"/\",cwd);var y=cwd||\"/\";if(x.match(/^(?:\\.\\.?\\/|\\/)/)){var m=loadAsFileSync(path.resolve(y,x))||loadAsDirectorySync(path.resolve(y,x));\nif(m)return m}var n=loadNodeModulesSync(x,y);if(n)return n;throw new Error(\"Cannot find module '\"+x+\"'\");function loadAsFileSync(x){x=path.normalize(x);if(require.modules[x]){return x}for(var i=0;i<require.extensions.length;i++){var ext=require.extensions[i];\nif(require.modules[x+ext])return x+ext}}function loadAsDirectorySync(x){x=x.replace(/\\/+$/,\"\");var pkgfile=path.normalize(x+\"/package.json\");if(require.modules[pkgfile]){var pkg=require.modules[pkgfile]();\nvar b=pkg.browserify;if(typeof b===\"object\"&&b.main){var m=loadAsFileSync(path.resolve(x,b.main));if(m)return m}else if(typeof b===\"string\"){var m=loadAsFileSync(path.resolve(x,b));if(m)return m}else if(pkg.main){var m=loadAsFileSync(path.resolve(x,pkg.main));\nif(m)return m}}return loadAsFileSync(x+\"/index\")}function loadNodeModulesSync(x,start){var dirs=nodeModulesPathsSync(start);for(var i=0;i<dirs.length;i++){var dir=dirs[i];var m=loadAsFileSync(dir+\"/\"+x);\nif(m)return m;var n=loadAsDirectorySync(dir+\"/\"+x);if(n)return n}var m=loadAsFileSync(x);if(m)return m}function nodeModulesPathsSync(start){var parts;if(start===\"/\")parts=[\"\"];else parts=path.normalize(start).split(\"/\");\nvar dirs=[];for(var i=parts.length-1;i>=0;i--){if(parts[i]===\"node_modules\")continue;var dir=parts.slice(0,i+1).join(\"/\")+\"/node_modules\";dirs.push(dir)}return dirs}}}();require.alias=function(from,to){var path=require.modules.path();\nvar res=null;try{res=require.resolve(from+\"/package.json\",\"/\")}catch(err){res=require.resolve(from,\"/\")}var basedir=path.dirname(res);var keys=(Object.keys||function(obj){var res=[];for(var key in obj)res.push(key);\nreturn res})(require.modules);for(var i=0;i<keys.length;i++){var key=keys[i];if(key.slice(0,basedir.length+1)===basedir+\"/\"){var f=key.slice(basedir.length);require.modules[to+f]=require.modules[basedir+f]\n}else if(key===basedir){require.modules[to]=require.modules[basedir]}}};(function(){var process={};var global=typeof window!==\"undefined\"?window:{};var definedProcess=false;require.define=function(filename,fn){if(!definedProcess&&require.modules.__browserify_process){process=require.modules.__browserify_process();\ndefinedProcess=true}var dirname=require._core[filename]?\"\":require.modules.path().dirname(filename);var require_=function(file){var requiredModule=require(file,dirname);var cached=require.cache[require.resolve(file,dirname)];\nif(cached&&cached.parent===null){cached.parent=module_}return requiredModule};require_.resolve=function(name){return require.resolve(name,dirname)};require_.modules=require.modules;require_.define=require.define;\nrequire_.cache=require.cache;var module_={id:filename,filename:filename,exports:{},loaded:false,parent:null};require.modules[filename]=function(){require.cache[filename]=module_;fn.call(module_.exports,require_,module_,module_.exports,dirname,filename,process,global);\nmodule_.loaded=true;return module_.exports}}})();require.define(\"path\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],\"function filter (xs, fn) {\\n    var res = [];\\n    for (var i = 0; i < xs.length; i++) {\\n        if (fn(xs[i], i, xs)) res.push(xs[i]);\\n    }\\n    return res;\\n}\\n\\n// resolves . and .. elements in a path array with directory names there\\n// must be no slashes, empty elements, or device names (c:\\\\) in the array\\n// (so also no leading and trailing slashes - it does not distinguish\\n// relative and absolute paths)\\nfunction normalizeArray(parts, allowAboveRoot) {\\n  // if the path tries to go above the root, `up` ends up > 0\\n  var up = 0;\\n  for (var i = parts.length; i >= 0; i--) {\\n    var last = parts[i];\\n    if (last == '.') {\\n      parts.splice(i, 1);\\n    } else if (last === '..') {\\n      parts.splice(i, 1);\\n      up++;\\n    } else if (up) {\\n      parts.splice(i, 1);\\n      up--;\\n    }\\n  }\\n\\n  // if the path is allowed to go above the root, restore leading ..s\\n  if (allowAboveRoot) {\\n    for (; up--; up) {\\n      parts.unshift('..');\\n    }\\n  }\\n\\n  return parts;\\n}\\n\\n// Regex to split a filename into [*, dir, basename, ext]\\n// posix version\\nvar splitPathRe = /^(.+\\\\/(?!$)|\\\\/)?((?:.+?)?(\\\\.[^.]*)?)$/;\\n\\n// path.resolve([from ...], to)\\n// posix version\\nexports.resolve = function() {\\nvar resolvedPath = '',\\n    resolvedAbsolute = false;\\n\\nfor (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {\\n  var path = (i >= 0)\\n      ? arguments[i]\\n      : process.cwd();\\n\\n  // Skip empty and invalid entries\\n  if (typeof path !== 'string' || !path) {\\n    continue;\\n  }\\n\\n  resolvedPath = path + '/' + resolvedPath;\\n  resolvedAbsolute = path.charAt(0) === '/';\\n}\\n\\n// At this point the path should be resolved to a full absolute path, but\\n// handle relative paths to be safe (might happen when process.cwd() fails)\\n\\n// Normalize the path\\nresolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {\\n    return !!p;\\n  }), !resolvedAbsolute).join('/');\\n\\n  return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';\\n};\\n\\n// path.normalize(path)\\n// posix version\\nexports.normalize = function(path) {\\nvar isAbsolute = path.charAt(0) === '/',\\n    trailingSlash = path.slice(-1) === '/';\\n\\n// Normalize the path\\npath = normalizeArray(filter(path.split('/'), function(p) {\\n    return !!p;\\n  }), !isAbsolute).join('/');\\n\\n  if (!path && !isAbsolute) {\\n    path = '.';\\n  }\\n  if (path && trailingSlash) {\\n    path += '/';\\n  }\\n  \\n  return (isAbsolute ? '/' : '') + path;\\n};\\n\\n\\n// posix version\\nexports.join = function() {\\n  var paths = Array.prototype.slice.call(arguments, 0);\\n  return exports.normalize(filter(paths, function(p, index) {\\n    return p && typeof p === 'string';\\n  }).join('/'));\\n};\\n\\n\\nexports.dirname = function(path) {\\n  var dir = splitPathRe.exec(path)[1] || '';\\n  var isWindows = false;\\n  if (!dir) {\\n    // No dirname\\n    return '.';\\n  } else if (dir.length === 1 ||\\n      (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {\\n    // It is just a slash or a drive letter with a slash\\n    return dir;\\n  } else {\\n    // It is a full dirname, strip trailing slash\\n    return dir.substring(0, dir.length - 1);\\n  }\\n};\\n\\n\\nexports.basename = function(path, ext) {\\n  var f = splitPathRe.exec(path)[2] || '';\\n  // TODO: make this comparison case-insensitive on windows?\\n  if (ext && f.substr(-1 * ext.length) === ext) {\\n    f = f.substr(0, f.length - ext.length);\\n  }\\n  return f;\\n};\\n\\n\\nexports.extname = function(path) {\\n  return splitPathRe.exec(path)[3] || '';\\n};\\n\\n//@ sourceURL=path\"));\nrequire.define(\"__browserify_process\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],\"var process = module.exports = {};\\n\\nprocess.nextTick = (function () {\\n    var canSetImmediate = typeof window !== 'undefined'\\n        && window.setImmediate;\\n    var canPost = typeof window !== 'undefined'\\n        && window.postMessage && window.addEventListener\\n    ;\\n\\n    if (canSetImmediate) {\\n        return window.setImmediate;\\n    }\\n\\n    if (canPost) {\\n        var queue = [];\\n        window.addEventListener('message', function (ev) {\\n            if (ev.source === window && ev.data === 'browserify-tick') {\\n                ev.stopPropagation();\\n                if (queue.length > 0) {\\n                    var fn = queue.shift();\\n                    fn();\\n                }\\n            }\\n        }, true);\\n\\n        return function nextTick(fn) {\\n            queue.push(fn);\\n            window.postMessage('browserify-tick', '*');\\n        };\\n    }\\n\\n    return function nextTick(fn) {\\n        setTimeout(fn, 0);\\n    };\\n})();\\n\\nprocess.title = 'browser';\\nprocess.browser = true;\\nprocess.env = {};\\nprocess.argv = [];\\n\\nprocess.binding = function (name) {\\n    if (name === 'evals') return (require)('vm')\\n    else throw new Error('No such module. (Possibly not yet loaded)')\\n};\\n\\n(function () {\\n    var cwd = '/';\\n    var path;\\n    process.cwd = function () { return cwd };\\n    process.chdir = function (dir) {\\n        if (!path) path = require('path');\\n        cwd = path.resolve(dir, cwd);\\n    };\\n})();\\n\\n//@ sourceURL=__browserify_process\"));\nrequire.define(\"/node_modules/underscore/package.json\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],'module.exports = {\"main\":\"underscore.js\"}\\n//@ sourceURL=/node_modules/underscore/package.json'));\nrequire.define(\"/node_modules/underscore/underscore.js\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],\"//     Underscore.js 1.4.4\\n//     http://underscorejs.org\\n//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.\\n//     Underscore may be freely distributed under the MIT license.\\n\\n(function() {\\n\\n  // Baseline setup\\n  // --------------\\n\\n  // Establish the root object, `window` in the browser, or `global` on the server.\\n  var root = this;\\n\\n  // Save the previous value of the `_` variable.\\n  var previousUnderscore = root._;\\n\\n  // Establish the object that gets returned to break out of a loop iteration.\\n  var breaker = {};\\n\\n  // Save bytes in the minified (but not gzipped) version:\\n  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\\n\\n  // Create quick reference variables for speed access to core prototypes.\\n  var push             = ArrayProto.push,\\n      slice            = ArrayProto.slice,\\n      concat           = ArrayProto.concat,\\n      toString         = ObjProto.toString,\\n      hasOwnProperty   = ObjProto.hasOwnProperty;\\n\\n  // All **ECMAScript 5** native function implementations that we hope to use\\n  // are declared here.\\n  var\\n    nativeForEach      = ArrayProto.forEach,\\n    nativeMap          = ArrayProto.map,\\n    nativeReduce       = ArrayProto.reduce,\\n    nativeReduceRight  = ArrayProto.reduceRight,\\n    nativeFilter       = ArrayProto.filter,\\n    nativeEvery        = ArrayProto.every,\\n    nativeSome         = ArrayProto.some,\\n    nativeIndexOf      = ArrayProto.indexOf,\\n    nativeLastIndexOf  = ArrayProto.lastIndexOf,\\n    nativeIsArray      = Array.isArray,\\n    nativeKeys         = Object.keys,\\n    nativeBind         = FuncProto.bind;\\n\\n  // Create a safe reference to the Underscore object for use below.\\n  var _ = function(obj) {\\n    if (obj instanceof _) return obj;\\n    if (!(this instanceof _)) return new _(obj);\\n    this._wrapped = obj;\\n  };\\n\\n  // Export the Underscore object for **Node.js**, with\\n  // backwards-compatibility for the old `require()` API. If we're in\\n  // the browser, add `_` as a global object via a string identifier,\\n  // for Closure Compiler \\\"advanced\\\" mode.\\n  if (typeof exports !== 'undefined') {\\n    if (typeof module !== 'undefined' && module.exports) {\\n      exports = module.exports = _;\\n    }\\n    exports._ = _;\\n  } else {\\n    root._ = _;\\n  }\\n\\n  // Current version.\\n  _.VERSION = '1.4.4';\\n\\n  // Collection Functions\\n  // --------------------\\n\\n  // The cornerstone, an `each` implementation, aka `forEach`.\\n  // Handles objects with the built-in `forEach`, arrays, and raw objects.\\n  // Delegates to **ECMAScript 5**'s native `forEach` if available.\\n  var each = _.each = _.forEach = function(obj, iterator, context) {\\n    if (obj == null) return;\\n    if (nativeForEach && obj.forEach === nativeForEach) {\\n      obj.forEach(iterator, context);\\n    } else if (obj.length === +obj.length) {\\n      for (var i = 0, l = obj.length; i < l; i++) {\\n        if (iterator.call(context, obj[i], i, obj) === breaker) return;\\n      }\\n    } else {\\n      for (var key in obj) {\\n        if (_.has(obj, key)) {\\n          if (iterator.call(context, obj[key], key, obj) === breaker) return;\\n        }\\n      }\\n    }\\n  };\\n\\n  // Return the results of applying the iterator to each element.\\n  // Delegates to **ECMAScript 5**'s native `map` if available.\\n  _.map = _.collect = function(obj, iterator, context) {\\n    var results = [];\\n    if (obj == null) return results;\\n    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);\\n    each(obj, function(value, index, list) {\\n      results[results.length] = iterator.call(context, value, index, list);\\n    });\\n    return results;\\n  };\\n\\n  var reduceError = 'Reduce of empty array with no initial value';\\n\\n  // **Reduce** builds up a single result from a list of values, aka `inject`,\\n  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.\\n  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {\\n    var initial = arguments.length > 2;\\n    if (obj == null) obj = [];\\n    if (nativeReduce && obj.reduce === nativeReduce) {\\n      if (context) iterator = _.bind(iterator, context);\\n      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);\\n    }\\n    each(obj, function(value, index, list) {\\n      if (!initial) {\\n        memo = value;\\n        initial = true;\\n      } else {\\n        memo = iterator.call(context, memo, value, index, list);\\n      }\\n    });\\n    if (!initial) throw new TypeError(reduceError);\\n    return memo;\\n  };\\n\\n  // The right-associative version of reduce, also known as `foldr`.\\n  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.\\n  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {\\n    var initial = arguments.length > 2;\\n    if (obj == null) obj = [];\\n    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {\\n      if (context) iterator = _.bind(iterator, context);\\n      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);\\n    }\\n    var length = obj.length;\\n    if (length !== +length) {\\n      var keys = _.keys(obj);\\n      length = keys.length;\\n    }\\n    each(obj, function(value, index, list) {\\n      index = keys ? keys[--length] : --length;\\n      if (!initial) {\\n        memo = obj[index];\\n        initial = true;\\n      } else {\\n        memo = iterator.call(context, memo, obj[index], index, list);\\n      }\\n    });\\n    if (!initial) throw new TypeError(reduceError);\\n    return memo;\\n  };\\n\\n  // Return the first value which passes a truth test. Aliased as `detect`.\\n  _.find = _.detect = function(obj, iterator, context) {\\n    var result;\\n    any(obj, function(value, index, list) {\\n      if (iterator.call(context, value, index, list)) {\\n        result = value;\\n        return true;\\n      }\\n    });\\n    return result;\\n  };\\n\\n  // Return all the elements that pass a truth test.\\n  // Delegates to **ECMAScript 5**'s native `filter` if available.\\n  // Aliased as `select`.\\n  _.filter = _.select = function(obj, iterator, context) {\\n    var results = [];\\n    if (obj == null) return results;\\n    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);\\n    each(obj, function(value, index, list) {\\n      if (iterator.call(context, value, index, list)) results[results.length] = value;\\n    });\\n    return results;\\n  };\\n\\n  // Return all the elements for which a truth test fails.\\n  _.reject = function(obj, iterator, context) {\\n    return _.filter(obj, function(value, index, list) {\\n      return !iterator.call(context, value, index, list);\\n    }, context);\\n  };\\n\\n  // Determine whether all of the elements match a truth test.\\n  // Delegates to **ECMAScript 5**'s native `every` if available.\\n  // Aliased as `all`.\\n  _.every = _.all = function(obj, iterator, context) {\\n    iterator || (iterator = _.identity);\\n    var result = true;\\n    if (obj == null) return result;\\n    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);\\n    each(obj, function(value, index, list) {\\n      if (!(result = result && iterator.call(context, value, index, list))) return breaker;\\n    });\\n    return !!result;\\n  };\\n\\n  // Determine if at least one element in the object matches a truth test.\\n  // Delegates to **ECMAScript 5**'s native `some` if available.\\n  // Aliased as `any`.\\n  var any = _.some = _.any = function(obj, iterator, context) {\\n    iterator || (iterator = _.identity);\\n    var result = false;\\n    if (obj == null) return result;\\n    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);\\n    each(obj, function(value, index, list) {\\n      if (result || (result = iterator.call(context, value, index, list))) return breaker;\\n    });\\n    return !!result;\\n  };\\n\\n  // Determine if the array or object contains a given value (using `===`).\\n  // Aliased as `include`.\\n  _.contains = _.include = function(obj, target) {\\n    if (obj == null) return false;\\n    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;\\n    return any(obj, function(value) {\\n      return value === target;\\n    });\\n  };\\n\\n  // Invoke a method (with arguments) on every item in a collection.\\n  _.invoke = function(obj, method) {\\n    var args = slice.call(arguments, 2);\\n    var isFunc = _.isFunction(method);\\n    return _.map(obj, function(value) {\\n      return (isFunc ? method : value[method]).apply(value, args);\\n    });\\n  };\\n\\n  // Convenience version of a common use case of `map`: fetching a property.\\n  _.pluck = function(obj, key) {\\n    return _.map(obj, function(value){ return value[key]; });\\n  };\\n\\n  // Convenience version of a common use case of `filter`: selecting only objects\\n  // containing specific `key:value` pairs.\\n  _.where = function(obj, attrs, first) {\\n    if (_.isEmpty(attrs)) return first ? null : [];\\n    return _[first ? 'find' : 'filter'](obj, function(value) {\\n      for (var key in attrs) {\\n        if (attrs[key] !== value[key]) return false;\\n      }\\n      return true;\\n    });\\n  };\\n\\n  // Convenience version of a common use case of `find`: getting the first object\\n  // containing specific `key:value` pairs.\\n  _.findWhere = function(obj, attrs) {\\n    return _.where(obj, attrs, true);\\n  };\\n\\n  // Return the maximum element or (element-based computation).\\n  // Can't optimize arrays of integers longer than 65,535 elements.\\n  // See: https://bugs.webkit.org/show_bug.cgi?id=80797\\n  _.max = function(obj, iterator, context) {\\n    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\\n      return Math.max.apply(Math, obj);\\n    }\\n    if (!iterator && _.isEmpty(obj)) return -Infinity;\\n    var result = {computed : -Infinity, value: -Infinity};\\n    each(obj, function(value, index, list) {\\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\\n      computed >= result.computed && (result = {value : value, computed : computed});\\n    });\\n    return result.value;\\n  };\\n\\n  // Return the minimum element (or element-based computation).\\n  _.min = function(obj, iterator, context) {\\n    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\\n      return Math.min.apply(Math, obj);\\n    }\\n    if (!iterator && _.isEmpty(obj)) return Infinity;\\n    var result = {computed : Infinity, value: Infinity};\\n    each(obj, function(value, index, list) {\\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\\n      computed < result.computed && (result = {value : value, computed : computed});\\n    });\\n    return result.value;\\n  };\\n\\n  // Shuffle an array.\\n  _.shuffle = function(obj) {\\n    var rand;\\n    var index = 0;\\n    var shuffled = [];\\n    each(obj, function(value) {\\n      rand = _.random(index++);\\n      shuffled[index - 1] = shuffled[rand];\\n      shuffled[rand] = value;\\n    });\\n    return shuffled;\\n  };\\n\\n  // An internal function to generate lookup iterators.\\n  var lookupIterator = function(value) {\\n    return _.isFunction(value) ? value : function(obj){ return obj[value]; };\\n  };\\n\\n  // Sort the object's values by a criterion produced by an iterator.\\n  _.sortBy = function(obj, value, context) {\\n    var iterator = lookupIterator(value);\\n    return _.pluck(_.map(obj, function(value, index, list) {\\n      return {\\n        value : value,\\n        index : index,\\n        criteria : iterator.call(context, value, index, list)\\n      };\\n    }).sort(function(left, right) {\\n      var a = left.criteria;\\n      var b = right.criteria;\\n      if (a !== b) {\\n        if (a > b || a === void 0) return 1;\\n        if (a < b || b === void 0) return -1;\\n      }\\n      return left.index < right.index ? -1 : 1;\\n    }), 'value');\\n  };\\n\\n  // An internal function used for aggregate \\\"group by\\\" operations.\\n  var group = function(obj, value, context, behavior) {\\n    var result = {};\\n    var iterator = lookupIterator(value || _.identity);\\n    each(obj, function(value, index) {\\n      var key = iterator.call(context, value, index, obj);\\n      behavior(result, key, value);\\n    });\\n    return result;\\n  };\\n\\n  // Groups the object's values by a criterion. Pass either a string attribute\\n  // to group by, or a function that returns the criterion.\\n  _.groupBy = function(obj, value, context) {\\n    return group(obj, value, context, function(result, key, value) {\\n      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);\\n    });\\n  };\\n\\n  // Counts instances of an object that group by a certain criterion. Pass\\n  // either a string attribute to count by, or a function that returns the\\n  // criterion.\\n  _.countBy = function(obj, value, context) {\\n    return group(obj, value, context, function(result, key) {\\n      if (!_.has(result, key)) result[key] = 0;\\n      result[key]++;\\n    });\\n  };\\n\\n  // Use a comparator function to figure out the smallest index at which\\n  // an object should be inserted so as to maintain order. Uses binary search.\\n  _.sortedIndex = function(array, obj, iterator, context) {\\n    iterator = iterator == null ? _.identity : lookupIterator(iterator);\\n    var value = iterator.call(context, obj);\\n    var low = 0, high = array.length;\\n    while (low < high) {\\n      var mid = (low + high) >>> 1;\\n      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;\\n    }\\n    return low;\\n  };\\n\\n  // Safely convert anything iterable into a real, live array.\\n  _.toArray = function(obj) {\\n    if (!obj) return [];\\n    if (_.isArray(obj)) return slice.call(obj);\\n    if (obj.length === +obj.length) return _.map(obj, _.identity);\\n    return _.values(obj);\\n  };\\n\\n  // Return the number of elements in an object.\\n  _.size = function(obj) {\\n    if (obj == null) return 0;\\n    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;\\n  };\\n\\n  // Array Functions\\n  // ---------------\\n\\n  // Get the first element of an array. Passing **n** will return the first N\\n  // values in the array. Aliased as `head` and `take`. The **guard** check\\n  // allows it to work with `_.map`.\\n  _.first = _.head = _.take = function(array, n, guard) {\\n    if (array == null) return void 0;\\n    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];\\n  };\\n\\n  // Returns everything but the last entry of the array. Especially useful on\\n  // the arguments object. Passing **n** will return all the values in\\n  // the array, excluding the last N. The **guard** check allows it to work with\\n  // `_.map`.\\n  _.initial = function(array, n, guard) {\\n    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));\\n  };\\n\\n  // Get the last element of an array. Passing **n** will return the last N\\n  // values in the array. The **guard** check allows it to work with `_.map`.\\n  _.last = function(array, n, guard) {\\n    if (array == null) return void 0;\\n    if ((n != null) && !guard) {\\n      return slice.call(array, Math.max(array.length - n, 0));\\n    } else {\\n      return array[array.length - 1];\\n    }\\n  };\\n\\n  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.\\n  // Especially useful on the arguments object. Passing an **n** will return\\n  // the rest N values in the array. The **guard**\\n  // check allows it to work with `_.map`.\\n  _.rest = _.tail = _.drop = function(array, n, guard) {\\n    return slice.call(array, (n == null) || guard ? 1 : n);\\n  };\\n\\n  // Trim out all falsy values from an array.\\n  _.compact = function(array) {\\n    return _.filter(array, _.identity);\\n  };\\n\\n  // Internal implementation of a recursive `flatten` function.\\n  var flatten = function(input, shallow, output) {\\n    each(input, function(value) {\\n      if (_.isArray(value)) {\\n        shallow ? push.apply(output, value) : flatten(value, shallow, output);\\n      } else {\\n        output.push(value);\\n      }\\n    });\\n    return output;\\n  };\\n\\n  // Return a completely flattened version of an array.\\n  _.flatten = function(array, shallow) {\\n    return flatten(array, shallow, []);\\n  };\\n\\n  // Return a version of the array that does not contain the specified value(s).\\n  _.without = function(array) {\\n    return _.difference(array, slice.call(arguments, 1));\\n  };\\n\\n  // Produce a duplicate-free version of the array. If the array has already\\n  // been sorted, you have the option of using a faster algorithm.\\n  // Aliased as `unique`.\\n  _.uniq = _.unique = function(array, isSorted, iterator, context) {\\n    if (_.isFunction(isSorted)) {\\n      context = iterator;\\n      iterator = isSorted;\\n      isSorted = false;\\n    }\\n    var initial = iterator ? _.map(array, iterator, context) : array;\\n    var results = [];\\n    var seen = [];\\n    each(initial, function(value, index) {\\n      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {\\n        seen.push(value);\\n        results.push(array[index]);\\n      }\\n    });\\n    return results;\\n  };\\n\\n  // Produce an array that contains the union: each distinct element from all of\\n  // the passed-in arrays.\\n  _.union = function() {\\n    return _.uniq(concat.apply(ArrayProto, arguments));\\n  };\\n\\n  // Produce an array that contains every item shared between all the\\n  // passed-in arrays.\\n  _.intersection = function(array) {\\n    var rest = slice.call(arguments, 1);\\n    return _.filter(_.uniq(array), function(item) {\\n      return _.every(rest, function(other) {\\n        return _.indexOf(other, item) >= 0;\\n      });\\n    });\\n  };\\n\\n  // Take the difference between one array and a number of other arrays.\\n  // Only the elements present in just the first array will remain.\\n  _.difference = function(array) {\\n    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));\\n    return _.filter(array, function(value){ return !_.contains(rest, value); });\\n  };\\n\\n  // Zip together multiple lists into a single array -- elements that share\\n  // an index go together.\\n  _.zip = function() {\\n    var args = slice.call(arguments);\\n    var length = _.max(_.pluck(args, 'length'));\\n    var results = new Array(length);\\n    for (var i = 0; i < length; i++) {\\n      results[i] = _.pluck(args, \\\"\\\" + i);\\n    }\\n    return results;\\n  };\\n\\n  // Converts lists into objects. Pass either a single array of `[key, value]`\\n  // pairs, or two parallel arrays of the same length -- one of keys, and one of\\n  // the corresponding values.\\n  _.object = function(list, values) {\\n    if (list == null) return {};\\n    var result = {};\\n    for (var i = 0, l = list.length; i < l; i++) {\\n      if (values) {\\n        result[list[i]] = values[i];\\n      } else {\\n        result[list[i][0]] = list[i][1];\\n      }\\n    }\\n    return result;\\n  };\\n\\n  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),\\n  // we need this function. Return the position of the first occurrence of an\\n  // item in an array, or -1 if the item is not included in the array.\\n  // Delegates to **ECMAScript 5**'s native `indexOf` if available.\\n  // If the array is large and already in sort order, pass `true`\\n  // for **isSorted** to use binary search.\\n  _.indexOf = function(array, item, isSorted) {\\n    if (array == null) return -1;\\n    var i = 0, l = array.length;\\n    if (isSorted) {\\n      if (typeof isSorted == 'number') {\\n        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);\\n      } else {\\n        i = _.sortedIndex(array, item);\\n        return array[i] === item ? i : -1;\\n      }\\n    }\\n    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);\\n    for (; i < l; i++) if (array[i] === item) return i;\\n    return -1;\\n  };\\n\\n  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.\\n  _.lastIndexOf = function(array, item, from) {\\n    if (array == null) return -1;\\n    var hasIndex = from != null;\\n    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {\\n      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);\\n    }\\n    var i = (hasIndex ? from : array.length);\\n    while (i--) if (array[i] === item) return i;\\n    return -1;\\n  };\\n\\n  // Generate an integer Array containing an arithmetic progression. A port of\\n  // the native Python `range()` function. See\\n  // [the Python documentation](http://docs.python.org/library/functions.html#range).\\n  _.range = function(start, stop, step) {\\n    if (arguments.length <= 1) {\\n      stop = start || 0;\\n      start = 0;\\n    }\\n    step = arguments[2] || 1;\\n\\n    var len = Math.max(Math.ceil((stop - start) / step), 0);\\n    var idx = 0;\\n    var range = new Array(len);\\n\\n    while(idx < len) {\\n      range[idx++] = start;\\n      start += step;\\n    }\\n\\n    return range;\\n  };\\n\\n  // Function (ahem) Functions\\n  // ------------------\\n\\n  // Create a function bound to a given object (assigning `this`, and arguments,\\n  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if\\n  // available.\\n  _.bind = function(func, context) {\\n    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\\n    var args = slice.call(arguments, 2);\\n    return function() {\\n      return func.apply(context, args.concat(slice.call(arguments)));\\n    };\\n  };\\n\\n  // Partially apply a function by creating a version that has had some of its\\n  // arguments pre-filled, without changing its dynamic `this` context.\\n  _.partial = function(func) {\\n    var args = slice.call(arguments, 1);\\n    return function() {\\n      return func.apply(this, args.concat(slice.call(arguments)));\\n    };\\n  };\\n\\n  // Bind all of an object's methods to that object. Useful for ensuring that\\n  // all callbacks defined on an object belong to it.\\n  _.bindAll = function(obj) {\\n    var funcs = slice.call(arguments, 1);\\n    if (funcs.length === 0) funcs = _.functions(obj);\\n    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });\\n    return obj;\\n  };\\n\\n  // Memoize an expensive function by storing its results.\\n  _.memoize = function(func, hasher) {\\n    var memo = {};\\n    hasher || (hasher = _.identity);\\n    return function() {\\n      var key = hasher.apply(this, arguments);\\n      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));\\n    };\\n  };\\n\\n  // Delays a function for the given number of milliseconds, and then calls\\n  // it with the arguments supplied.\\n  _.delay = function(func, wait) {\\n    var args = slice.call(arguments, 2);\\n    return setTimeout(function(){ return func.apply(null, args); }, wait);\\n  };\\n\\n  // Defers a function, scheduling it to run after the current call stack has\\n  // cleared.\\n  _.defer = function(func) {\\n    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));\\n  };\\n\\n  // Returns a function, that, when invoked, will only be triggered at most once\\n  // during a given window of time.\\n  _.throttle = function(func, wait) {\\n    var context, args, timeout, result;\\n    var previous = 0;\\n    var later = function() {\\n      previous = new Date;\\n      timeout = null;\\n      result = func.apply(context, args);\\n    };\\n    return function() {\\n      var now = new Date;\\n      var remaining = wait - (now - previous);\\n      context = this;\\n      args = arguments;\\n      if (remaining <= 0) {\\n        clearTimeout(timeout);\\n        timeout = null;\\n        previous = now;\\n        result = func.apply(context, args);\\n      } else if (!timeout) {\\n        timeout = setTimeout(later, remaining);\\n      }\\n      return result;\\n    };\\n  };\\n\\n  // Returns a function, that, as long as it continues to be invoked, will not\\n  // be triggered. The function will be called after it stops being called for\\n  // N milliseconds. If `immediate` is passed, trigger the function on the\\n  // leading edge, instead of the trailing.\\n  _.debounce = function(func, wait, immediate) {\\n    var timeout, result;\\n    return function() {\\n      var context = this, args = arguments;\\n      var later = function() {\\n        timeout = null;\\n        if (!immediate) result = func.apply(context, args);\\n      };\\n      var callNow = immediate && !timeout;\\n      clearTimeout(timeout);\\n      timeout = setTimeout(later, wait);\\n      if (callNow) result = func.apply(context, args);\\n      return result;\\n    };\\n  };\\n\\n  // Returns a function that will be executed at most one time, no matter how\\n  // often you call it. Useful for lazy initialization.\\n  _.once = function(func) {\\n    var ran = false, memo;\\n    return function() {\\n      if (ran) return memo;\\n      ran = true;\\n      memo = func.apply(this, arguments);\\n      func = null;\\n      return memo;\\n    };\\n  };\\n\\n  // Returns the first function passed as an argument to the second,\\n  // allowing you to adjust arguments, run code before and after, and\\n  // conditionally execute the original function.\\n  _.wrap = function(func, wrapper) {\\n    return function() {\\n      var args = [func];\\n      push.apply(args, arguments);\\n      return wrapper.apply(this, args);\\n    };\\n  };\\n\\n  // Returns a function that is the composition of a list of functions, each\\n  // consuming the return value of the function that follows.\\n  _.compose = function() {\\n    var funcs = arguments;\\n    return function() {\\n      var args = arguments;\\n      for (var i = funcs.length - 1; i >= 0; i--) {\\n        args = [funcs[i].apply(this, args)];\\n      }\\n      return args[0];\\n    };\\n  };\\n\\n  // Returns a function that will only be executed after being called N times.\\n  _.after = function(times, func) {\\n    if (times <= 0) return func();\\n    return function() {\\n      if (--times < 1) {\\n        return func.apply(this, arguments);\\n      }\\n    };\\n  };\\n\\n  // Object Functions\\n  // ----------------\\n\\n  // Retrieve the names of an object's properties.\\n  // Delegates to **ECMAScript 5**'s native `Object.keys`\\n  _.keys = nativeKeys || function(obj) {\\n    if (obj !== Object(obj)) throw new TypeError('Invalid object');\\n    var keys = [];\\n    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;\\n    return keys;\\n  };\\n\\n  // Retrieve the values of an object's properties.\\n  _.values = function(obj) {\\n    var values = [];\\n    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);\\n    return values;\\n  };\\n\\n  // Convert an object into a list of `[key, value]` pairs.\\n  _.pairs = function(obj) {\\n    var pairs = [];\\n    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);\\n    return pairs;\\n  };\\n\\n  // Invert the keys and values of an object. The values must be serializable.\\n  _.invert = function(obj) {\\n    var result = {};\\n    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;\\n    return result;\\n  };\\n\\n  // Return a sorted list of the function names available on the object.\\n  // Aliased as `methods`\\n  _.functions = _.methods = function(obj) {\\n    var names = [];\\n    for (var key in obj) {\\n      if (_.isFunction(obj[key])) names.push(key);\\n    }\\n    return names.sort();\\n  };\\n\\n  // Extend a given object with all the properties in passed-in object(s).\\n  _.extend = function(obj) {\\n    each(slice.call(arguments, 1), function(source) {\\n      if (source) {\\n        for (var prop in source) {\\n          obj[prop] = source[prop];\\n        }\\n      }\\n    });\\n    return obj;\\n  };\\n\\n  // Return a copy of the object only containing the whitelisted properties.\\n  _.pick = function(obj) {\\n    var copy = {};\\n    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\\n    each(keys, function(key) {\\n      if (key in obj) copy[key] = obj[key];\\n    });\\n    return copy;\\n  };\\n\\n   // Return a copy of the object without the blacklisted properties.\\n  _.omit = function(obj) {\\n    var copy = {};\\n    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\\n    for (var key in obj) {\\n      if (!_.contains(keys, key)) copy[key] = obj[key];\\n    }\\n    return copy;\\n  };\\n\\n  // Fill in a given object with default properties.\\n  _.defaults = function(obj) {\\n    each(slice.call(arguments, 1), function(source) {\\n      if (source) {\\n        for (var prop in source) {\\n          if (obj[prop] == null) obj[prop] = source[prop];\\n        }\\n      }\\n    });\\n    return obj;\\n  };\\n\\n  // Create a (shallow-cloned) duplicate of an object.\\n  _.clone = function(obj) {\\n    if (!_.isObject(obj)) return obj;\\n    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\\n  };\\n\\n  // Invokes interceptor with the obj, and then returns obj.\\n  // The primary purpose of this method is to \\\"tap into\\\" a method chain, in\\n  // order to perform operations on intermediate results within the chain.\\n  _.tap = function(obj, interceptor) {\\n    interceptor(obj);\\n    return obj;\\n  };\\n\\n  // Internal recursive comparison function for `isEqual`.\\n  var eq = function(a, b, aStack, bStack) {\\n    // Identical objects are equal. `0 === -0`, but they aren't identical.\\n    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.\\n    if (a === b) return a !== 0 || 1 / a == 1 / b;\\n    // A strict comparison is necessary because `null == undefined`.\\n    if (a == null || b == null) return a === b;\\n    // Unwrap any wrapped objects.\\n    if (a instanceof _) a = a._wrapped;\\n    if (b instanceof _) b = b._wrapped;\\n    // Compare `[[Class]]` names.\\n    var className = toString.call(a);\\n    if (className != toString.call(b)) return false;\\n    switch (className) {\\n      // Strings, numbers, dates, and booleans are compared by value.\\n      case '[object String]':\\n        // Primitives and their corresponding object wrappers are equivalent; thus, `\\\"5\\\"` is\\n        // equivalent to `new String(\\\"5\\\")`.\\n        return a == String(b);\\n      case '[object Number]':\\n        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for\\n        // other numeric values.\\n        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);\\n      case '[object Date]':\\n      case '[object Boolean]':\\n        // Coerce dates and booleans to numeric primitive values. Dates are compared by their\\n        // millisecond representations. Note that invalid dates with millisecond representations\\n        // of `NaN` are not equivalent.\\n        return +a == +b;\\n      // RegExps are compared by their source patterns and flags.\\n      case '[object RegExp]':\\n        return a.source == b.source &&\\n               a.global == b.global &&\\n               a.multiline == b.multiline &&\\n               a.ignoreCase == b.ignoreCase;\\n    }\\n    if (typeof a != 'object' || typeof b != 'object') return false;\\n    // Assume equality for cyclic structures. The algorithm for detecting cyclic\\n    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\\n    var length = aStack.length;\\n    while (length--) {\\n      // Linear search. Performance is inversely proportional to the number of\\n      // unique nested structures.\\n      if (aStack[length] == a) return bStack[length] == b;\\n    }\\n    // Add the first object to the stack of traversed objects.\\n    aStack.push(a);\\n    bStack.push(b);\\n    var size = 0, result = true;\\n    // Recursively compare objects and arrays.\\n    if (className == '[object Array]') {\\n      // Compare array lengths to determine if a deep comparison is necessary.\\n      size = a.length;\\n      result = size == b.length;\\n      if (result) {\\n        // Deep compare the contents, ignoring non-numeric properties.\\n        while (size--) {\\n          if (!(result = eq(a[size], b[size], aStack, bStack))) break;\\n        }\\n      }\\n    } else {\\n      // Objects with different constructors are not equivalent, but `Object`s\\n      // from different frames are.\\n      var aCtor = a.constructor, bCtor = b.constructor;\\n      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&\\n                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {\\n        return false;\\n      }\\n      // Deep compare objects.\\n      for (var key in a) {\\n        if (_.has(a, key)) {\\n          // Count the expected number of properties.\\n          size++;\\n          // Deep compare each member.\\n          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;\\n        }\\n      }\\n      // Ensure that both objects contain the same number of properties.\\n      if (result) {\\n        for (key in b) {\\n          if (_.has(b, key) && !(size--)) break;\\n        }\\n        result = !size;\\n      }\\n    }\\n    // Remove the first object from the stack of traversed objects.\\n    aStack.pop();\\n    bStack.pop();\\n    return result;\\n  };\\n\\n  // Perform a deep comparison to check if two objects are equal.\\n  _.isEqual = function(a, b) {\\n    return eq(a, b, [], []);\\n  };\\n\\n  // Is a given array, string, or object empty?\\n  // An \\\"empty\\\" object has no enumerable own-properties.\\n  _.isEmpty = function(obj) {\\n    if (obj == null) return true;\\n    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;\\n    for (var key in obj) if (_.has(obj, key)) return false;\\n    return true;\\n  };\\n\\n  // Is a given value a DOM element?\\n  _.isElement = function(obj) {\\n    return !!(obj && obj.nodeType === 1);\\n  };\\n\\n  // Is a given value an array?\\n  // Delegates to ECMA5's native Array.isArray\\n  _.isArray = nativeIsArray || function(obj) {\\n    return toString.call(obj) == '[object Array]';\\n  };\\n\\n  // Is a given variable an object?\\n  _.isObject = function(obj) {\\n    return obj === Object(obj);\\n  };\\n\\n  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.\\n  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {\\n    _['is' + name] = function(obj) {\\n      return toString.call(obj) == '[object ' + name + ']';\\n    };\\n  });\\n\\n  // Define a fallback version of the method in browsers (ahem, IE), where\\n  // there isn't any inspectable \\\"Arguments\\\" type.\\n  if (!_.isArguments(arguments)) {\\n    _.isArguments = function(obj) {\\n      return !!(obj && _.has(obj, 'callee'));\\n    };\\n  }\\n\\n  // Optimize `isFunction` if appropriate.\\n  if (typeof (/./) !== 'function') {\\n    _.isFunction = function(obj) {\\n      return typeof obj === 'function';\\n    };\\n  }\\n\\n  // Is a given object a finite number?\\n  _.isFinite = function(obj) {\\n    return isFinite(obj) && !isNaN(parseFloat(obj));\\n  };\\n\\n  // Is the given value `NaN`? (NaN is the only number which does not equal itself).\\n  _.isNaN = function(obj) {\\n    return _.isNumber(obj) && obj != +obj;\\n  };\\n\\n  // Is a given value a boolean?\\n  _.isBoolean = function(obj) {\\n    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';\\n  };\\n\\n  // Is a given value equal to null?\\n  _.isNull = function(obj) {\\n    return obj === null;\\n  };\\n\\n  // Is a given variable undefined?\\n  _.isUndefined = function(obj) {\\n    return obj === void 0;\\n  };\\n\\n  // Shortcut function for checking if an object has a given property directly\\n  // on itself (in other words, not on a prototype).\\n  _.has = function(obj, key) {\\n    return hasOwnProperty.call(obj, key);\\n  };\\n\\n  // Utility Functions\\n  // -----------------\\n\\n  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\\n  // previous owner. Returns a reference to the Underscore object.\\n  _.noConflict = function() {\\n    root._ = previousUnderscore;\\n    return this;\\n  };\\n\\n  // Keep the identity function around for default iterators.\\n  _.identity = function(value) {\\n    return value;\\n  };\\n\\n  // Run a function **n** times.\\n  _.times = function(n, iterator, context) {\\n    var accum = Array(n);\\n    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);\\n    return accum;\\n  };\\n\\n  // Return a random integer between min and max (inclusive).\\n  _.random = function(min, max) {\\n    if (max == null) {\\n      max = min;\\n      min = 0;\\n    }\\n    return min + Math.floor(Math.random() * (max - min + 1));\\n  };\\n\\n  // List of HTML entities for escaping.\\n  var entityMap = {\\n    escape: {\\n      '&': '&amp;',\\n      '<': '&lt;',\\n      '>': '&gt;',\\n      '\\\"': '&quot;',\\n      \\\"'\\\": '&#x27;',\\n      '/': '&#x2F;'\\n    }\\n  };\\n  entityMap.unescape = _.invert(entityMap.escape);\\n\\n  // Regexes containing the keys and values listed immediately above.\\n  var entityRegexes = {\\n    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),\\n    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')\\n  };\\n\\n  // Functions for escaping and unescaping strings to/from HTML interpolation.\\n  _.each(['escape', 'unescape'], function(method) {\\n    _[method] = function(string) {\\n      if (string == null) return '';\\n      return ('' + string).replace(entityRegexes[method], function(match) {\\n        return entityMap[method][match];\\n      });\\n    };\\n  });\\n\\n  // If the value of the named property is a function then invoke it;\\n  // otherwise, return it.\\n  _.result = function(object, property) {\\n    if (object == null) return null;\\n    var value = object[property];\\n    return _.isFunction(value) ? value.call(object) : value;\\n  };\\n\\n  // Add your own custom functions to the Underscore object.\\n  _.mixin = function(obj) {\\n    each(_.functions(obj), function(name){\\n      var func = _[name] = obj[name];\\n      _.prototype[name] = function() {\\n        var args = [this._wrapped];\\n        push.apply(args, arguments);\\n        return result.call(this, func.apply(_, args));\\n      };\\n    });\\n  };\\n\\n  // Generate a unique integer id (unique within the entire client session).\\n  // Useful for temporary DOM ids.\\n  var idCounter = 0;\\n  _.uniqueId = function(prefix) {\\n    var id = ++idCounter + '';\\n    return prefix ? prefix + id : id;\\n  };\\n\\n  // By default, Underscore uses ERB-style template delimiters, change the\\n  // following template settings to use alternative delimiters.\\n  _.templateSettings = {\\n    evaluate    : /<%([\\\\s\\\\S]+?)%>/g,\\n    interpolate : /<%=([\\\\s\\\\S]+?)%>/g,\\n    escape      : /<%-([\\\\s\\\\S]+?)%>/g\\n  };\\n\\n  // When customizing `templateSettings`, if you don't want to define an\\n  // interpolation, evaluation or escaping regex, we need one that is\\n  // guaranteed not to match.\\n  var noMatch = /(.)^/;\\n\\n  // Certain characters need to be escaped so that they can be put into a\\n  // string literal.\\n  var escapes = {\\n    \\\"'\\\":      \\\"'\\\",\\n    '\\\\\\\\':     '\\\\\\\\',\\n    '\\\\r':     'r',\\n    '\\\\n':     'n',\\n    '\\\\t':     't',\\n    '\\\\u2028': 'u2028',\\n    '\\\\u2029': 'u2029'\\n  };\\n\\n  var escaper = /\\\\\\\\|'|\\\\r|\\\\n|\\\\t|\\\\u2028|\\\\u2029/g;\\n\\n  // JavaScript micro-templating, similar to John Resig's implementation.\\n  // Underscore templating handles arbitrary delimiters, preserves whitespace,\\n  // and correctly escapes quotes within interpolated code.\\n  _.template = function(text, data, settings) {\\n    var render;\\n    settings = _.defaults({}, settings, _.templateSettings);\\n\\n    // Combine delimiters into one regular expression via alternation.\\n    var matcher = new RegExp([\\n      (settings.escape || noMatch).source,\\n      (settings.interpolate || noMatch).source,\\n      (settings.evaluate || noMatch).source\\n    ].join('|') + '|$', 'g');\\n\\n    // Compile the template source, escaping string literals appropriately.\\n    var index = 0;\\n    var source = \\\"__p+='\\\";\\n    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {\\n      source += text.slice(index, offset)\\n        .replace(escaper, function(match) { return '\\\\\\\\' + escapes[match]; });\\n\\n      if (escape) {\\n        source += \\\"'+\\\\n((__t=(\\\" + escape + \\\"))==null?'':_.escape(__t))+\\\\n'\\\";\\n      }\\n      if (interpolate) {\\n        source += \\\"'+\\\\n((__t=(\\\" + interpolate + \\\"))==null?'':__t)+\\\\n'\\\";\\n      }\\n      if (evaluate) {\\n        source += \\\"';\\\\n\\\" + evaluate + \\\"\\\\n__p+='\\\";\\n      }\\n      index = offset + match.length;\\n      return match;\\n    });\\n    source += \\\"';\\\\n\\\";\\n\\n    // If a variable is not specified, place data values in local scope.\\n    if (!settings.variable) source = 'with(obj||{}){\\\\n' + source + '}\\\\n';\\n\\n    source = \\\"var __t,__p='',__j=Array.prototype.join,\\\" +\\n      \\\"print=function(){__p+=__j.call(arguments,'');};\\\\n\\\" +\\n      source + \\\"return __p;\\\\n\\\";\\n\\n    try {\\n      render = new Function(settings.variable || 'obj', '_', source);\\n    } catch (e) {\\n      e.source = source;\\n      throw e;\\n    }\\n\\n    if (data) return render(data, _);\\n    var template = function(data) {\\n      return render.call(this, data, _);\\n    };\\n\\n    // Provide the compiled function source as a convenience for precompilation.\\n    template.source = 'function(' + (settings.variable || 'obj') + '){\\\\n' + source + '}';\\n\\n    return template;\\n  };\\n\\n  // Add a \\\"chain\\\" function, which will delegate to the wrapper.\\n  _.chain = function(obj) {\\n    return _(obj).chain();\\n  };\\n\\n  // OOP\\n  // ---------------\\n  // If Underscore is called as a function, it returns a wrapped object that\\n  // can be used OO-style. This wrapper holds altered versions of all the\\n  // underscore functions. Wrapped objects may be chained.\\n\\n  // Helper function to continue chaining intermediate results.\\n  var result = function(obj) {\\n    return this._chain ? _(obj).chain() : obj;\\n  };\\n\\n  // Add all of the Underscore functions to the wrapper object.\\n  _.mixin(_);\\n\\n  // Add all mutator Array functions to the wrapper.\\n  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\\n    var method = ArrayProto[name];\\n    _.prototype[name] = function() {\\n      var obj = this._wrapped;\\n      method.apply(obj, arguments);\\n      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];\\n      return result.call(this, obj);\\n    };\\n  });\\n\\n  // Add all accessor Array functions to the wrapper.\\n  each(['concat', 'join', 'slice'], function(name) {\\n    var method = ArrayProto[name];\\n    _.prototype[name] = function() {\\n      return result.call(this, method.apply(this._wrapped, arguments));\\n    };\\n  });\\n\\n  _.extend(_.prototype, {\\n\\n    // Start chaining a wrapped Underscore object.\\n    chain: function() {\\n      this._chain = true;\\n      return this;\\n    },\\n\\n    // Extracts the result from a wrapped and chained object.\\n    value: function() {\\n      return this._wrapped;\\n    }\\n\\n  });\\n\\n}).call(this);\\n\\n//@ sourceURL=/node_modules/underscore/underscore.js\"));\nrequire.define(\"events\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],\"if (!process.EventEmitter) process.EventEmitter = function () {};\\n\\nvar EventEmitter = exports.EventEmitter = process.EventEmitter;\\nvar isArray = typeof Array.isArray === 'function'\\n    ? Array.isArray\\n    : function (xs) {\\n        return Object.prototype.toString.call(xs) === '[object Array]'\\n    }\\n;\\n\\n// By default EventEmitters will print a warning if more than\\n// 10 listeners are added to it. This is a useful default which\\n// helps finding memory leaks.\\n//\\n// Obviously not all Emitters should be limited to 10. This function allows\\n// that to be increased. Set to zero for unlimited.\\nvar defaultMaxListeners = 10;\\nEventEmitter.prototype.setMaxListeners = function(n) {\\n  if (!this._events) this._events = {};\\n  this._events.maxListeners = n;\\n};\\n\\n\\nEventEmitter.prototype.emit = function(type) {\\n  // If there is no 'error' event listener then throw.\\n  if (type === 'error') {\\n    if (!this._events || !this._events.error ||\\n        (isArray(this._events.error) && !this._events.error.length))\\n    {\\n      if (arguments[1] instanceof Error) {\\n        throw arguments[1]; // Unhandled 'error' event\\n      } else {\\n        throw new Error(\\\"Uncaught, unspecified 'error' event.\\\");\\n      }\\n      return false;\\n    }\\n  }\\n\\n  if (!this._events) return false;\\n  var handler = this._events[type];\\n  if (!handler) return false;\\n\\n  if (typeof handler == 'function') {\\n    switch (arguments.length) {\\n      // fast cases\\n      case 1:\\n        handler.call(this);\\n        break;\\n      case 2:\\n        handler.call(this, arguments[1]);\\n        break;\\n      case 3:\\n        handler.call(this, arguments[1], arguments[2]);\\n        break;\\n      // slower\\n      default:\\n        var args = Array.prototype.slice.call(arguments, 1);\\n        handler.apply(this, args);\\n    }\\n    return true;\\n\\n  } else if (isArray(handler)) {\\n    var args = Array.prototype.slice.call(arguments, 1);\\n\\n    var listeners = handler.slice();\\n    for (var i = 0, l = listeners.length; i < l; i++) {\\n      listeners[i].apply(this, args);\\n    }\\n    return true;\\n\\n  } else {\\n    return false;\\n  }\\n};\\n\\n// EventEmitter is defined in src/node_events.cc\\n// EventEmitter.prototype.emit() is also defined there.\\nEventEmitter.prototype.addListener = function(type, listener) {\\n  if ('function' !== typeof listener) {\\n    throw new Error('addListener only takes instances of Function');\\n  }\\n\\n  if (!this._events) this._events = {};\\n\\n  // To avoid recursion in the case that type == \\\"newListeners\\\"! Before\\n  // adding it to the listeners, first emit \\\"newListeners\\\".\\n  this.emit('newListener', type, listener);\\n\\n  if (!this._events[type]) {\\n    // Optimize the case of one listener. Don't need the extra array object.\\n    this._events[type] = listener;\\n  } else if (isArray(this._events[type])) {\\n\\n    // Check for listener leak\\n    if (!this._events[type].warned) {\\n      var m;\\n      if (this._events.maxListeners !== undefined) {\\n        m = this._events.maxListeners;\\n      } else {\\n        m = defaultMaxListeners;\\n      }\\n\\n      if (m && m > 0 && this._events[type].length > m) {\\n        this._events[type].warned = true;\\n        console.error('(node) warning: possible EventEmitter memory ' +\\n                      'leak detected. %d listeners added. ' +\\n                      'Use emitter.setMaxListeners() to increase limit.',\\n                      this._events[type].length);\\n        console.trace();\\n      }\\n    }\\n\\n    // If we've already got an array, just append.\\n    this._events[type].push(listener);\\n  } else {\\n    // Adding the second element, need to change to array.\\n    this._events[type] = [this._events[type], listener];\\n  }\\n\\n  return this;\\n};\\n\\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\\n\\nEventEmitter.prototype.once = function(type, listener) {\\n  var self = this;\\n  self.on(type, function g() {\\n    self.removeListener(type, g);\\n    listener.apply(this, arguments);\\n  });\\n\\n  return this;\\n};\\n\\nEventEmitter.prototype.removeListener = function(type, listener) {\\n  if ('function' !== typeof listener) {\\n    throw new Error('removeListener only takes instances of Function');\\n  }\\n\\n  // does not use listeners(), so no side effect of creating _events[type]\\n  if (!this._events || !this._events[type]) return this;\\n\\n  var list = this._events[type];\\n\\n  if (isArray(list)) {\\n    var i = list.indexOf(listener);\\n    if (i < 0) return this;\\n    list.splice(i, 1);\\n    if (list.length == 0)\\n      delete this._events[type];\\n  } else if (this._events[type] === listener) {\\n    delete this._events[type];\\n  }\\n\\n  return this;\\n};\\n\\nEventEmitter.prototype.removeAllListeners = function(type) {\\n  // does not use listeners(), so no side effect of creating _events[type]\\n  if (type && this._events && this._events[type]) this._events[type] = null;\\n  return this;\\n};\\n\\nEventEmitter.prototype.listeners = function(type) {\\n  if (!this._events) this._events = {};\\n  if (!this._events[type]) this._events[type] = [];\\n  if (!isArray(this._events[type])) {\\n    this._events[type] = [this._events[type]];\\n  }\\n  return this._events[type];\\n};\\n\\n//@ sourceURL=events\"));\nrequire.define(\"/src/shared/vars.js\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],'// jshint -W001\\n\\n\"use strict\";\\n\\n// Identifiers provided by the ECMAScript standard.\\n\\nexports.reservedVars = {\\n\targuments : false,\\n\tNaN       : false\\n};\\n\\nexports.ecmaIdentifiers = {\\n\tArray              : false,\\n\tBoolean            : false,\\n\tDate               : false,\\n\tdecodeURI          : false,\\n\tdecodeURIComponent : false,\\n\tencodeURI          : false,\\n\tencodeURIComponent : false,\\n\tError              : false,\\n\t\"eval\"             : false,\\n\tEvalError          : false,\\n\tFunction           : false,\\n\thasOwnProperty     : false,\\n\tisFinite           : false,\\n\tisNaN              : false,\\n\tJSON               : false,\\n\tMath               : false,\\n\tMap                : false,\\n\tNumber             : false,\\n\tObject             : false,\\n\tparseInt           : false,\\n\tparseFloat         : false,\\n\tRangeError         : false,\\n\tReferenceError     : false,\\n\tRegExp             : false,\\n\tSet                : false,\\n\tString             : false,\\n\tSyntaxError        : false,\\n\tTypeError          : false,\\n\tURIError           : false,\\n\tWeakMap            : false\\n};\\n\\n// Global variables commonly provided by a web browser environment.\\n\\nexports.browser = {\\n\tArrayBuffer          : false,\\n\tArrayBufferView      : false,\\n\tAudio                : false,\\n\tBlob                 : false,\\n\taddEventListener     : false,\\n\tapplicationCache     : false,\\n\tatob                 : false,\\n\tblur                 : false,\\n\tbtoa                 : false,\\n\tclearInterval        : false,\\n\tclearTimeout         : false,\\n\tclose                : false,\\n\tclosed               : false,\\n\tDataView             : false,\\n\tDOMParser            : false,\\n\tdefaultStatus        : false,\\n\tdocument             : false,\\n\tElement              : false,\\n\tevent                : false,\\n\tFileReader           : false,\\n\tFloat32Array         : false,\\n\tFloat64Array         : false,\\n\tFormData             : false,\\n\tfocus                : false,\\n\tframes               : false,\\n\tgetComputedStyle     : false,\\n\tHTMLElement          : false,\\n\tHTMLAnchorElement    : false,\\n\tHTMLBaseElement      : false,\\n\tHTMLBlockquoteElement: false,\\n\tHTMLBodyElement      : false,\\n\tHTMLBRElement        : false,\\n\tHTMLButtonElement    : false,\\n\tHTMLCanvasElement    : false,\\n\tHTMLDirectoryElement : false,\\n\tHTMLDivElement       : false,\\n\tHTMLDListElement     : false,\\n\tHTMLFieldSetElement  : false,\\n\tHTMLFontElement      : false,\\n\tHTMLFormElement      : false,\\n\tHTMLFrameElement     : false,\\n\tHTMLFrameSetElement  : false,\\n\tHTMLHeadElement      : false,\\n\tHTMLHeadingElement   : false,\\n\tHTMLHRElement        : false,\\n\tHTMLHtmlElement      : false,\\n\tHTMLIFrameElement    : false,\\n\tHTMLImageElement     : false,\\n\tHTMLInputElement     : false,\\n\tHTMLIsIndexElement   : false,\\n\tHTMLLabelElement     : false,\\n\tHTMLLayerElement     : false,\\n\tHTMLLegendElement    : false,\\n\tHTMLLIElement        : false,\\n\tHTMLLinkElement      : false,\\n\tHTMLMapElement       : false,\\n\tHTMLMenuElement      : false,\\n\tHTMLMetaElement      : false,\\n\tHTMLModElement       : false,\\n\tHTMLObjectElement    : false,\\n\tHTMLOListElement     : false,\\n\tHTMLOptGroupElement  : false,\\n\tHTMLOptionElement    : false,\\n\tHTMLParagraphElement : false,\\n\tHTMLParamElement     : false,\\n\tHTMLPreElement       : false,\\n\tHTMLQuoteElement     : false,\\n\tHTMLScriptElement    : false,\\n\tHTMLSelectElement    : false,\\n\tHTMLStyleElement     : false,\\n\tHTMLTableCaptionElement: false,\\n\tHTMLTableCellElement : false,\\n\tHTMLTableColElement  : false,\\n\tHTMLTableElement     : false,\\n\tHTMLTableRowElement  : false,\\n\tHTMLTableSectionElement: false,\\n\tHTMLTextAreaElement  : false,\\n\tHTMLTitleElement     : false,\\n\tHTMLUListElement     : false,\\n\tHTMLVideoElement     : false,\\n\thistory              : false,\\n\tInt16Array           : false,\\n\tInt32Array           : false,\\n\tInt8Array            : false,\\n\tImage                : false,\\n\tlength               : false,\\n\tlocalStorage         : false,\\n\tlocation             : false,\\n\tMessageChannel       : false,\\n\tMessageEvent         : false,\\n\tMessagePort          : false,\\n\tmoveBy               : false,\\n\tmoveTo               : false,\\n\tMutationObserver     : false,\\n\tname                 : false,\\n\tNode                 : false,\\n\tNodeFilter           : false,\\n\tnavigator            : false,\\n\tonbeforeunload       : true,\\n\tonblur               : true,\\n\tonerror              : true,\\n\tonfocus              : true,\\n\tonload               : true,\\n\tonresize             : true,\\n\tonunload             : true,\\n\topen                 : false,\\n\topenDatabase         : false,\\n\topener               : false,\\n\tOption               : false,\\n\tparent               : false,\\n\tprint                : false,\\n\tremoveEventListener  : false,\\n\tresizeBy             : false,\\n\tresizeTo             : false,\\n\tscreen               : false,\\n\tscroll               : false,\\n\tscrollBy             : false,\\n\tscrollTo             : false,\\n\tsessionStorage       : false,\\n\tsetInterval          : false,\\n\tsetTimeout           : false,\\n\tSharedWorker         : false,\\n\tstatus               : false,\\n\ttop                  : false,\\n\tUint16Array          : false,\\n\tUint32Array          : false,\\n\tUint8Array           : false,\\n\tUint8ClampedArray    : false,\\n\tWebSocket            : false,\\n\twindow               : false,\\n\tWorker               : false,\\n\tXMLHttpRequest       : false,\\n\tXMLSerializer        : false,\\n\tXPathEvaluator       : false,\\n\tXPathException       : false,\\n\tXPathExpression      : false,\\n\tXPathNamespace       : false,\\n\tXPathNSResolver      : false,\\n\tXPathResult          : false\\n};\\n\\nexports.devel = {\\n\talert  : false,\\n\tconfirm: false,\\n\tconsole: false,\\n\tDebug  : false,\\n\topera  : false,\\n\tprompt : false\\n};\\n\\nexports.worker = {\\n\timportScripts: true,\\n\tpostMessage  : true,\\n\tself         : true\\n};\\n\\n// Widely adopted global names that are not part of ECMAScript standard\\nexports.nonstandard = {\\n\tescape  : false,\\n\tunescape: false\\n};\\n\\n// Globals provided by popular JavaScript environments.\\n\\nexports.couch = {\\n\t\"require\" : false,\\n\trespond   : false,\\n\tgetRow    : false,\\n\temit      : false,\\n\tsend      : false,\\n\tstart     : false,\\n\tsum       : false,\\n\tlog       : false,\\n\texports   : false,\\n\tmodule    : false,\\n\tprovides  : false\\n};\\n\\nexports.node = {\\n\t__filename   : false,\\n\t__dirname    : false,\\n\tBuffer       : false,\\n\tDataView     : false,\\n\tconsole      : false,\\n\texports      : true,  // In Node it is ok to exports = module.exports = foo();\\n\tGLOBAL       : false,\\n\tglobal       : false,\\n\tmodule       : false,\\n\tprocess      : false,\\n\trequire      : false,\\n\tsetTimeout   : false,\\n\tclearTimeout : false,\\n\tsetInterval  : false,\\n\tclearInterval: false\\n};\\n\\nexports.phantom = {\\n\tphantom      : true,\\n\trequire      : true,\\n\tWebPage      : true\\n};\\n\\nexports.rhino = {\\n\tdefineClass  : false,\\n\tdeserialize  : false,\\n\tgc           : false,\\n\thelp         : false,\\n\timportPackage: false,\\n\t\"java\"       : false,\\n\tload         : false,\\n\tloadClass    : false,\\n\tprint        : false,\\n\tquit         : false,\\n\treadFile     : false,\\n\treadUrl      : false,\\n\trunCommand   : false,\\n\tseal         : false,\\n\tserialize    : false,\\n\tspawn        : false,\\n\tsync         : false,\\n\ttoint32      : false,\\n\tversion      : false\\n};\\n\\nexports.wsh = {\\n\tActiveXObject            : true,\\n\tEnumerator               : true,\\n\tGetObject                : true,\\n\tScriptEngine             : true,\\n\tScriptEngineBuildVersion : true,\\n\tScriptEngineMajorVersion : true,\\n\tScriptEngineMinorVersion : true,\\n\tVBArray                  : true,\\n\tWSH                      : true,\\n\tWScript                  : true,\\n\tXDomainRequest           : true\\n};\\n\\n// Globals provided by popular JavaScript libraries.\\n\\nexports.dojo = {\\n\tdojo     : false,\\n\tdijit    : false,\\n\tdojox    : false,\\n\tdefine\t : false,\\n\t\"require\": false\\n};\\n\\nexports.jquery = {\\n\t\"$\"    : false,\\n\tjQuery : false\\n};\\n\\nexports.mootools = {\\n\t\"$\"           : false,\\n\t\"$$\"          : false,\\n\tAsset         : false,\\n\tBrowser       : false,\\n\tChain         : false,\\n\tClass         : false,\\n\tColor         : false,\\n\tCookie        : false,\\n\tCore          : false,\\n\tDocument      : false,\\n\tDomReady      : false,\\n\tDOMEvent      : false,\\n\tDOMReady      : false,\\n\tDrag          : false,\\n\tElement       : false,\\n\tElements      : false,\\n\tEvent         : false,\\n\tEvents        : false,\\n\tFx            : false,\\n\tGroup         : false,\\n\tHash          : false,\\n\tHtmlTable     : false,\\n\tIframe        : false,\\n\tIframeShim    : false,\\n\tInputValidator: false,\\n\tinstanceOf    : false,\\n\tKeyboard      : false,\\n\tLocale        : false,\\n\tMask          : false,\\n\tMooTools      : false,\\n\tNative        : false,\\n\tOptions       : false,\\n\tOverText      : false,\\n\tRequest       : false,\\n\tScroller      : false,\\n\tSlick         : false,\\n\tSlider        : false,\\n\tSortables     : false,\\n\tSpinner       : false,\\n\tSwiff         : false,\\n\tTips          : false,\\n\tType          : false,\\n\ttypeOf        : false,\\n\tURI           : false,\\n\tWindow        : false\\n};\\n\\nexports.prototypejs = {\\n\t\"$\"               : false,\\n\t\"$$\"              : false,\\n\t\"$A\"              : false,\\n\t\"$F\"              : false,\\n\t\"$H\"              : false,\\n\t\"$R\"              : false,\\n\t\"$break\"          : false,\\n\t\"$continue\"       : false,\\n\t\"$w\"              : false,\\n\tAbstract          : false,\\n\tAjax              : false,\\n\tClass             : false,\\n\tEnumerable        : false,\\n\tElement           : false,\\n\tEvent             : false,\\n\tField             : false,\\n\tForm              : false,\\n\tHash              : false,\\n\tInsertion         : false,\\n\tObjectRange       : false,\\n\tPeriodicalExecuter: false,\\n\tPosition          : false,\\n\tPrototype         : false,\\n\tSelector          : false,\\n\tTemplate          : false,\\n\tToggle            : false,\\n\tTry               : false,\\n\tAutocompleter     : false,\\n\tBuilder           : false,\\n\tControl           : false,\\n\tDraggable         : false,\\n\tDraggables        : false,\\n\tDroppables        : false,\\n\tEffect            : false,\\n\tSortable          : false,\\n\tSortableObserver  : false,\\n\tSound             : false,\\n\tScriptaculous     : false\\n};\\n\\nexports.yui = {\\n\tYUI       : false,\\n\tY         : false,\\n\tYUI_config: false\\n};\\n\\n\\n//@ sourceURL=/src/shared/vars.js'));\nrequire.define(\"/src/shared/messages.js\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],'\"use strict\";\\n\\nvar _ = require(\"underscore\");\\n\\nvar errors = {\\n\t// JSHint options\\n\tE001: \"Bad option: \\'{a}\\'.\",\\n\tE002: \"Bad option value.\",\\n\\n\t// JSHint input\\n\tE003: \"Expected a JSON value.\",\\n\tE004: \"Input is neither a string nor an array of strings.\",\\n\tE005: \"Input is empty.\",\\n\tE006: \"Unexpected early end of program.\",\\n\\n\t// Strict mode\\n\tE007: \"Missing \\\\\"use strict\\\\\" statement.\",\\n\tE008: \"Strict violation.\",\\n\tE009: \"Option \\'validthis\\' can\\'t be used in a global scope.\",\\n\tE010: \"\\'with\\' is not allowed in strict mode.\",\\n\\n\t// Constants\\n\tE011: \"const \\'{a}\\' has already been declared.\",\\n\tE012: \"const \\'{a}\\' is initialized to \\'undefined\\'.\",\\n\tE013: \"Attempting to override \\'{a}\\' which is a constant.\",\\n\\n\t// Regular expressions\\n\tE014: \"A regular expression literal can be confused with \\'/=\\'.\",\\n\tE015: \"Unclosed regular expression.\",\\n\tE016: \"Invalid regular expression.\",\\n\\n\t// Tokens\\n\tE017: \"Unclosed comment.\",\\n\tE018: \"Unbegun comment.\",\\n\tE019: \"Unmatched \\'{a}\\'.\",\\n\tE020: \"Expected \\'{a}\\' to match \\'{b}\\' from line {c} and instead saw \\'{d}\\'.\",\\n\tE021: \"Expected \\'{a}\\' and instead saw \\'{b}\\'.\",\\n\tE022: \"Line breaking error \\'{a}\\'.\",\\n\tE023: \"Missing \\'{a}\\'.\",\\n\tE024: \"Unexpected \\'{a}\\'.\",\\n\tE025: \"Missing \\':\\' on a case clause.\",\\n\tE026: \"Missing \\'}\\' to match \\'{\\' from line {a}.\",\\n\tE027: \"Missing \\']\\' to match \\'[\\' form line {a}.\",\\n\tE028: \"Illegal comma.\",\\n\tE029: \"Unclosed string.\",\\n\\n\t// Everything else\\n\tE030: \"Expected an identifier and instead saw \\'{a}\\'.\",\\n\tE031: \"Bad assignment.\", // FIXME: Rephrase\\n\tE032: \"Expected a small integer and instead saw \\'{a}\\'.\",\\n\tE033: \"Expected an operator and instead saw \\'{a}\\'.\",\\n\tE034: \"get/set are ES5 features.\",\\n\tE035: \"Missing property name.\",\\n\tE036: \"Expected to see a statement and instead saw a block.\",\\n\tE037: \"Constant {a} was not declared correctly.\",\\n\tE038: \"Variable {a} was not declared correctly.\",\\n\tE039: \"Function declarations are not invocable. Wrap the whole function invocation in parens.\",\\n\tE040: \"Each value should have its own case label.\",\\n\tE041: \"Unrecoverable syntax error.\",\\n\tE042: \"Stopping.\",\\n\tE043: \"Too many errors.\"\\n};\\n\\nvar warnings = {\\n\tW001: \"\\'hasOwnProperty\\' is a really bad name.\",\\n\tW002: \"Value of \\'{a}\\' may be overwritten in IE.\",\\n\tW003: \"\\'{a}\\' was used before it was defined.\",\\n\tW004: \"\\'{a}\\' is already defined.\",\\n\tW005: \"A dot following a number can be confused with a decimal point.\",\\n\tW006: \"Confusing minuses.\",\\n\tW007: \"Confusing pluses.\",\\n\tW008: \"A leading decimal point can be confused with a dot: \\'{a}\\'.\",\\n\tW009: \"The array literal notation [] is preferrable.\",\\n\tW010: \"The object literal notation {} is preferrable.\",\\n\tW011: \"Unexpected space after \\'{a}\\'.\",\\n\tW012: \"Unexpected space before \\'{a}\\'.\",\\n\tW013: \"Missing space after \\'{a}\\'.\",\\n\tW014: \"Bad line breaking before \\'{a}\\'.\",\\n\tW015: \"Expected \\'{a}\\' to have an indentation at {b} instead at {c}.\",\\n\tW016: \"Unexpected use of \\'{a}\\'.\",\\n\tW017: \"Bad operand.\",\\n\tW018: \"Confusing use of \\'{a}\\'.\",\\n\tW019: \"Use the isNaN function to compare with NaN.\",\\n\tW020: \"Read only.\",\\n\tW021: \"\\'{a}\\' is a function.\",\\n\tW022: \"Do not assign to the exception parameter.\",\\n\tW023: \"Expected an identifier in an assignment and instead saw a function invocation.\",\\n\tW024: \"Expected an identifier and instead saw \\'{a}\\' (a reserved word).\",\\n\tW025: \"Missing name in function declaration.\",\\n\tW026: \"Inner functions should be listed at the top of the outer function.\",\\n\tW027: \"Unreachable \\'{a}\\' after \\'{b}\\'.\",\\n\tW028: \"Label \\'{a}\\' on {b} statement.\",\\n\tW029: \"Label \\'{a}\\' looks like a javascript url.\",\\n\tW030: \"Expected an assignment or function call and instead saw an expression.\",\\n\tW031: \"Do not use \\'new\\' for side effects.\",\\n\tW032: \"Unnecessary semicolon.\",\\n\tW033: \"Missing semicolon.\",\\n\tW034: \"Unnecessary directive \\\\\"{a}\\\\\".\",\\n\tW035: \"Empty block.\",\\n\tW036: \"Unexpected /*member \\'{a}\\'.\",\\n\tW037: \"\\'{a}\\' is a statement label.\",\\n\tW038: \"\\'{a}\\' used out of scope.\",\\n\tW039: \"\\'{a}\\' is not allowed.\",\\n\tW040: \"Possible strict violation.\",\\n\tW041: \"Use \\'{a}\\' to compare with \\'{b}\\'.\",\\n\tW042: \"Avoid EOL escaping.\",\\n\tW043: \"Bad escaping of EOL. Use option multistr if needed.\",\\n\tW044: \"Bad escaping.\",\\n\tW045: \"Bad number \\'{a}\\'.\",\\n\tW046: \"Don\\'t use extra leading zeros \\'{a}\\'.\",\\n\tW047: \"A trailing decimal point can be confused with a dot: \\'{a}\\'.\",\\n\tW048: \"Unexpected control character in regular expression.\",\\n\tW049: \"Unexpected escaped character \\'{a}\\' in regular expression.\",\\n\tW050: \"JavaScript URL.\",\\n\tW051: \"Variables should not be deleted.\",\\n\tW052: \"Unexpected \\'{a}\\'.\",\\n\tW053: \"Do not use {a} as a constructor.\",\\n\tW054: \"The Function constructor is a form of eval.\",\\n\tW055: \"A constructor name should start with an uppercase letter.\",\\n\tW056: \"Bad constructor.\",\\n\tW057: \"Weird construction. Is \\'new\\' unnecessary?\",\\n\tW058: \"Missing \\'()\\' invoking a constructor.\",\\n\tW059: \"Avoid arguments.{a}.\",\\n\tW060: \"document.write can be a form of eval.\",\\n\tW061: \"eval can be harmful.\",\\n\tW062: \"Wrap an immediate function invocation in parens \" +\\n\t\t\"to assist the reader in understanding that the expression \" +\\n\t\t\"is the result of a function, and not the function itself.\",\\n\tW063: \"Math is not a function.\",\\n\tW064: \"Missing \\'new\\' prefix when invoking a constructor.\",\\n\tW065: \"Missing radix parameter.\",\\n\tW066: \"Implied eval. Consider passing a function instead of a string.\",\\n\tW067: \"Bad invocation.\",\\n\tW068: \"Wrapping non-IIFE function literals in parens is unnecessary.\",\\n\tW069: \"[\\'{a}\\'] is better written in dot notation.\",\\n\tW070: \"Extra comma. (it breaks older versions of IE)\",\\n\tW071: \"This function has too many statements. ({a})\",\\n\tW072: \"This function has too many parameters. ({a})\",\\n\tW073: \"Blocks are nested too deeply. ({a})\",\\n\tW074: \"This function\\'s cyclomatic complexity is too high. ({a})\",\\n\tW075: \"Duplicate key \\'{a}\\'.\",\\n\tW076: \"Unexpected parameter \\'{a}\\' in get {b} function.\",\\n\tW077: \"Expected a single parameter in set {a} function.\",\\n\tW078: \"Setter is defined without getter.\",\\n\tW079: \"Redefinition of \\'{a}\\'.\",\\n\tW080: \"It\\'s not necessary to initialize \\'{a}\\' to \\'undefined\\'.\",\\n\tW081: \"Too many var statements.\",\\n\tW082: \"Function declarations should not be placed in blocks. \" +\\n\t\t\"Use a function expression or move the statement to the top of \" +\\n\t\t\"the outer function.\",\\n\tW083: \"Don\\'t make functions within a loop.\",\\n\tW084: \"Expected a conditional expression and instead saw an assignment.\",\\n\tW085: \"Don\\'t use \\'with\\'.\",\\n\tW086: \"Expected a \\'break\\' statement before \\'{a}\\'.\",\\n\tW087: \"Forgotten \\'debugger\\' statement?\",\\n\tW088: \"Creating global \\'for\\' variable. Should be \\'for (var {a} ...\\'.\",\\n\tW089: \"The body of a for in should be wrapped in an if statement to filter \" +\\n\t\t\"unwanted properties from the prototype.\",\\n\tW090: \"\\'{a}\\' is not a statement label.\",\\n\tW091: \"\\'{a}\\' is out of scope.\",\\n\tW092: \"Wrap the /regexp/ literal in parens to disambiguate the slash operator.\",\\n\tW093: \"Did you mean to return a conditional instead of an assignment?\",\\n\tW094: \"Unexpected comma.\",\\n\tW095: \"Expected a string and instead saw {a}.\",\\n\tW096: \"The \\'{a}\\' key may produce unexpected results.\",\\n\tW097: \"Use the function form of \\\\\"use strict\\\\\".\",\\n\tW098: \"\\'{a}\\' is defined but never used.\",\\n\tW099: \"Mixed spaces and tabs.\",\\n\tW100: \"This character may get silently deleted by one or more browsers.\",\\n\tW101: \"Line is too long.\",\\n\tW102: \"Trailing whitespace.\",\\n\tW103: \"The \\'{a}\\' property is deprecated.\",\\n\tW104: \"\\'{a}\\' is only available in JavaScript 1.7.\",\\n\tW105: \"Unexpected {a} in \\'{b}\\'.\",\\n\tW106: \"Identifier \\'{a}\\' is not in camel case.\",\\n\tW107: \"Script URL.\",\\n\tW108: \"Strings must use doublequote.\",\\n\tW109: \"Strings must use singlequote.\",\\n\tW110: \"Mixed double and single quotes.\",\\n\tW112: \"Unclosed string.\",\\n\tW113: \"Control character in string: {a}.\",\\n\tW114: \"Avoid {a}.\",\\n\tW115: \"Octal literals are not allowed in strict mode.\",\\n\tW116: \"Expected \\'{a}\\' and instead saw \\'{b}\\'.\",\\n\tW117: \"\\'{a}\\' is not defined.\",\\n};\\n\\nvar info = {\\n\tI001: \"Comma warnings can be turned off with \\'laxcomma\\'.\"\\n};\\n\\nexports.errors = {};\\nexports.warnings = {};\\nexports.info = {};\\n\\n_.each(errors, function (desc, code) {\\n\texports.errors[code] = { code: code, desc: desc };\\n});\\n\\n_.each(warnings, function (desc, code) {\\n\texports.warnings[code] = { code: code, desc: desc };\\n});\\n\\n_.each(info, function (desc, code) {\\n\texports.info[code] = { code: code, desc: desc };\\n});\\n\\n//@ sourceURL=/src/shared/messages.js'));\nrequire.define(\"/src/stable/lex.js\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],'/*\\n * Lexical analysis and token construction.\\n */\\n\\n\"use strict\";\\n\\nvar _      = require(\"underscore\");\\nvar events = require(\"events\");\\nvar reg    = require(\"./reg.js\");\\nvar state  = require(\"./state.js\").state;\\n\\n// Some of these token types are from JavaScript Parser API\\n// while others are specific to JSHint parser.\\n// JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API\\n\\nvar Token = {\\n\tIdentifier: 1,\\n\tPunctuator: 2,\\n\tNumericLiteral: 3,\\n\tStringLiteral: 4,\\n\tComment: 5,\\n\tKeyword: 6,\\n\tNullLiteral: 7,\\n\tBooleanLiteral: 8,\\n\tRegExp: 9\\n};\\n\\n// This is auto generated from the unicode tables.\\n// The tables are at:\\n// http://www.fileformat.info/info/unicode/category/Lu/list.htm\\n// http://www.fileformat.info/info/unicode/category/Ll/list.htm\\n// http://www.fileformat.info/info/unicode/category/Lt/list.htm\\n// http://www.fileformat.info/info/unicode/category/Lm/list.htm\\n// http://www.fileformat.info/info/unicode/category/Lo/list.htm\\n// http://www.fileformat.info/info/unicode/category/Nl/list.htm\\n\\nvar unicodeLetterTable = [\\n\t170, 170, 181, 181, 186, 186, 192, 214,\\n\t216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,\\n\t880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,\\n\t910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,\\n\t1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,\\n\t1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,\\n\t1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,\\n\t1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,\\n\t2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,\\n\t2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,\\n\t2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,\\n\t2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,\\n\t2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,\\n\t2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,\\n\t2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,\\n\t2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,\\n\t2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,\\n\t2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,\\n\t2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,\\n\t2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,\\n\t3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,\\n\t3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,\\n\t3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,\\n\t3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,\\n\t3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,\\n\t3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,\\n\t3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,\\n\t3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,\\n\t3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,\\n\t3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,\\n\t3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,\\n\t4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,\\n\t4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,\\n\t4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,\\n\t4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,\\n\t4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,\\n\t4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,\\n\t5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,\\n\t5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,\\n\t6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,\\n\t6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,\\n\t6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,\\n\t6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,\\n\t7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,\\n\t7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,\\n\t8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,\\n\t8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,\\n\t8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,\\n\t8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,\\n\t8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,\\n\t8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,\\n\t8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,\\n\t11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,\\n\t11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,\\n\t11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,\\n\t11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,\\n\t12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,\\n\t12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,\\n\t12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,\\n\t19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,\\n\t42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,\\n\t42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,\\n\t42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,\\n\t43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,\\n\t43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,\\n\t43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,\\n\t43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,\\n\t43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,\\n\t43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,\\n\t43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,\\n\t43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,\\n\t55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,\\n\t64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,\\n\t64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,\\n\t64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,\\n\t64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,\\n\t65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,\\n\t65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,\\n\t65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,\\n\t65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,\\n\t65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,\\n\t66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,\\n\t66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,\\n\t67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,\\n\t67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,\\n\t68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,\\n\t68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,\\n\t69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,\\n\t92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,\\n\t119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,\\n\t119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,\\n\t120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,\\n\t120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,\\n\t120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,\\n\t120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,\\n\t120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,\\n\t131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,\\n\t177984, 177984, 178205, 178205, 194560, 195101\\n];\\n\\nvar identifierStartTable = [];\\n\\nfor (var i = 0; i < 128; i++) {\\n\tidentifierStartTable[i] =\\n\t\ti === 36 ||           // $\\n\t\ti >= 65 && i <= 90 || // A-Z\\n\t\ti === 95 ||           // _\\n\t\ti >= 97 && i <= 122;  // a-z\\n}\\n\\nvar identifierPartTable = [];\\n\\nfor (var i = 0; i < 128; i++) {\\n\tidentifierPartTable[i] =\\n\t\tidentifierStartTable[i] || // $, _, A-Z, a-z\\n\t\ti >= 48 && i <= 57;        // 0-9\\n}\\n\\n/*\\n * Lexer for JSHint.\\n *\\n * This object does a char-by-char scan of the provided source code\\n * and produces a sequence of tokens.\\n *\\n *   var lex = new Lexer(\"var i = 0;\");\\n *   lex.start();\\n *   lex.token(); // returns the next token\\n *\\n * You have to use the token() method to move the lexer forward\\n * but you don\\'t have to use its return value to get tokens. In addition\\n * to token() method returning the next token, the Lexer object also\\n * emits events.\\n *\\n *   lex.on(\"Identifier\", function (data) {\\n *     if (data.name.indexOf(\"_\") >= 0) {\\n *       // Produce a warning.\\n *     }\\n *   });\\n *\\n * Note that the token() method returns tokens in a JSLint-compatible\\n * format while the event emitter uses a slightly modified version of\\n * Mozilla\\'s JavaScript Parser API. Eventually, we will move away from\\n * JSLint format.\\n */\\nfunction Lexer(source) {\\n\tvar lines = source;\\n\\n\tif (typeof lines === \"string\") {\\n\t\tlines = lines\\n\t\t\t.replace(/\\\\r\\\\n/g, \"\\\\n\")\\n\t\t\t.replace(/\\\\r/g, \"\\\\n\")\\n\t\t\t.split(\"\\\\n\");\\n\t}\\n\\n\t// If the first line is a shebang (#!), make it a blank and move on.\\n\t// Shebangs are used by Node scripts.\\n\\n\tif (lines[0] && lines[0].substr(0, 2) === \"#!\") {\\n\t\tlines[0] = \"\";\\n\t}\\n\\n\tthis.emitter = new events.EventEmitter();\\n\tthis.source = source;\\n\tthis.lines = lines;\\n\tthis.prereg = true;\\n\\n\tthis.line = 0;\\n\tthis.char = 1;\\n\tthis.from = 1;\\n\tthis.input = \"\";\\n\\n\tfor (var i = 0; i < state.option.indent; i += 1) {\\n\t\tstate.tab += \" \";\\n\t}\\n}\\n\\nLexer.prototype = {\\n\t_lines: [],\\n\\n\tget lines() {\\n\t\tthis._lines = state.lines;\\n\t\treturn this._lines;\\n\t},\\n\\n\tset lines(val) {\\n\t\tthis._lines = val;\\n\t\tstate.lines = this._lines;\\n\t},\\n\\n\t/*\\n\t * Return the next i character without actually moving the\\n\t * char pointer.\\n\t */\\n\tpeek: function (i) {\\n\t\treturn this.input.charAt(i || 0);\\n\t},\\n\\n\t/*\\n\t * Move the char pointer forward i times.\\n\t */\\n\tskip: function (i) {\\n\t\ti = i || 1;\\n\t\tthis.char += i;\\n\t\tthis.input = this.input.slice(i);\\n\t},\\n\\n\t/*\\n\t * Subscribe to a token event. The API for this method is similar\\n\t * Underscore.js i.e. you can subscribe to multiple events with\\n\t * one call:\\n\t *\\n\t *   lex.on(\"Identifier Number\", function (data) {\\n\t *     // ...\\n\t *   });\\n\t */\\n\ton: function (names, listener) {\\n\t\tnames.split(\" \").forEach(function (name) {\\n\t\t\tthis.emitter.on(name, listener);\\n\t\t}.bind(this));\\n\t},\\n\\n\t/*\\n\t * Trigger a token event. All arguments will be passed to each\\n\t * listener.\\n\t */\\n\ttrigger: function () {\\n\t\tthis.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));\\n\t},\\n\\n\t/*\\n\t * Extract a punctuator out of the next sequence of characters\\n\t * or return \\'null\\' if its not possible.\\n\t *\\n\t * This method\\'s implementation was heavily influenced by the\\n\t * scanPunctuator function in the Esprima parser\\'s source code.\\n\t */\\n\tscanPunctuator: function () {\\n\t\tvar ch1 = this.peek();\\n\t\tvar ch2, ch3, ch4;\\n\\n\t\tswitch (ch1) {\\n\t\t// Most common single-character punctuators\\n\t\tcase \".\":\\n\t\t\tif ((/^[0-9]$/).test(this.peek(1))) {\\n\t\t\t\treturn null;\\n\t\t\t}\\n\\n\t\t\t/* falls through */\\n\t\tcase \"(\":\\n\t\tcase \")\":\\n\t\tcase \";\":\\n\t\tcase \",\":\\n\t\tcase \"{\":\\n\t\tcase \"}\":\\n\t\tcase \"[\":\\n\t\tcase \"]\":\\n\t\tcase \":\":\\n\t\tcase \"~\":\\n\t\tcase \"?\":\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: ch1\\n\t\t\t};\\n\\n\t\t// A pound sign (for Node shebangs)\\n\t\tcase \"#\":\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: ch1\\n\t\t\t};\\n\\n\t\t// We\\'re at the end of input\\n\t\tcase \"\":\\n\t\t\treturn null;\\n\t\t}\\n\\n\t\t// Peek more characters\\n\\n\t\tch2 = this.peek(1);\\n\t\tch3 = this.peek(2);\\n\t\tch4 = this.peek(3);\\n\\n\t\t// 4-character punctuator: >>>=\\n\\n\t\tif (ch1 === \">\" && ch2 === \">\" && ch3 === \">\" && ch4 === \"=\") {\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: \">>>=\"\\n\t\t\t};\\n\t\t}\\n\\n\t\t// 3-character punctuators: === !== >>> <<= >>=\\n\\n\t\tif (ch1 === \"=\" && ch2 === \"=\" && ch3 === \"=\") {\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: \"===\"\\n\t\t\t};\\n\t\t}\\n\\n\t\tif (ch1 === \"!\" && ch2 === \"=\" && ch3 === \"=\") {\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: \"!==\"\\n\t\t\t};\\n\t\t}\\n\\n\t\tif (ch1 === \">\" && ch2 === \">\" && ch3 === \">\") {\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: \">>>\"\\n\t\t\t};\\n\t\t}\\n\\n\t\tif (ch1 === \"<\" && ch2 === \"<\" && ch3 === \"=\") {\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: \"<<=\"\\n\t\t\t};\\n\t\t}\\n\\n\t\tif (ch1 === \">\" && ch2 === \">\" && ch3 === \"=\") {\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: \"<<=\"\\n\t\t\t};\\n\t\t}\\n\\n\t\t// 2-character punctuators: <= >= == != ++ -- << >> && ||\\n\t\t// += -= *= %= &= |= ^= (but not /=, see below)\\n\t\tif (ch1 === ch2 && (\"+-<>&|\".indexOf(ch1) >= 0)) {\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: ch1 + ch2\\n\t\t\t};\\n\t\t}\\n\\n\t\tif (\"<>=!+-*%&|^\".indexOf(ch1) >= 0) {\\n\t\t\tif (ch2 === \"=\") {\\n\t\t\t\treturn {\\n\t\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\t\tvalue: ch1 + ch2\\n\t\t\t\t};\\n\t\t\t}\\n\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: ch1\\n\t\t\t};\\n\t\t}\\n\\n\t\t// Special case: /=. We need to make sure that this is an\\n\t\t// operator and not a regular expression.\\n\\n\t\tif (ch1 === \"/\") {\\n\t\t\tif (ch2 === \"=\" && /\\\\/=(?!(\\\\S*\\\\/[gim]?))/.test(this.input)) {\\n\t\t\t\t// /= is not a part of a regular expression, return it as a\\n\t\t\t\t// punctuator.\\n\t\t\t\treturn {\\n\t\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\t\tvalue: \"/=\"\\n\t\t\t\t};\\n\t\t\t}\\n\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Punctuator,\\n\t\t\t\tvalue: \"/\"\\n\t\t\t};\\n\t\t}\\n\\n\t\treturn null;\\n\t},\\n\\n\t/*\\n\t * Extract a comment out of the next sequence of characters and/or\\n\t * lines or return \\'null\\' if its not possible. Since comments can\\n\t * span across multiple lines this method has to move the char\\n\t * pointer.\\n\t *\\n\t * In addition to normal JavaScript comments (// and /*) this method\\n\t * also recognizes JSHint- and JSLint-specific comments such as\\n\t * /*jshint, /*jslint, /*globals and so on.\\n\t */\\n\tscanComments: function () {\\n\t\tvar ch1 = this.peek();\\n\t\tvar ch2 = this.peek(1);\\n\t\tvar rest = this.input.substr(2);\\n\t\tvar startLine = this.line;\\n\t\tvar startChar = this.char;\\n\\n\t\t// Create a comment token object and make sure it\\n\t\t// has all the data JSHint needs to work with special\\n\t\t// comments.\\n\\n\t\tfunction commentToken(label, body, opt) {\\n\t\t\tvar special = [\"jshint\", \"jslint\", \"members\", \"member\", \"globals\", \"global\", \"exported\"];\\n\t\t\tvar isSpecial = false;\\n\t\t\tvar value = label + body;\\n\t\t\tvar commentType = \"plain\";\\n\t\t\topt = opt || {};\\n\\n\t\t\tif (opt.isMultiline) {\\n\t\t\t\tvalue += \"*/\";\\n\t\t\t}\\n\\n\t\t\tspecial.forEach(function (str) {\\n\t\t\t\tif (isSpecial) {\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\t// Don\\'t recognize any special comments other than jshint for single-line\\n\t\t\t\t// comments. This introduced many problems with legit comments.\\n\t\t\t\tif (label === \"//\" && str !== \"jshint\") {\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tif (body.substr(0, str.length) === str) {\\n\t\t\t\t\tisSpecial = true;\\n\t\t\t\t\tlabel = label + str;\\n\t\t\t\t\tbody = body.substr(str.length);\\n\t\t\t\t}\\n\\n\t\t\t\tif (!isSpecial && body.charAt(0) === \" \" && body.substr(1, str.length) === str) {\\n\t\t\t\t\tisSpecial = true;\\n\t\t\t\t\tlabel = label + \" \" + str;\\n\t\t\t\t\tbody = body.substr(str.length + 1);\\n\t\t\t\t}\\n\\n\t\t\t\tif (!isSpecial) {\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tswitch (str) {\\n\t\t\t\tcase \"member\":\\n\t\t\t\t\tcommentType = \"members\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"global\":\\n\t\t\t\t\tcommentType = \"globals\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tdefault:\\n\t\t\t\t\tcommentType = str;\\n\t\t\t\t}\\n\t\t\t});\\n\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Comment,\\n\t\t\t\tcommentType: commentType,\\n\t\t\t\tvalue: value,\\n\t\t\t\tbody: body,\\n\t\t\t\tisSpecial: isSpecial,\\n\t\t\t\tisMultiline: opt.isMultiline || false,\\n\t\t\t\tisMalformed: opt.isMalformed || false\\n\t\t\t};\\n\t\t}\\n\\n\t\t// End of unbegun comment. Raise an error and skip that input.\\n\t\tif (ch1 === \"*\" && ch2 === \"/\") {\\n\t\t\tthis.trigger(\"error\", {\\n\t\t\t\tcode: \"E018\",\\n\t\t\t\tline: startLine,\\n\t\t\t\tcharacter: startChar\\n\t\t\t});\\n\\n\t\t\tthis.skip(2);\\n\t\t\treturn null;\\n\t\t}\\n\\n\t\t// Comments must start either with // or /*\\n\t\tif (ch1 !== \"/\" || (ch2 !== \"*\" && ch2 !== \"/\")) {\\n\t\t\treturn null;\\n\t\t}\\n\\n\t\t// One-line comment\\n\t\tif (ch2 === \"/\") {\\n\t\t\tthis.skip(this.input.length); // Skip to the EOL.\\n\t\t\treturn commentToken(\"//\", rest);\\n\t\t}\\n\\n\t\tvar body = \"\";\\n\\n\t\t/* Multi-line comment */\\n\t\tif (ch2 === \"*\") {\\n\t\t\tthis.skip(2);\\n\\n\t\t\twhile (this.peek() !== \"*\" || this.peek(1) !== \"/\") {\\n\t\t\t\tif (this.peek() === \"\") { // End of Line\\n\t\t\t\t\tbody += \"\\\\n\";\\n\\n\t\t\t\t\t// If we hit EOF and our comment is still unclosed,\\n\t\t\t\t\t// trigger an error and end the comment implicitly.\\n\t\t\t\t\tif (!this.nextLine()) {\\n\t\t\t\t\t\tthis.trigger(\"error\", {\\n\t\t\t\t\t\t\tcode: \"E017\",\\n\t\t\t\t\t\t\tline: startLine,\\n\t\t\t\t\t\t\tcharacter: startChar\\n\t\t\t\t\t\t});\\n\\n\t\t\t\t\t\treturn commentToken(\"/*\", body, {\\n\t\t\t\t\t\t\tisMultiline: true,\\n\t\t\t\t\t\t\tisMalformed: true\\n\t\t\t\t\t\t});\\n\t\t\t\t\t}\\n\t\t\t\t} else {\\n\t\t\t\t\tbody += this.peek();\\n\t\t\t\t\tthis.skip();\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tthis.skip(2);\\n\t\t\treturn commentToken(\"/*\", body, { isMultiline: true });\\n\t\t}\\n\t},\\n\\n\t/*\\n\t * Extract a keyword out of the next sequence of characters or\\n\t * return \\'null\\' if its not possible.\\n\t */\\n\tscanKeyword: function () {\\n\t\tvar result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);\\n\t\tvar keywords = [\\n\t\t\t\"if\", \"in\", \"do\", \"var\", \"for\", \"new\",\\n\t\t\t\"try\", \"let\", \"this\", \"else\", \"case\",\\n\t\t\t\"void\", \"with\", \"enum\", \"while\", \"break\",\\n\t\t\t\"catch\", \"throw\", \"const\", \"yield\", \"class\",\\n\t\t\t\"super\", \"return\", \"typeof\", \"delete\",\\n\t\t\t\"switch\", \"export\", \"import\", \"default\",\\n\t\t\t\"finally\", \"extends\", \"function\", \"continue\",\\n\t\t\t\"debugger\", \"instanceof\"\\n\t\t];\\n\\n\t\tif (result && keywords.indexOf(result[0]) >= 0) {\\n\t\t\treturn {\\n\t\t\t\ttype: Token.Keyword,\\n\t\t\t\tvalue: result[0]\\n\t\t\t};\\n\t\t}\\n\\n\t\treturn null;\\n\t},\\n\\n\t/*\\n\t * Extract a JavaScript identifier out of the next sequence of\\n\t * characters or return \\'null\\' if its not possible. In addition,\\n\t * to Identifier this method can also produce BooleanLiteral\\n\t * (true/false) and NullLiteral (null).\\n\t */\\n\tscanIdentifier: function () {\\n\t\tvar id = \"\";\\n\t\tvar index = 0;\\n\t\tvar type, char;\\n\\n\t\t// Detects any character in the Unicode categories \"Uppercase\\n\t\t// letter (Lu)\", \"Lowercase letter (Ll)\", \"Titlecase letter\\n\t\t// (Lt)\", \"Modifier letter (Lm)\", \"Other letter (Lo)\", or\\n\t\t// \"Letter number (Nl)\".\\n\t\t//\\n\t\t// Both approach and unicodeLetterTable were borrowed from\\n\t\t// Google\\'s Traceur.\\n\\n\t\tfunction isUnicodeLetter(code) {\\n\t\t\tfor (var i = 0; i < unicodeLetterTable.length;) {\\n\t\t\t\tif (code < unicodeLetterTable[i++]) {\\n\t\t\t\t\treturn false;\\n\t\t\t\t}\\n\\n\t\t\t\tif (code <= unicodeLetterTable[i++]) {\\n\t\t\t\t\treturn true;\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\treturn false;\\n\t\t}\\n\\n\t\tfunction isHexDigit(str) {\\n\t\t\treturn (/^[0-9a-fA-F]$/).test(str);\\n\t\t}\\n\\n\t\tvar readUnicodeEscapeSequence = function () {\\n\t\t\t/*jshint validthis:true */\\n\t\t\tindex += 1;\\n\\n\t\t\tif (this.peek(index) !== \"u\") {\\n\t\t\t\treturn null;\\n\t\t\t}\\n\\n\t\t\tvar ch1 = this.peek(index + 1);\\n\t\t\tvar ch2 = this.peek(index + 2);\\n\t\t\tvar ch3 = this.peek(index + 3);\\n\t\t\tvar ch4 = this.peek(index + 4);\\n\t\t\tvar code;\\n\\n\t\t\tif (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {\\n\t\t\t\tcode = parseInt(ch1 + ch2 + ch3 + ch4, 16);\\n\\n\t\t\t\tif (isUnicodeLetter(code)) {\\n\t\t\t\t\tindex += 5;\\n\t\t\t\t\treturn \"\\\\\\\\u\" + ch1 + ch2 + ch3 + ch4;\\n\t\t\t\t}\\n\\n\t\t\t\treturn null;\\n\t\t\t}\\n\\n\t\t\treturn null;\\n\t\t}.bind(this);\\n\\n\t\tvar getIdentifierStart = function () {\\n\t\t\t/*jshint validthis:true */\\n\t\t\tvar chr = this.peek(index);\\n\t\t\tvar code = chr.charCodeAt(0);\\n\\n\t\t\tif (code === 92) {\\n\t\t\t\treturn readUnicodeEscapeSequence();\\n\t\t\t}\\n\\n\t\t\tif (code < 128) {\\n\t\t\t\tif (identifierStartTable[code]) {\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t\treturn chr;\\n\t\t\t\t}\\n\\n\t\t\t\treturn null;\\n\t\t\t}\\n\\n\t\t\tif (isUnicodeLetter(code)) {\\n\t\t\t\tindex += 1;\\n\t\t\t\treturn chr;\\n\t\t\t}\\n\\n\t\t\treturn null;\\n\t\t}.bind(this);\\n\\n\t\tvar getIdentifierPart = function () {\\n\t\t\t/*jshint validthis:true */\\n\t\t\tvar chr = this.peek(index);\\n\t\t\tvar code = chr.charCodeAt(0);\\n\\n\t\t\tif (code === 92) {\\n\t\t\t\treturn readUnicodeEscapeSequence();\\n\t\t\t}\\n\\n\t\t\tif (code < 128) {\\n\t\t\t\tif (identifierPartTable[code]) {\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t\treturn chr;\\n\t\t\t\t}\\n\\n\t\t\t\treturn null;\\n\t\t\t}\\n\\n\t\t\tif (isUnicodeLetter(code)) {\\n\t\t\t\tindex += 1;\\n\t\t\t\treturn chr;\\n\t\t\t}\\n\\n\t\t\treturn null;\\n\t\t}.bind(this);\\n\\n\t\tchar = getIdentifierStart();\\n\t\tif (char === null) {\\n\t\t\treturn null;\\n\t\t}\\n\\n\t\tid = char;\\n\t\tfor (;;) {\\n\t\t\tchar = getIdentifierPart();\\n\\n\t\t\tif (char === null) {\\n\t\t\t\tbreak;\\n\t\t\t}\\n\\n\t\t\tid += char;\\n\t\t}\\n\\n\t\tswitch (id) {\\n\t\tcase \"true\":\\n\t\tcase \"false\":\\n\t\t\ttype = Token.BooleanLiteral;\\n\t\t\tbreak;\\n\t\tcase \"null\":\\n\t\t\ttype = Token.NullLiteral;\\n\t\t\tbreak;\\n\t\tdefault:\\n\t\t\ttype = Token.Identifier;\\n\t\t}\\n\\n\t\treturn {\\n\t\t\ttype: type,\\n\t\t\tvalue: id\\n\t\t};\\n\t},\\n\\n\t/*\\n\t * Extract a numeric literal out of the next sequence of\\n\t * characters or return \\'null\\' if its not possible. This method\\n\t * supports all numeric literals described in section 7.8.3\\n\t * of the EcmaScript 5 specification.\\n\t *\\n\t * This method\\'s implementation was heavily influenced by the\\n\t * scanNumericLiteral function in the Esprima parser\\'s source code.\\n\t */\\n\tscanNumericLiteral: function () {\\n\t\tvar index = 0;\\n\t\tvar value = \"\";\\n\t\tvar length = this.input.length;\\n\t\tvar char = this.peek(index);\\n\t\tvar bad;\\n\\n\t\tfunction isDecimalDigit(str) {\\n\t\t\treturn (/^[0-9]$/).test(str);\\n\t\t}\\n\\n\t\tfunction isOctalDigit(str) {\\n\t\t\treturn (/^[0-7]$/).test(str);\\n\t\t}\\n\\n\t\tfunction isHexDigit(str) {\\n\t\t\treturn (/^[0-9a-fA-F]$/).test(str);\\n\t\t}\\n\\n\t\tfunction isIdentifierStart(ch) {\\n\t\t\treturn (ch === \"$\") || (ch === \"_\") || (ch === \"\\\\\\\\\") ||\\n\t\t\t\t(ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\");\\n\t\t}\\n\\n\t\t// Numbers must start either with a decimal digit or a point.\\n\\n\t\tif (char !== \".\" && !isDecimalDigit(char)) {\\n\t\t\treturn null;\\n\t\t}\\n\\n\t\tif (char !== \".\") {\\n\t\t\tvalue = this.peek(index);\\n\t\t\tindex += 1;\\n\t\t\tchar = this.peek(index);\\n\\n\t\t\tif (value === \"0\") {\\n\t\t\t\t// Base-16 numbers.\\n\t\t\t\tif (char === \"x\" || char === \"X\") {\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t\tvalue += char;\\n\\n\t\t\t\t\twhile (index < length) {\\n\t\t\t\t\t\tchar = this.peek(index);\\n\t\t\t\t\t\tif (!isHexDigit(char)) {\\n\t\t\t\t\t\t\tbreak;\\n\t\t\t\t\t\t}\\n\t\t\t\t\t\tvalue += char;\\n\t\t\t\t\t\tindex += 1;\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tif (value.length <= 2) { // 0x\\n\t\t\t\t\t\treturn {\\n\t\t\t\t\t\t\ttype: Token.NumericLiteral,\\n\t\t\t\t\t\t\tvalue: value,\\n\t\t\t\t\t\t\tisMalformed: true\\n\t\t\t\t\t\t};\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tif (index < length) {\\n\t\t\t\t\t\tchar = this.peek(index);\\n\t\t\t\t\t\tif (isIdentifierStart(char)) {\\n\t\t\t\t\t\t\treturn null;\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\\n\t\t\t\t\treturn {\\n\t\t\t\t\t\ttype: Token.NumericLiteral,\\n\t\t\t\t\t\tvalue: value,\\n\t\t\t\t\t\tbase: 16,\\n\t\t\t\t\t\tisMalformed: false\\n\t\t\t\t\t};\\n\t\t\t\t}\\n\\n\t\t\t\t// Base-8 numbers.\\n\t\t\t\tif (isOctalDigit(char)) {\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t\tvalue += char;\\n\t\t\t\t\tbad = false;\\n\\n\t\t\t\t\twhile (index < length) {\\n\t\t\t\t\t\tchar = this.peek(index);\\n\\n\t\t\t\t\t\t// Numbers like \\'019\\' (note the 9) are not valid octals\\n\t\t\t\t\t\t// but we still parse them and mark as malformed.\\n\\n\t\t\t\t\t\tif (isDecimalDigit(char)) {\\n\t\t\t\t\t\t\tbad = true;\\n\t\t\t\t\t\t} else if (!isOctalDigit(char)) {\\n\t\t\t\t\t\t\tbreak;\\n\t\t\t\t\t\t}\\n\t\t\t\t\t\tvalue += char;\\n\t\t\t\t\t\tindex += 1;\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tif (index < length) {\\n\t\t\t\t\t\tchar = this.peek(index);\\n\t\t\t\t\t\tif (isIdentifierStart(char)) {\\n\t\t\t\t\t\t\treturn null;\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\\n\t\t\t\t\treturn {\\n\t\t\t\t\t\ttype: Token.NumericLiteral,\\n\t\t\t\t\t\tvalue: value,\\n\t\t\t\t\t\tbase: 8,\\n\t\t\t\t\t\tisMalformed: false\\n\t\t\t\t\t};\\n\t\t\t\t}\\n\\n\t\t\t\t// Decimal numbers that start with \\'0\\' such as \\'09\\' are illegal\\n\t\t\t\t// but we still parse them and return as malformed.\\n\\n\t\t\t\tif (isDecimalDigit(char)) {\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t\tvalue += char;\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\twhile (index < length) {\\n\t\t\t\tchar = this.peek(index);\\n\t\t\t\tif (!isDecimalDigit(char)) {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t\tvalue += char;\\n\t\t\t\tindex += 1;\\n\t\t\t}\\n\t\t}\\n\\n\t\t// Decimal digits.\\n\\n\t\tif (char === \".\") {\\n\t\t\tvalue += char;\\n\t\t\tindex += 1;\\n\\n\t\t\twhile (index < length) {\\n\t\t\t\tchar = this.peek(index);\\n\t\t\t\tif (!isDecimalDigit(char)) {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t\tvalue += char;\\n\t\t\t\tindex += 1;\\n\t\t\t}\\n\t\t}\\n\\n\t\t// Exponent part.\\n\\n\t\tif (char === \"e\" || char === \"E\") {\\n\t\t\tvalue += char;\\n\t\t\tindex += 1;\\n\t\t\tchar = this.peek(index);\\n\\n\t\t\tif (char === \"+\" || char === \"-\") {\\n\t\t\t\tvalue += this.peek(index);\\n\t\t\t\tindex += 1;\\n\t\t\t}\\n\\n\t\t\tchar = this.peek(index);\\n\t\t\tif (isDecimalDigit(char)) {\\n\t\t\t\tvalue += char;\\n\t\t\t\tindex += 1;\\n\\n\t\t\t\twhile (index < length) {\\n\t\t\t\t\tchar = this.peek(index);\\n\t\t\t\t\tif (!isDecimalDigit(char)) {\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t}\\n\t\t\t\t\tvalue += char;\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t}\\n\t\t\t} else {\\n\t\t\t\treturn null;\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (index < length) {\\n\t\t\tchar = this.peek(index);\\n\t\t\tif (isIdentifierStart(char)) {\\n\t\t\t\treturn null;\\n\t\t\t}\\n\t\t}\\n\\n\t\treturn {\\n\t\t\ttype: Token.NumericLiteral,\\n\t\t\tvalue: value,\\n\t\t\tbase: 10,\\n\t\t\tisMalformed: !isFinite(value)\\n\t\t};\\n\t},\\n\\n\t/*\\n\t * Extract a string out of the next sequence of characters and/or\\n\t * lines or return \\'null\\' if its not possible. Since strings can\\n\t * span across multiple lines this method has to move the char\\n\t * pointer.\\n\t *\\n\t * This method recognizes pseudo-multiline JavaScript strings:\\n\t *\\n\t *   var str = \"hello\\\\\\n\t *   world\";\\n   */\\n\tscanStringLiteral: function () {\\n\t\tvar quote = this.peek();\\n\\n\t\t// String must start with a quote.\\n\t\tif (quote !== \"\\\\\"\" && quote !== \"\\'\") {\\n\t\t\treturn null;\\n\t\t}\\n\\n\t\t// In JSON strings must always use double quotes.\\n\t\tif (state.jsonMode && quote !== \"\\\\\"\") {\\n\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\tcode: \"W108\",\\n\t\t\t\tline: this.line,\\n\t\t\t\tcharacter: this.char // +1?\\n\t\t\t});\\n\t\t}\\n\\n\t\tvar value = \"\";\\n\t\tvar startLine = this.line;\\n\t\tvar startChar = this.char;\\n\t\tvar allowNewLine = false;\\n\\n\t\tthis.skip();\\n\\n\t\twhile (this.peek() !== quote) {\\n\t\t\twhile (this.peek() === \"\") { // End Of Line\\n\\n\t\t\t\t// If an EOL is not preceded by a backslash, show a warning\\n\t\t\t\t// and proceed like it was a legit multi-line string where\\n\t\t\t\t// author simply forgot to escape the newline symbol.\\n\t\t\t\t//\\n\t\t\t\t// Another approach is to implicitly close a string on EOL\\n\t\t\t\t// but it generates too many false positives.\\n\\n\t\t\t\tif (!allowNewLine) {\\n\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\tcode: \"W112\",\\n\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\tcharacter: this.char\\n\t\t\t\t\t});\\n\t\t\t\t} else {\\n\t\t\t\t\tallowNewLine = false;\\n\\n\t\t\t\t\t// Otherwise show a warning if multistr option was not set.\\n\t\t\t\t\t// For JSON, show warning no matter what.\\n\\n\t\t\t\t\tif (!state.option.multistr) {\\n\t\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\t\tcode: \"W043\",\\n\t\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\t\tcharacter: this.char\\n\t\t\t\t\t\t});\\n\t\t\t\t\t} else if (state.jsonMode) {\\n\t\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\t\tcode: \"W042\",\\n\t\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\t\tcharacter: this.char\\n\t\t\t\t\t\t});\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\t// If we get an EOF inside of an unclosed string, show an\\n\t\t\t\t// error and implicitly close it at the EOF point.\\n\\n\t\t\t\tif (!this.nextLine()) {\\n\t\t\t\t\tthis.trigger(\"error\", {\\n\t\t\t\t\t\tcode: \"E029\",\\n\t\t\t\t\t\tline: startLine,\\n\t\t\t\t\t\tcharacter: startChar\\n\t\t\t\t\t});\\n\\n\t\t\t\t\treturn {\\n\t\t\t\t\t\ttype: Token.StringLiteral,\\n\t\t\t\t\t\tvalue: value,\\n\t\t\t\t\t\tisUnclosed: true,\\n\t\t\t\t\t\tquote: quote\\n\t\t\t\t\t};\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tallowNewLine = false;\\n\t\t\tvar char = this.peek();\\n\t\t\tvar jump = 1; // A length of a jump, after we\\'re done\\n\t\t\t              // parsing this character.\\n\\n\t\t\tif (char < \" \") {\\n\t\t\t\t// Warn about a control character in a string.\\n\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\tcode: \"W113\",\\n\t\t\t\t\tline: this.line,\\n\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\tdata: [ \"<non-printable>\" ]\\n\t\t\t\t});\\n\t\t\t}\\n\\n\t\t\t// Special treatment for some escaped characters.\\n\\n\t\t\tif (char === \"\\\\\\\\\") {\\n\t\t\t\tthis.skip();\\n\t\t\t\tchar = this.peek();\\n\\n\t\t\t\tswitch (char) {\\n\t\t\t\tcase \"\\'\":\\n\t\t\t\t\tif (state.jsonMode) {\\n\t\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\t\tcode: \"W114\",\\n\t\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\t\t\tdata: [ \"\\\\\\\\\\'\" ]\\n\t\t\t\t\t\t});\\n\t\t\t\t\t}\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"b\":\\n\t\t\t\t\tchar = \"\\\\b\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"f\":\\n\t\t\t\t\tchar = \"\\\\f\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"n\":\\n\t\t\t\t\tchar = \"\\\\n\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"r\":\\n\t\t\t\t\tchar = \"\\\\r\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"t\":\\n\t\t\t\t\tchar = \"\\\\t\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"0\":\\n\t\t\t\t\tchar = \"\\\\0\";\\n\\n\t\t\t\t\t// Octal literals fail in strict mode.\\n\t\t\t\t\t// Check if the number is between 00 and 07.\\n\t\t\t\t\tvar n = parseInt(this.peek(1), 10);\\n\t\t\t\t\tif (n >= 0 && n <= 7 && state.directive[\"use strict\"]) {\\n\t\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\t\tcode: \"W115\",\\n\t\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\t\tcharacter: this.char\\n\t\t\t\t\t\t});\\n\t\t\t\t\t}\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"u\":\\n\t\t\t\t\tchar = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));\\n\t\t\t\t\tjump = 5;\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"v\":\\n\t\t\t\t\tif (state.jsonMode) {\\n\t\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\t\tcode: \"W114\",\\n\t\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\t\t\tdata: [ \"\\\\\\\\v\" ]\\n\t\t\t\t\t\t});\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tchar = \"\\\\v\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"x\":\\n\t\t\t\t\tvar\tx = parseInt(this.input.substr(1, 2), 16);\\n\\n\t\t\t\t\tif (state.jsonMode) {\\n\t\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\t\tcode: \"W114\",\\n\t\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\t\t\tdata: [ \"\\\\\\\\x-\" ]\\n\t\t\t\t\t\t});\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tchar = String.fromCharCode(x);\\n\t\t\t\t\tjump = 3;\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"\\\\\\\\\":\\n\t\t\t\tcase \"\\\\\"\":\\n\t\t\t\tcase \"/\":\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"\":\\n\t\t\t\t\tallowNewLine = true;\\n\t\t\t\t\tchar = \"\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"!\":\\n\t\t\t\t\tif (value.slice(value.length - 2) === \"<\") {\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t}\\n\\n\t\t\t\t\t/*falls through */\\n\t\t\t\tdefault:\\n\t\t\t\t\t// Weird escaping.\\n\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\tcode: \"W044\",\\n\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\tcharacter: this.char\\n\t\t\t\t\t});\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tvalue += char;\\n\t\t\tthis.skip(jump);\\n\t\t}\\n\\n\t\tthis.skip();\\n\t\treturn {\\n\t\t\ttype: Token.StringLiteral,\\n\t\t\tvalue: value,\\n\t\t\tisUnclosed: false,\\n\t\t\tquote: quote\\n\t\t};\\n\t},\\n\\n\t/*\\n\t * Extract a regular expression out of the next sequence of\\n\t * characters and/or lines or return \\'null\\' if its not possible.\\n\t *\\n\t * This method is platform dependent: it accepts almost any\\n\t * regular expression values but then tries to compile and run\\n\t * them using system\\'s RegExp object. This means that there are\\n\t * rare edge cases where one JavaScript engine complains about\\n\t * your regular expression while others don\\'t.\\n\t */\\n\tscanRegExp: function () {\\n\t\tvar index = 0;\\n\t\tvar length = this.input.length;\\n\t\tvar char = this.peek();\\n\t\tvar value = char;\\n\t\tvar body = \"\";\\n\t\tvar flags = [];\\n\t\tvar malformed = false;\\n\t\tvar isCharSet = false;\\n\t\tvar terminated;\\n\\n\t\tvar scanUnexpectedChars = function () {\\n\t\t\t// Unexpected control character\\n\t\t\tif (char < \" \") {\\n\t\t\t\tmalformed = true;\\n\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\tcode: \"W048\",\\n\t\t\t\t\tline: this.line,\\n\t\t\t\t\tcharacter: this.char\\n\t\t\t\t});\\n\t\t\t}\\n\\n\t\t\t// Unexpected escaped character\\n\t\t\tif (char === \"<\") {\\n\t\t\t\tmalformed = true;\\n\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\tcode: \"W049\",\\n\t\t\t\t\tline: this.line,\\n\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\tdata: [ char ]\\n\t\t\t\t});\\n\t\t\t}\\n\t\t}.bind(this);\\n\\n\t\t// Regular expressions must start with \\'/\\'\\n\t\tif (!this.prereg || char !== \"/\") {\\n\t\t\treturn null;\\n\t\t}\\n\\n\t\tindex += 1;\\n\t\tterminated = false;\\n\\n\t\t// Try to get everything in between slashes. A couple of\\n\t\t// cases aside (see scanUnexpectedChars) we don\\'t really\\n\t\t// care whether the resulting expression is valid or not.\\n\t\t// We will check that later using the RegExp object.\\n\\n\t\twhile (index < length) {\\n\t\t\tchar = this.peek(index);\\n\t\t\tvalue += char;\\n\t\t\tbody += char;\\n\\n\t\t\tif (isCharSet) {\\n\t\t\t\tif (char === \"]\") {\\n\t\t\t\t\tif (this.peek(index - 1) !== \"\\\\\\\\\" || this.peek(index - 2) === \"\\\\\\\\\") {\\n\t\t\t\t\t\tisCharSet = false;\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\tif (char === \"\\\\\\\\\") {\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t\tchar = this.peek(index);\\n\t\t\t\t\tbody += char;\\n\t\t\t\t\tvalue += char;\\n\\n\t\t\t\t\tscanUnexpectedChars();\\n\t\t\t\t}\\n\\n\t\t\t\tindex += 1;\\n\t\t\t\tcontinue;\\n\t\t\t}\\n\\n\t\t\tif (char === \"\\\\\\\\\") {\\n\t\t\t\tindex += 1;\\n\t\t\t\tchar = this.peek(index);\\n\t\t\t\tbody += char;\\n\t\t\t\tvalue += char;\\n\\n\t\t\t\tscanUnexpectedChars();\\n\\n\t\t\t\tif (char === \"/\") {\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t\tcontinue;\\n\t\t\t\t}\\n\\n\t\t\t\tif (char === \"[\") {\\n\t\t\t\t\tindex += 1;\\n\t\t\t\t\tcontinue;\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tif (char === \"[\") {\\n\t\t\t\tisCharSet = true;\\n\t\t\t\tindex += 1;\\n\t\t\t\tcontinue;\\n\t\t\t}\\n\\n\t\t\tif (char === \"/\") {\\n\t\t\t\tbody = body.substr(0, body.length - 1);\\n\t\t\t\tterminated = true;\\n\t\t\t\tindex += 1;\\n\t\t\t\tbreak;\\n\t\t\t}\\n\\n\t\t\tindex += 1;\\n\t\t}\\n\\n\t\t// A regular expression that was never closed is an\\n\t\t// error from which we cannot recover.\\n\\n\t\tif (!terminated) {\\n\t\t\tthis.trigger(\"error\", {\\n\t\t\t\tcode: \"E015\",\\n\t\t\t\tline: this.line,\\n\t\t\t\tcharacter: this.from\\n\t\t\t});\\n\\n\t\t\treturn void this.trigger(\"fatal\", {\\n\t\t\t\tline: this.line,\\n\t\t\t\tfrom: this.from\\n\t\t\t});\\n\t\t}\\n\\n\t\t// Parse flags (if any).\\n\\n\t\twhile (index < length) {\\n\t\t\tchar = this.peek(index);\\n\t\t\tif (!/[gim]/.test(char)) {\\n\t\t\t\tbreak;\\n\t\t\t}\\n\t\t\tflags.push(char);\\n\t\t\tvalue += char;\\n\t\t\tindex += 1;\\n\t\t}\\n\\n\t\t// Check regular expression for correctness.\\n\\n\t\ttry {\\n\t\t\tnew RegExp(body, flags.join(\"\"));\\n\t\t} catch (err) {\\n\t\t\tmalformed = true;\\n\t\t\tthis.trigger(\"error\", {\\n\t\t\t\tcode: \"E016\",\\n\t\t\t\tline: this.line,\\n\t\t\t\tcharacter: this.char,\\n\t\t\t\tdata: [ err.message ] // Platform dependent!\\n\t\t\t});\\n\t\t}\\n\\n\t\treturn {\\n\t\t\ttype: Token.RegExp,\\n\t\t\tvalue: value,\\n\t\t\tflags: flags,\\n\t\t\tisMalformed: malformed\\n\t\t};\\n\t},\\n\\n\t/*\\n\t * Scan for any occurence of mixed tabs and spaces. If smarttabs option\\n\t * is on, ignore tabs followed by spaces.\\n\t *\\n\t * Tabs followed by one space followed by a block comment are allowed.\\n\t */\\n\tscanMixedSpacesAndTabs: function () {\\n\t\tvar at, match;\\n\\n\t\tif (state.option.smarttabs) {\\n\t\t\t// Negative look-behind for \"//\"\\n\t\t\tmatch = this.input.match(/(\\\\/\\\\/)? \\\\t/);\\n\t\t\tat = match && !match[1] ? 0 : -1;\\n\t\t} else {\\n\t\t\tat = this.input.search(/ \\\\t|\\\\t [^\\\\*]/);\\n\t\t}\\n\\n\t\treturn at;\\n\t},\\n\\n\t/*\\n\t * Scan for characters that get silently deleted by one or more browsers.\\n\t */\\n\tscanUnsafeChars: function () {\\n\t\treturn this.input.search(reg.unsafeChars);\\n\t},\\n\\n\t/*\\n\t * Produce the next raw token or return \\'null\\' if no tokens can be matched.\\n\t * This method skips over all space characters.\\n\t */\\n\tnext: function () {\\n\t\tthis.from = this.char;\\n\\n\t\t// Move to the next non-space character.\\n\t\tvar start;\\n\t\tif (/\\\\s/.test(this.peek())) {\\n\t\t\tstart = this.char;\\n\\n\t\t\twhile (/\\\\s/.test(this.peek())) {\\n\t\t\t\tthis.from += 1;\\n\t\t\t\tthis.skip();\\n\t\t\t}\\n\\n\t\t\tif (this.peek() === \"\") { // EOL\\n\t\t\t\tif (state.option.trailing) {\\n\t\t\t\t\tthis.trigger(\"warning\", { code: \"W102\", line: this.line, character: start });\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\\n\t\t// Methods that work with multi-line structures and move the\\n\t\t// character pointer.\\n\\n\t\tvar match = this.scanComments() ||\\n\t\t\tthis.scanStringLiteral();\\n\\n\t\tif (match) {\\n\t\t\treturn match;\\n\t\t}\\n\\n\t\t// Methods that don\\'t move the character pointer.\\n\\n\t\tmatch =\\n\t\t\tthis.scanRegExp() ||\\n\t\t\tthis.scanPunctuator() ||\\n\t\t\tthis.scanKeyword() ||\\n\t\t\tthis.scanIdentifier() ||\\n\t\t\tthis.scanNumericLiteral();\\n\\n\t\tif (match) {\\n\t\t\tthis.skip(match.value.length);\\n\t\t\treturn match;\\n\t\t}\\n\\n\t\t// No token could be matched, give up.\\n\\n\t\treturn null;\\n\t},\\n\\n\t/*\\n\t * Switch to the next line and reset all char pointers. Once\\n\t * switched, this method also checks for mixed spaces and tabs\\n\t * and other minor warnings.\\n\t */\\n\tnextLine: function () {\\n\t\tvar char;\\n\\n\t\tif (this.line >= this.lines.length) {\\n\t\t\treturn false;\\n\t\t}\\n\\n\t\tthis.input = this.lines[this.line];\\n\t\tthis.line += 1;\\n\t\tthis.char = 1;\\n\t\tthis.from = 1;\\n\\n\t\tchar = this.scanMixedSpacesAndTabs();\\n\t\tif (char >= 0) {\\n\t\t\tthis.trigger(\"warning\", { code: \"W099\", line: this.line, character: char + 1 });\\n\t\t}\\n\\n\t\tthis.input = this.input.replace(/\\\\t/g, state.tab);\\n\t\tchar = this.scanUnsafeChars();\\n\\n\t\tif (char >= 0) {\\n\t\t\tthis.trigger(\"warning\", { code: \"W100\", line: this.line, character: char });\\n\t\t}\\n\\n\t\t// If there is a limit on line length, warn when lines get too\\n\t\t// long.\\n\\n\t\tif (state.option.maxlen && state.option.maxlen < this.input.length) {\\n\t\t\tthis.trigger(\"warning\", { code: \"W101\", line: this.line, character: this.input.length });\\n\t\t}\\n\\n\t\treturn true;\\n\t},\\n\\n\t/*\\n\t * This is simply a synonym for nextLine() method with a friendlier\\n\t * public name.\\n\t */\\n\tstart: function () {\\n\t\tthis.nextLine();\\n\t},\\n\\n\t/*\\n\t * Produce the next token. This function is called by advance() to get\\n\t * the next token. It retuns a token in a JSLint-compatible format.\\n\t */\\n\ttoken: function () {\\n\t\tvar token;\\n\\n\t\tfunction isReserved(token, isProperty) {\\n\t\t\tif (!token.reserved) {\\n\t\t\t\treturn false;\\n\t\t\t}\\n\\n\t\t\tif (token.meta && token.meta.isFutureReservedWord) {\\n\t\t\t\t// ES3 FutureReservedWord in an ES5 environment.\\n\t\t\t\tif (state.option.es5 && !token.meta.es5) {\\n\t\t\t\t\treturn false;\\n\t\t\t\t}\\n\\n\t\t\t\t// Some ES5 FutureReservedWord identifiers are active only\\n\t\t\t\t// within a strict mode environment.\\n\t\t\t\tif (token.meta.strictOnly) {\\n\t\t\t\t\tif (!state.option.strict && !state.directive[\"use strict\"]) {\\n\t\t\t\t\t\treturn false;\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\tif (isProperty) {\\n\t\t\t\t\treturn false;\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\treturn true;\\n\t\t}\\n\\n\t\t// Produce a token object.\\n\t\tvar create = function (type, value, isProperty) {\\n\t\t\t/*jshint validthis:true */\\n\t\t\tvar obj;\\n\\n\t\t\tif (type !== \"(endline)\" && type !== \"(end)\") {\\n\t\t\t\tthis.prereg = false;\\n\t\t\t}\\n\\n\t\t\tif (type === \"(punctuator)\") {\\n\t\t\t\tswitch (value) {\\n\t\t\t\tcase \".\":\\n\t\t\t\tcase \")\":\\n\t\t\t\tcase \"~\":\\n\t\t\t\tcase \"#\":\\n\t\t\t\tcase \"]\":\\n\t\t\t\t\tthis.prereg = false;\\n\t\t\t\t\tbreak;\\n\t\t\t\tdefault:\\n\t\t\t\t\tthis.prereg = true;\\n\t\t\t\t}\\n\\n\t\t\t\tobj = Object.create(state.syntax[value] || state.syntax[\"(error)\"]);\\n\t\t\t}\\n\\n\t\t\tif (type === \"(identifier)\") {\\n\t\t\t\tif (value === \"return\" || value === \"case\" || value === \"typeof\") {\\n\t\t\t\t\tthis.prereg = true;\\n\t\t\t\t}\\n\\n\t\t\t\tif (_.has(state.syntax, value)) {\\n\t\t\t\t\tobj = Object.create(state.syntax[value] || state.syntax[\"(error)\"]);\\n\\n\t\t\t\t\t// If this can\\'t be a reserved keyword, reset the object.\\n\t\t\t\t\tif (!isReserved(obj, isProperty && type === \"(identifier)\")) {\\n\t\t\t\t\t\tobj = null;\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tif (!obj) {\\n\t\t\t\tobj = Object.create(state.syntax[type]);\\n\t\t\t}\\n\\n\t\t\tobj.identifier = (type === \"(identifier)\");\\n\t\t\tobj.type = obj.type || type;\\n\t\t\tobj.value = value;\\n\t\t\tobj.line = this.line;\\n\t\t\tobj.character = this.char;\\n\t\t\tobj.from = this.from;\\n\\n\t\t\tif (isProperty && obj.identifier) {\\n\t\t\t\tobj.isProperty = isProperty;\\n\t\t\t}\\n\\n\t\t\treturn obj;\\n\t\t}.bind(this);\\n\\n\t\tfor (;;) {\\n\t\t\tif (!this.input.length) {\\n\t\t\t\treturn create(this.nextLine() ? \"(endline)\" : \"(end)\", \"\");\\n\t\t\t}\\n\\n\t\t\ttoken = this.next();\\n\\n\t\t\tif (!token) {\\n\t\t\t\tif (this.input.length) {\\n\t\t\t\t\t// Unexpected character.\\n\t\t\t\t\tthis.trigger(\"error\", {\\n\t\t\t\t\t\tcode: \"E024\",\\n\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\t\tdata: [ this.peek() ]\\n\t\t\t\t\t});\\n\\n\t\t\t\t\tthis.input = \"\";\\n\t\t\t\t}\\n\\n\t\t\t\tcontinue;\\n\t\t\t}\\n\\n\t\t\tswitch (token.type) {\\n\t\t\tcase Token.StringLiteral:\\n\t\t\t\tthis.trigger(\"String\", {\\n\t\t\t\t\tline: this.line,\\n\t\t\t\t\tchar: this.char,\\n\t\t\t\t\tfrom: this.from,\\n\t\t\t\t\tvalue: token.value,\\n\t\t\t\t\tquote: token.quote\\n\t\t\t\t});\\n\\n\t\t\t\treturn create(\"(string)\", token.value);\\n\t\t\tcase Token.Identifier:\\n\t\t\t\tthis.trigger(\"Identifier\", {\\n\t\t\t\t\tline: this.line,\\n\t\t\t\t\tchar: this.char,\\n\t\t\t\t\tfrom: this.form,\\n\t\t\t\t\tname: token.value,\\n\t\t\t\t\tisProperty: state.tokens.curr.id === \".\"\\n\t\t\t\t});\\n\\n\t\t\t\t/* falls through */\\n\t\t\tcase Token.Keyword:\\n\t\t\tcase Token.NullLiteral:\\n\t\t\tcase Token.BooleanLiteral:\\n\t\t\t\treturn create(\"(identifier)\", token.value, state.tokens.curr.id === \".\");\\n\\n\t\t\tcase Token.NumericLiteral:\\n\t\t\t\tif (token.isMalformed) {\\n\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\tcode: \"W045\",\\n\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\t\tdata: [ token.value ]\\n\t\t\t\t\t});\\n\t\t\t\t}\\n\\n\t\t\t\tif (state.jsonMode && token.base === 16) {\\n\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\tcode: \"W114\",\\n\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\t\tdata: [ \"0x-\" ]\\n\t\t\t\t\t});\\n\t\t\t\t}\\n\\n\t\t\t\tif (state.directive[\"use strict\"] && token.base === 8) {\\n\t\t\t\t\tthis.trigger(\"warning\", {\\n\t\t\t\t\t\tcode: \"W115\",\\n\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\tcharacter: this.char\\n\t\t\t\t\t});\\n\t\t\t\t}\\n\\n\t\t\t\tthis.trigger(\"Number\", {\\n\t\t\t\t\tline: this.line,\\n\t\t\t\t\tchar: this.char,\\n\t\t\t\t\tfrom: this.from,\\n\t\t\t\t\tvalue: token.value,\\n\t\t\t\t\tbase: token.base,\\n\t\t\t\t\tisMalformed: token.malformed\\n\t\t\t\t});\\n\\n\t\t\t\treturn create(\"(number)\", token.value);\\n\\n\t\t\tcase Token.RegExp:\\n\t\t\t\treturn create(\"(regexp)\", token.value);\\n\\n\t\t\tcase Token.Comment:\\n\t\t\t\tstate.tokens.curr.comment = true;\\n\\n\t\t\t\tif (token.isSpecial) {\\n\t\t\t\t\treturn {\\n\t\t\t\t\t\tvalue: token.value,\\n\t\t\t\t\t\tbody: token.body,\\n\t\t\t\t\t\ttype: token.commentType,\\n\t\t\t\t\t\tisSpecial: token.isSpecial,\\n\t\t\t\t\t\tline: this.line,\\n\t\t\t\t\t\tcharacter: this.char,\\n\t\t\t\t\t\tfrom: this.from\\n\t\t\t\t\t};\\n\t\t\t\t}\\n\\n\t\t\t\tbreak;\\n\\n\t\t\tcase \"\":\\n\t\t\t\tbreak;\\n\\n\t\t\tdefault:\\n\t\t\t\treturn create(\"(punctuator)\", token.value);\\n\t\t\t}\\n\t\t}\\n\t}\\n};\\n\\nexports.Lexer = Lexer;\\n//@ sourceURL=/src/stable/lex.js'));\nrequire.define(\"/src/stable/reg.js\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],'/*\\n * Regular expressions. Some of these are stupidly long.\\n */\\n\\n/*jshint maxlen:1000 */\\n\\n\"use string\";\\n\\n// Unsafe comment or string (ax)\\nexports.unsafeString =\\n\t/@cc|<\\\\/?|script|\\\\]\\\\s*\\\\]|<\\\\s*!|&lt/i;\\n\\n// Unsafe characters that are silently deleted by one or more browsers (cx)\\nexports.unsafeChars =\\n\t/[\\\\u0000-\\\\u001f\\\\u007f-\\\\u009f\\\\u00ad\\\\u0600-\\\\u0604\\\\u070f\\\\u17b4\\\\u17b5\\\\u200c-\\\\u200f\\\\u2028-\\\\u202f\\\\u2060-\\\\u206f\\\\ufeff\\\\ufff0-\\\\uffff]/;\\n\\n// Characters in strings that need escaping (nx and nxg)\\nexports.needEsc =\\n\t/[\\\\u0000-\\\\u001f&<\"\\\\/\\\\\\\\\\\\u007f-\\\\u009f\\\\u00ad\\\\u0600-\\\\u0604\\\\u070f\\\\u17b4\\\\u17b5\\\\u200c-\\\\u200f\\\\u2028-\\\\u202f\\\\u2060-\\\\u206f\\\\ufeff\\\\ufff0-\\\\uffff]/;\\n\\nexports.needEscGlobal =\\n\t/[\\\\u0000-\\\\u001f&<\"\\\\/\\\\\\\\\\\\u007f-\\\\u009f\\\\u00ad\\\\u0600-\\\\u0604\\\\u070f\\\\u17b4\\\\u17b5\\\\u200c-\\\\u200f\\\\u2028-\\\\u202f\\\\u2060-\\\\u206f\\\\ufeff\\\\ufff0-\\\\uffff]/g;\\n\\n// Star slash (lx)\\nexports.starSlash = /\\\\*\\\\//;\\n\\n// Identifier (ix)\\nexports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;\\n\\n// JavaScript URL (jx)\\nexports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\\\s*:/i;\\n\\n// Catches /* falls through */ comments (ft)\\nexports.fallsThrough = /^\\\\s*\\\\/\\\\*\\\\s*falls\\\\sthrough\\\\s*\\\\*\\\\/\\\\s*$/;\\n//@ sourceURL=/src/stable/reg.js'));\nrequire.define(\"/src/stable/state.js\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],'\"use strict\";\\n\\nvar state = {\\n\tsyntax: {},\\n\\n\treset: function () {\\n\t\tthis.tokens = {\\n\t\t\tprev: null,\\n\t\t\tnext: null,\\n\t\t\tcurr: null\\n\t\t},\\n\\n\t\tthis.option = {};\\n\t\tthis.directive = {};\\n\t\tthis.jsonMode = false;\\n\t\tthis.lines = [];\\n\t\tthis.tab = \"\";\\n\t\tthis.cache = {}; // Node.JS doesn\\'t have Map. Sniff.\\n\t}\\n};\\n\\nexports.state = state;\\n//@ sourceURL=/src/stable/state.js'));\nrequire.define(\"/src/stable/style.js\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],'\"use strict\";\\n\\nexports.register = function (linter) {\\n\t// Check for properties named __proto__. This special property was\\n\t// deprecated and then re-introduced for ES6.\\n\\n\tlinter.on(\"Identifier\", function style_scanProto(data) {\\n\t\tif (linter.getOption(\"proto\")) {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\tif (data.name === \"__proto__\") {\\n\t\t\tlinter.warn(\"W103\", {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.char,\\n\t\t\t\tdata: [ data.name ]\\n\t\t\t});\\n\t\t}\\n\t});\\n\\n\t// Check for properties named __iterator__. This is a special property\\n\t// available only in browsers with JavaScript 1.7 implementation.\\n\\n\tlinter.on(\"Identifier\", function style_scanIterator(data) {\\n\t\tif (linter.getOption(\"iterator\")) {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\tif (data.name === \"__iterator__\") {\\n\t\t\tlinter.warn(\"W104\", {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.char,\\n\t\t\t\tdata: [ data.name ]\\n\t\t\t});\\n\t\t}\\n\t});\\n\\n\t// Check for dangling underscores.\\n\\n\tlinter.on(\"Identifier\", function style_scanDangling(data) {\\n\t\tif (!linter.getOption(\"nomen\")) {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\t// Underscore.js\\n\t\tif (data.name === \"_\") {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\t// In Node, __dirname and __filename should be ignored.\\n\t\tif (linter.getOption(\"node\")) {\\n\t\t\tif (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) {\\n\t\t\t\treturn;\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (/^(_+.*|.*_+)$/.test(data.name)) {\\n\t\t\tlinter.warn(\"W105\", {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.from,\\n\t\t\t\tdata: [ \"dangling \\'_\\'\", data.name ]\\n\t\t\t});\\n\t\t}\\n\t});\\n\\n\t// Check that all identifiers are using camelCase notation.\\n\t// Exceptions: names like MY_VAR and _myVar.\\n\\n\tlinter.on(\"Identifier\", function style_scanCamelCase(data) {\\n\t\tif (!linter.getOption(\"camelcase\")) {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\tif (data.name.replace(/^_+/, \"\").indexOf(\"_\") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {\\n\t\t\tlinter.warn(\"W106\", {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.from,\\n\t\t\t\tdata: [ data.name ]\\n\t\t\t});\\n\t\t}\\n\t});\\n\\n\t// Enforce consistency in style of quoting.\\n\\n\tlinter.on(\"String\", function style_scanQuotes(data) {\\n\t\tvar quotmark = linter.getOption(\"quotmark\");\\n\t\tvar code;\\n\\n\t\tif (!quotmark) {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\t// If quotmark is set to \\'single\\' warn about all double-quotes.\\n\\n\t\tif (quotmark === \"single\" && data.quote !== \"\\'\") {\\n\t\t\tcode = \"W109\";\\n\t\t}\\n\\n\t\t// If quotmark is set to \\'double\\' warn about all single-quotes.\\n\\n\t\tif (quotmark === \"double\" && data.quote !== \"\\\\\"\") {\\n\t\t\tcode = \"W108\";\\n\t\t}\\n\\n\t\t// If quotmark is set to true, remember the first quotation style\\n\t\t// and then warn about all others.\\n\\n\t\tif (quotmark === true) {\\n\t\t\tif (!linter.getCache(\"quotmark\")) {\\n\t\t\t\tlinter.setCache(\"quotmark\", data.quote);\\n\t\t\t}\\n\\n\t\t\tif (linter.getCache(\"quotmark\") !== data.quote) {\\n\t\t\t\tcode = \"W110\";\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (code) {\\n\t\t\tlinter.warn(code, {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.char,\\n\t\t\t});\\n\t\t}\\n\t});\\n\\n\tlinter.on(\"Number\", function style_scanNumbers(data) {\\n\t\tif (data.value.charAt(0) === \".\") {\\n\t\t\t// Warn about a leading decimal point.\\n\t\t\tlinter.warn(\"W008\", {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.char,\\n\t\t\t\tdata: [ data.value ]\\n\t\t\t});\\n\t\t}\\n\\n\t\tif (data.value.substr(data.value.length - 1) === \".\") {\\n\t\t\t// Warn about a trailing decimal point.\\n\t\t\tlinter.warn(\"W047\", {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.char,\\n\t\t\t\tdata: [ data.value ]\\n\t\t\t});\\n\t\t}\\n\\n\t\tif (/^00+/.test(data.value)) {\\n\t\t\t// Multiple leading zeroes.\\n\t\t\tlinter.warn(\"W046\", {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.char,\\n\t\t\t\tdata: [ data.value ]\\n\t\t\t});\\n\t\t}\\n\t});\\n\\n\t// Warn about script URLs.\\n\\n\tlinter.on(\"String\", function style_scanJavaScriptURLs(data) {\\n\t\tvar re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\\\s*:/i;\\n\\n\t\tif (linter.getOption(\"scripturl\")) {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\tif (re.test(data.value)) {\\n\t\t\tlinter.warn(\"W107\", {\\n\t\t\t\tline: data.line,\\n\t\t\t\tchar: data.char\\n\t\t\t});\\n\t\t}\\n\t});\\n};\\n//@ sourceURL=/src/stable/style.js'));\nrequire.define(\"/src/stable/jshint.js\",Function([\"require\",\"module\",\"exports\",\"__dirname\",\"__filename\",\"process\",\"global\"],'/*!\\n * JSHint, by JSHint Community.\\n *\\n * This file (and this file only) is licensed under the same slightly modified\\n * MIT license that JSLint is. It stops evil-doers everywhere:\\n *\\n *\t Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\\n *\\n *\t Permission is hereby granted, free of charge, to any person obtaining\\n *\t a copy of this software and associated documentation files (the \"Software\"),\\n *\t to deal in the Software without restriction, including without limitation\\n *\t the rights to use, copy, modify, merge, publish, distribute, sublicense,\\n *\t and/or sell copies of the Software, and to permit persons to whom\\n *\t the Software is furnished to do so, subject to the following conditions:\\n *\\n *\t The above copyright notice and this permission notice shall be included\\n *\t in all copies or substantial portions of the Software.\\n *\\n *\t The Software shall be used for Good, not Evil.\\n *\\n *\t THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\n *\t IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\\n *\t FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\\n *\t AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\\n *\t LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\\n *\t FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\\n *\t DEALINGS IN THE SOFTWARE.\\n *\\n */\\n\\n/*jshint quotmark:double */\\n\\nvar _        = require(\"underscore\");\\nvar events   = require(\"events\");\\nvar vars     = require(\"../shared/vars.js\");\\nvar messages = require(\"../shared/messages.js\");\\nvar Lexer    = require(\"./lex.js\").Lexer;\\nvar reg      = require(\"./reg.js\");\\nvar state    = require(\"./state.js\").state;\\nvar style    = require(\"./style.js\");\\n\\n// We build the application inside a function so that we produce only a single\\n// global variable. That function will be invoked immediately, and its return\\n// value is the JSHINT function itself.\\n\\nvar JSHINT = (function () {\\n\t\"use strict\";\\n\\n\tvar anonname,\t\t// The guessed name for anonymous functions.\\n\\n// These are operators that should not be used with the ! operator.\\n\\n\t\tbang = {\\n\t\t\t\"<\"  : true,\\n\t\t\t\"<=\" : true,\\n\t\t\t\"==\" : true,\\n\t\t\t\"===\": true,\\n\t\t\t\"!==\": true,\\n\t\t\t\"!=\" : true,\\n\t\t\t\">\"  : true,\\n\t\t\t\">=\" : true,\\n\t\t\t\"+\"  : true,\\n\t\t\t\"-\"  : true,\\n\t\t\t\"*\"  : true,\\n\t\t\t\"/\"  : true,\\n\t\t\t\"%\"  : true\\n\t\t},\\n\\n\t\t// These are the JSHint boolean options.\\n\t\tboolOptions = {\\n\t\t\tasi         : true, // if automatic semicolon insertion should be tolerated\\n\t\t\tbitwise     : true, // if bitwise operators should not be allowed\\n\t\t\tboss        : true, // if advanced usage of assignments should be allowed\\n\t\t\tbrowser     : true, // if the standard browser globals should be predefined\\n\t\t\tcamelcase   : true, // if identifiers should be required in camel case\\n\t\t\tcouch       : true, // if CouchDB globals should be predefined\\n\t\t\tcurly       : true, // if curly braces around all blocks should be required\\n\t\t\tdebug       : true, // if debugger statements should be allowed\\n\t\t\tdevel       : true, // if logging globals should be predefined (console, alert, etc.)\\n\t\t\tdojo        : true, // if Dojo Toolkit globals should be predefined\\n\t\t\teqeqeq      : true, // if === should be required\\n\t\t\teqnull      : true, // if == null comparisons should be tolerated\\n\t\t\tes5         : true, // if ES5 syntax should be allowed\\n\t\t\tesnext      : true, // if es.next specific syntax should be allowed\\n\t\t\tevil        : true, // if eval should be allowed\\n\t\t\texpr        : true, // if ExpressionStatement should be allowed as Programs\\n\t\t\tforin       : true, // if for in statements must filter\\n\t\t\tfuncscope   : true, // if only function scope should be used for scope tests\\n\t\t\tgcl         : true, // if JSHint should be compatible with Google Closure Linter\\n\t\t\tglobalstrict: true, // if global \"use strict\"; should be allowed (also enables \\'strict\\')\\n\t\t\timmed       : true, // if immediate invocations must be wrapped in parens\\n\t\t\titerator    : true, // if the `__iterator__` property should be allowed\\n\t\t\tjquery      : true, // if jQuery globals should be predefined\\n\t\t\tlastsemic   : true, // if semicolons may be ommitted for the trailing\\n\t\t\t                    // statements inside of a one-line blocks.\\n\t\t\tlatedef     : true, // if the use before definition should not be tolerated\\n\t\t\tlaxbreak    : true, // if line breaks should not be checked\\n\t\t\tlaxcomma    : true, // if line breaks should not be checked around commas\\n\t\t\tloopfunc    : true, // if functions should be allowed to be defined within\\n\t\t\t                    // loops\\n\t\t\tmootools    : true, // if MooTools globals should be predefined\\n\t\t\tmultistr    : true, // allow multiline strings\\n\t\t\tnewcap      : true, // if constructor names must be capitalized\\n\t\t\tnoarg       : true, // if arguments.caller and arguments.callee should be\\n\t\t\t                    // disallowed\\n\t\t\tnode        : true, // if the Node.js environment globals should be\\n\t\t\t                    // predefined\\n\t\t\tnoempty     : true, // if empty blocks should be disallowed\\n\t\t\tnonew       : true, // if using `new` for side-effects should be disallowed\\n\t\t\tnonstandard : true, // if non-standard (but widely adopted) globals should\\n\t\t\t                    // be predefined\\n\t\t\tnomen       : true, // if names should be checked\\n\t\t\tonevar      : true, // if only one var statement per function should be\\n\t\t\t                    // allowed\\n\t\t\tpassfail    : true, // if the scan should stop on first error\\n\t\t\tphantom     : true, // if PhantomJS symbols should be allowed\\n\t\t\tplusplus    : true, // if increment/decrement should not be allowed\\n\t\t\tproto       : true, // if the `__proto__` property should be allowed\\n\t\t\tprototypejs : true, // if Prototype and Scriptaculous globals should be\\n\t\t\t                    // predefined\\n\t\t\trhino       : true, // if the Rhino environment globals should be predefined\\n\t\t\tundef       : true, // if variables should be declared before used\\n\t\t\tscripturl   : true, // if script-targeted URLs should be tolerated\\n\t\t\tshadow      : true, // if variable shadowing should be tolerated\\n\t\t\tsmarttabs   : true, // if smarttabs should be tolerated\\n\t\t\t                    // (http://www.emacswiki.org/emacs/SmartTabs)\\n\t\t\tstrict      : true, // require the \"use strict\"; pragma\\n\t\t\tsub         : true, // if all forms of subscript notation are tolerated\\n\t\t\tsupernew    : true, // if `new function () { ... };` and `new Object;`\\n\t\t\t                    // should be tolerated\\n\t\t\ttrailing    : true, // if trailing whitespace rules apply\\n\t\t\tvalidthis   : true, // if \\'this\\' inside a non-constructor function is valid.\\n\t\t\t                    // This is a function scoped option only.\\n\t\t\twithstmt    : true, // if with statements should be allowed\\n\t\t\twhite       : true, // if strict whitespace rules apply\\n\t\t\tworker      : true, // if Web Worker script symbols should be allowed\\n\t\t\twsh         : true, // if the Windows Scripting Host environment globals\\n\t\t\t                    // should be predefined\\n\t\t\tyui         : true, // YUI variables should be predefined\\n\\n\t\t\t// Obsolete options\\n\t\t\tonecase     : true, // if one case switch statements should be allowed\\n\t\t\tregexp      : true, // if the . should not be allowed in regexp literals\\n\t\t\tregexdash   : true  // if unescaped first/last dash (-) inside brackets\\n\t\t\t                    // should be tolerated\\n\t\t},\\n\\n\t\t// These are the JSHint options that can take any value\\n\t\t// (we use this object to detect invalid options)\\n\t\tvalOptions = {\\n\t\t\tmaxlen       : false,\\n\t\t\tindent       : false,\\n\t\t\tmaxerr       : false,\\n\t\t\tpredef       : false,\\n\t\t\tquotmark     : false, //\\'single\\'|\\'double\\'|true\\n\t\t\tscope        : false,\\n\t\t\tmaxstatements: false, // {int} max statements per function\\n\t\t\tmaxdepth     : false, // {int} max nested block depth per function\\n\t\t\tmaxparams    : false, // {int} max params per function\\n\t\t\tmaxcomplexity: false, // {int} max cyclomatic complexity per function\\n\t\t\tunused       : true  // warn if variables are unused. Available options:\\n\t\t\t                     //   false    - don\\'t check for unused variables\\n\t\t\t                     //   true     - \"vars\" + check last function param\\n\t\t\t                     //   \"vars\"   - skip checking unused function params\\n\t\t\t                     //   \"strict\" - \"vars\" + check all function params\\n\t\t},\\n\\n\t\t// These are JSHint boolean options which are shared with JSLint\\n\t\t// where the definition in JSHint is opposite JSLint\\n\t\tinvertedOptions = {\\n\t\t\tbitwise : true,\\n\t\t\tforin   : true,\\n\t\t\tnewcap  : true,\\n\t\t\tnomen   : true,\\n\t\t\tplusplus: true,\\n\t\t\tregexp  : true,\\n\t\t\tundef   : true,\\n\t\t\twhite   : true,\\n\\n\t\t\t// Inverted and renamed, use JSHint name here\\n\t\t\teqeqeq  : true,\\n\t\t\tonevar  : true\\n\t\t},\\n\\n\t\t// These are JSHint boolean options which are shared with JSLint\\n\t\t// where the name has been changed but the effect is unchanged\\n\t\trenamedOptions = {\\n\t\t\teqeq   : \"eqeqeq\",\\n\t\t\tvars   : \"onevar\",\\n\t\t\twindows: \"wsh\"\\n\t\t},\\n\\n\t\tdeclared, // Globals that were declared using /*global ... */ syntax.\\n\t\texported, // Variables that are used outside of the current file.\\n\\n\t\tfunctionicity = [\\n\t\t\t\"closure\", \"exception\", \"global\", \"label\",\\n\t\t\t\"outer\", \"unused\", \"var\"\\n\t\t],\\n\\n\t\tfunct, // The current function\\n\t\tfunctions, // All of the functions\\n\\n\t\tglobal, // The global scope\\n\t\tignored, // Ignored warnings\\n\t\timplied, // Implied globals\\n\t\tinblock,\\n\t\tindent,\\n\t\tlookahead,\\n\t\tlex,\\n\t\tmember,\\n\t\tmembersOnly,\\n\t\tnoreach,\\n\t\tpredefined,\t\t// Global variables defined by option\\n\\n\t\tscope,  // The current scope\\n\t\tstack,\\n\t\tunuseds,\\n\t\turls,\\n\t\tuseESNextSyntax,\\n\t\twarnings,\\n\\n\t\textraModules = [],\\n\t\temitter = new events.EventEmitter();\\n\\n\tfunction checkOption(name, t) {\\n\t\tname = name.trim();\\n\\n\t\tif (/^-W\\\\d{3}$/g.test(name)) {\\n\t\t\treturn true;\\n\t\t}\\n\\n\t\tif (valOptions[name] === undefined && boolOptions[name] === undefined) {\\n\t\t\tif (t.type !== \"jslint\" || renamedOptions[name] === undefined) {\\n\t\t\t\terror(\"E001\", t, name);\\n\t\t\t\treturn false;\\n\t\t\t}\\n\t\t}\\n\\n\t\treturn true;\\n\t}\\n\\n\tfunction isString(obj) {\\n\t\treturn Object.prototype.toString.call(obj) === \"[object String]\";\\n\t}\\n\\n\tfunction isIdentifier(tkn, value) {\\n\t\tif (!tkn)\\n\t\t\treturn false;\\n\\n\t\tif (!tkn.identifier || tkn.value !== value)\\n\t\t\treturn false;\\n\\n\t\treturn true;\\n\t}\\n\\n\tfunction isReserved(token) {\\n\t\tif (!token.reserved) {\\n\t\t\treturn false;\\n\t\t}\\n\\n\t\tif (token.meta && token.meta.isFutureReservedWord) {\\n\t\t\t// ES3 FutureReservedWord in an ES5 environment.\\n\t\t\tif (state.option.es5 && !token.meta.es5) {\\n\t\t\t\treturn false;\\n\t\t\t}\\n\\n\t\t\t// Some ES5 FutureReservedWord identifiers are active only\\n\t\t\t// within a strict mode environment.\\n\t\t\tif (token.meta.strictOnly) {\\n\t\t\t\tif (!state.option.strict && !state.directive[\"use strict\"]) {\\n\t\t\t\t\treturn false;\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tif (token.isProperty) {\\n\t\t\t\treturn false;\\n\t\t\t}\\n\t\t}\\n\\n\t\treturn true;\\n\t}\\n\\n\tfunction supplant(str, data) {\\n\t\treturn str.replace(/\\\\{([^{}]*)\\\\}/g, function (a, b) {\\n\t\t\tvar r = data[b];\\n\t\t\treturn typeof r === \"string\" || typeof r === \"number\" ? r : a;\\n\t\t});\\n\t}\\n\\n\tfunction combine(t, o) {\\n\t\tvar n;\\n\t\tfor (n in o) {\\n\t\t\tif (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {\\n\t\t\t\tt[n] = o[n];\\n\t\t\t}\\n\t\t}\\n\t}\\n\\n\tfunction updatePredefined() {\\n\t\tObject.keys(JSHINT.blacklist).forEach(function (key) {\\n\t\t\tdelete predefined[key];\\n\t\t});\\n\t}\\n\\n\tfunction assume() {\\n\t\tif (state.option.couch) {\\n\t\t\tcombine(predefined, vars.couch);\\n\t\t}\\n\\n\t\tif (state.option.rhino) {\\n\t\t\tcombine(predefined, vars.rhino);\\n\t\t}\\n\\n\t\tif (state.option.phantom) {\\n\t\t\tcombine(predefined, vars.phantom);\\n\t\t}\\n\\n\t\tif (state.option.prototypejs) {\\n\t\t\tcombine(predefined, vars.prototypejs);\\n\t\t}\\n\\n\t\tif (state.option.node) {\\n\t\t\tcombine(predefined, vars.node);\\n\t\t}\\n\\n\t\tif (state.option.devel) {\\n\t\t\tcombine(predefined, vars.devel);\\n\t\t}\\n\\n\t\tif (state.option.dojo) {\\n\t\t\tcombine(predefined, vars.dojo);\\n\t\t}\\n\\n\t\tif (state.option.browser) {\\n\t\t\tcombine(predefined, vars.browser);\\n\t\t}\\n\\n\t\tif (state.option.nonstandard) {\\n\t\t\tcombine(predefined, vars.nonstandard);\\n\t\t}\\n\\n\t\tif (state.option.jquery) {\\n\t\t\tcombine(predefined, vars.jquery);\\n\t\t}\\n\\n\t\tif (state.option.mootools) {\\n\t\t\tcombine(predefined, vars.mootools);\\n\t\t}\\n\\n\t\tif (state.option.worker) {\\n\t\t\tcombine(predefined, vars.worker);\\n\t\t}\\n\\n\t\tif (state.option.wsh) {\\n\t\t\tcombine(predefined, vars.wsh);\\n\t\t}\\n\\n\t\tif (state.option.esnext) {\\n\t\t\tuseESNextSyntax();\\n\t\t}\\n\\n\t\tif (state.option.globalstrict && state.option.strict !== false) {\\n\t\t\tstate.option.strict = true;\\n\t\t}\\n\\n\t\tif (state.option.yui) {\\n\t\t\tcombine(predefined, vars.yui);\\n\t\t}\\n\t}\\n\\n\\n\t// Produce an error warning.\\n\tfunction quit(code, line, chr) {\\n\t\tvar percentage = Math.floor((line / state.lines.length) * 100);\\n\t\tvar message = messages.errors[code].desc;\\n\\n\t\tthrow {\\n\t\t\tname: \"JSHintError\",\\n\t\t\tline: line,\\n\t\t\tcharacter: chr,\\n\t\t\tmessage: message + \" (\" + percentage + \"% scanned).\",\\n\t\t\traw: message\\n\t\t};\\n\t}\\n\\n\tfunction isundef(scope, code, token, a) {\\n\t\treturn JSHINT.undefs.push([scope, code, token, a]);\\n\t}\\n\\n\tfunction warning(code, t, a, b, c, d) {\\n\t\tvar ch, l, w, msg;\\n\\n\t\tif (/^W\\\\d{3}$/.test(code)) {\\n\t\t\tif (ignored[code]) {\\n\t\t\t\treturn;\\n\t\t\t}\\n\\n\t\t\tmsg = messages.warnings[code];\\n\t\t} else if (/E\\\\d{3}/.test(code)) {\\n\t\t\tmsg = messages.errors[code];\\n\t\t} else if (/I\\\\d{3}/.test(code)) {\\n\t\t\tmsg = messages.info[code];\\n\t\t}\\n\\n\t\tt = t || state.tokens.next;\\n\t\tif (t.id === \"(end)\") {  // `~\\n\t\t\tt = state.tokens.curr;\\n\t\t}\\n\\n\t\tl = t.line || 0;\\n\t\tch = t.from || 0;\\n\\n\t\tw = {\\n\t\t\tid: \"(error)\",\\n\t\t\traw: msg.desc,\\n\t\t\tcode: msg.code,\\n\t\t\tevidence: state.lines[l - 1] || \"\",\\n\t\t\tline: l,\\n\t\t\tcharacter: ch,\\n\t\t\tscope: JSHINT.scope,\\n\t\t\ta: a,\\n\t\t\tb: b,\\n\t\t\tc: c,\\n\t\t\td: d\\n\t\t};\\n\\n\t\tw.reason = supplant(msg.desc, w);\\n\t\tJSHINT.errors.push(w);\\n\\n\t\tif (state.option.passfail) {\\n\t\t\tquit(\"E042\", l, ch);\\n\t\t}\\n\\n\t\twarnings += 1;\\n\t\tif (warnings >= state.option.maxerr) {\\n\t\t\tquit(\"E043\", l, ch);\\n\t\t}\\n\\n\t\treturn w;\\n\t}\\n\\n\tfunction warningAt(m, l, ch, a, b, c, d) {\\n\t\treturn warning(m, {\\n\t\t\tline: l,\\n\t\t\tfrom: ch\\n\t\t}, a, b, c, d);\\n\t}\\n\\n\tfunction error(m, t, a, b, c, d) {\\n\t\twarning(m, t, a, b, c, d);\\n\t}\\n\\n\tfunction errorAt(m, l, ch, a, b, c, d) {\\n\t\treturn error(m, {\\n\t\t\tline: l,\\n\t\t\tfrom: ch\\n\t\t}, a, b, c, d);\\n\t}\\n\\n\t// Tracking of \"internal\" scripts, like eval containing a static string\\n\tfunction addInternalSrc(elem, src) {\\n\t\tvar i;\\n\t\ti = {\\n\t\t\tid: \"(internal)\",\\n\t\t\telem: elem,\\n\t\t\tvalue: src\\n\t\t};\\n\t\tJSHINT.internals.push(i);\\n\t\treturn i;\\n\t}\\n\\n\tfunction addlabel(t, type, tkn) {\\n\t\t// Define t in the current function in the current scope.\\n\t\tif (type === \"exception\") {\\n\t\t\tif (_.has(funct[\"(context)\"], t)) {\\n\t\t\t\tif (funct[t] !== true && !state.option.node) {\\n\t\t\t\t\twarning(\"W002\", state.tokens.next, t);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (_.has(funct, t) && !funct[\"(global)\"]) {\\n\t\t\tif (funct[t] === true) {\\n\t\t\t\tif (state.option.latedef)\\n\t\t\t\t\twarning(\"W003\", state.tokens.next, t);\\n\t\t\t} else {\\n\t\t\t\tif (!state.option.shadow && type !== \"exception\") {\\n\t\t\t\t\twarning(\"W004\", state.tokens.next, t);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\\n\t\tfunct[t] = type;\\n\\n\t\tif (tkn) {\\n\t\t\tfunct[\"(tokens)\"][t] = tkn;\\n\t\t}\\n\\n\t\tif (funct[\"(global)\"]) {\\n\t\t\tglobal[t] = funct;\\n\t\t\tif (_.has(implied, t)) {\\n\t\t\t\tif (state.option.latedef) {\\n\t\t\t\t\twarning(\"W003\", state.tokens.next, t);\\n\t\t\t\t}\\n\\n\t\t\t\tdelete implied[t];\\n\t\t\t}\\n\t\t} else {\\n\t\t\tscope[t] = funct;\\n\t\t}\\n\t}\\n\\n\tfunction doOption() {\\n\t\tvar nt = state.tokens.next;\\n\t\tvar body = nt.body.split(\",\").map(function (s) { return s.trim(); });\\n\t\tvar predef = {};\\n\\n\t\tif (nt.type === \"globals\") {\\n\t\t\tbody.forEach(function (g) {\\n\t\t\t\tg = g.split(\":\");\\n\t\t\t\tvar key = g[0];\\n\t\t\t\tvar val = g[1];\\n\\n\t\t\t\tif (key.charAt(0) === \"-\") {\\n\t\t\t\t\tkey = key.slice(1);\\n\t\t\t\t\tval = false;\\n\\n\t\t\t\t\tJSHINT.blacklist[key] = key;\\n\t\t\t\t\tupdatePredefined();\\n\t\t\t\t} else {\\n\t\t\t\t\tpredef[key] = (val === \"true\");\\n\t\t\t\t}\\n\t\t\t});\\n\\n\t\t\tcombine(predefined, predef);\\n\\n\t\t\tfor (var key in predef) {\\n\t\t\t\tif (_.has(predef, key)) {\\n\t\t\t\t\tdeclared[key] = nt;\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (nt.type === \"exported\") {\\n\t\t\tbody.forEach(function (e) {\\n\t\t\t\texported[e] = true;\\n\t\t\t});\\n\t\t}\\n\\n\t\tif (nt.type === \"members\") {\\n\t\t\tmembersOnly = membersOnly || {};\\n\\n\t\t\tbody.forEach(function (m) {\\n\t\t\t\tvar ch1 = m.charAt(0);\\n\t\t\t\tvar ch2 = m.charAt(m.length - 1);\\n\\n\t\t\t\tif (ch1 === ch2 && (ch1 === \"\\\\\"\" || ch1 === \"\\'\")) {\\n\t\t\t\t\tm = m\\n\t\t\t\t\t\t.substr(1, m.length - 2)\\n\t\t\t\t\t\t.replace(\"\\\\\\\\b\", \"\\\\b\")\\n\t\t\t\t\t\t.replace(\"\\\\\\\\t\", \"\\\\t\")\\n\t\t\t\t\t\t.replace(\"\\\\\\\\n\", \"\\\\n\")\\n\t\t\t\t\t\t.replace(\"\\\\\\\\v\", \"\\\\v\")\\n\t\t\t\t\t\t.replace(\"\\\\\\\\f\", \"\\\\f\")\\n\t\t\t\t\t\t.replace(\"\\\\\\\\r\", \"\\\\r\")\\n\t\t\t\t\t\t.replace(\"\\\\\\\\\\\\\\\\\", \"\\\\\\\\\")\\n\t\t\t\t\t\t.replace(\"\\\\\\\\\\\\\"\", \"\\\\\"\");\\n\t\t\t\t}\\n\\n\t\t\t\tmembersOnly[m] = false;\\n\t\t\t});\\n\t\t}\\n\\n\t\tvar numvals = [\\n\t\t\t\"maxstatements\",\\n\t\t\t\"maxparams\",\\n\t\t\t\"maxdepth\",\\n\t\t\t\"maxcomplexity\",\\n\t\t\t\"maxerr\",\\n\t\t\t\"maxlen\",\\n\t\t\t\"indent\"\\n\t\t];\\n\\n\t\tif (nt.type === \"jshint\" || nt.type === \"jslint\") {\\n\t\t\tbody.forEach(function (g) {\\n\t\t\t\tg = g.split(\":\");\\n\t\t\t\tvar key = (g[0] || \"\").trim();\\n\t\t\t\tvar val = (g[1] || \"\").trim();\\n\\n\t\t\t\tif (!checkOption(key, nt)) {\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tif (numvals.indexOf(key) >= 0) {\\n\t\t\t\t\tval = +val;\\n\\n\t\t\t\t\tif (typeof val !== \"number\" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {\\n\t\t\t\t\t\terror(\"E032\", nt, g[1].trim());\\n\t\t\t\t\t\treturn;\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tif (key === \"indent\") {\\n\t\t\t\t\t\tstate.option[\"(explicitIndent)\"] = true;\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tstate.option[key] = val;\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tif (key === \"validthis\") {\\n\t\t\t\t\t// `validthis` is valid only within a function scope.\\n\t\t\t\t\tif (funct[\"(global)\"]) {\\n\t\t\t\t\t\terror(\"E009\");\\n\t\t\t\t\t} else {\\n\t\t\t\t\t\tif (val === \"true\" || val === \"false\") {\\n\t\t\t\t\t\t\tstate.option.validthis = (val === \"true\");\\n\t\t\t\t\t\t} else {\\n\t\t\t\t\t\t\terror(\"E002\", nt);\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tif (key === \"quotmark\") {\\n\t\t\t\t\tswitch (val) {\\n\t\t\t\t\tcase \"true\":\\n\t\t\t\t\tcase \"false\":\\n\t\t\t\t\t\tstate.option.quotmark = (val === \"true\");\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\tcase \"double\":\\n\t\t\t\t\tcase \"single\":\\n\t\t\t\t\t\tstate.option.quotmark = val;\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\tdefault:\\n\t\t\t\t\t\terror(\"E002\", nt);\\n\t\t\t\t\t}\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tif (key === \"unused\") {\\n\t\t\t\t\tswitch (val) {\\n\t\t\t\t\tcase \"true\":\\n\t\t\t\t\t\tstate.option.unused = true;\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\tcase \"false\":\\n\t\t\t\t\t\tstate.option.unused = false;\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\tcase \"vars\":\\n\t\t\t\t\tcase \"strict\":\\n\t\t\t\t\t\tstate.option.unused = val;\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\tdefault:\\n\t\t\t\t\t\terror(\"E002\", nt);\\n\t\t\t\t\t}\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tif (/^-W\\\\d{3}$/g.test(key)) {\\n\t\t\t\t\tignored[key.slice(1)] = true;\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tvar tn;\\n\t\t\t\tif (val === \"true\" || val === \"false\") {\\n\t\t\t\t\tif (nt.type === \"jslint\") {\\n\t\t\t\t\t\ttn = renamedOptions[key] || key;\\n\t\t\t\t\t\tstate.option[tn] = (val === \"true\");\\n\\n\t\t\t\t\t\tif (invertedOptions[tn] !== undefined) {\\n\t\t\t\t\t\t\tstate.option[tn] = !state.option[tn];\\n\t\t\t\t\t\t}\\n\t\t\t\t\t} else {\\n\t\t\t\t\t\tstate.option[key] = (val === \"true\");\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tif (key === \"newcap\") {\\n\t\t\t\t\t\tstate.option[\"(explicitNewcap)\"] = true;\\n\t\t\t\t\t}\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\terror(\"E002\", nt);\\n\t\t\t});\\n\\n\t\t\tassume();\\n\t\t}\\n\t}\\n\\n\t// We need a peek function. If it has an argument, it peeks that much farther\\n\t// ahead. It is used to distinguish\\n\t//\t   for ( var i in ...\\n\t// from\\n\t//\t   for ( var i = ...\\n\\n\tfunction peek(p) {\\n\t\tvar i = p || 0, j = 0, t;\\n\\n\t\twhile (j <= i) {\\n\t\t\tt = lookahead[j];\\n\t\t\tif (!t) {\\n\t\t\t\tt = lookahead[j] = lex.token();\\n\t\t\t}\\n\t\t\tj += 1;\\n\t\t}\\n\t\treturn t;\\n\t}\\n\\n\t// Produce the next token. It looks for programming errors.\\n\\n\tfunction advance(id, t) {\\n\t\tswitch (state.tokens.curr.id) {\\n\t\tcase \"(number)\":\\n\t\t\tif (state.tokens.next.id === \".\") {\\n\t\t\t\twarning(\"W005\", state.tokens.curr);\\n\t\t\t}\\n\t\t\tbreak;\\n\t\tcase \"-\":\\n\t\t\tif (state.tokens.next.id === \"-\" || state.tokens.next.id === \"--\") {\\n\t\t\t\twarning(\"W006\");\\n\t\t\t}\\n\t\t\tbreak;\\n\t\tcase \"+\":\\n\t\t\tif (state.tokens.next.id === \"+\" || state.tokens.next.id === \"++\") {\\n\t\t\t\twarning(\"W007\");\\n\t\t\t}\\n\t\t\tbreak;\\n\t\t}\\n\\n\t\tif (state.tokens.curr.type === \"(string)\" || state.tokens.curr.identifier) {\\n\t\t\tanonname = state.tokens.curr.value;\\n\t\t}\\n\\n\t\tif (id && state.tokens.next.id !== id) {\\n\t\t\tif (t) {\\n\t\t\t\tif (state.tokens.next.id === \"(end)\") {\\n\t\t\t\t\terror(\"E019\", t, t.id);\\n\t\t\t\t} else {\\n\t\t\t\t\terror(\"E020\", state.tokens.next, id, t.id, t.line, state.tokens.next.value);\\n\t\t\t\t}\\n\t\t\t} else if (state.tokens.next.type !== \"(identifier)\" || state.tokens.next.value !== id) {\\n\t\t\t\twarning(\"W116\", state.tokens.next, id, state.tokens.next.value);\\n\t\t\t}\\n\t\t}\\n\\n\t\tstate.tokens.prev = state.tokens.curr;\\n\t\tstate.tokens.curr = state.tokens.next;\\n\t\tfor (;;) {\\n\t\t\tstate.tokens.next = lookahead.shift() || lex.token();\\n\\n\t\t\tif (!state.tokens.next) { // No more tokens left, give up\\n\t\t\t\tquit(\"E041\", state.tokens.curr.line);\\n\t\t\t}\\n\\n\t\t\tif (state.tokens.next.id === \"(end)\" || state.tokens.next.id === \"(error)\") {\\n\t\t\t\treturn;\\n\t\t\t}\\n\\n\t\t\tif (state.tokens.next.isSpecial) {\\n\t\t\t\tdoOption();\\n\t\t\t} else {\\n\t\t\t\tif (state.tokens.next.id !== \"(endline)\") {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\t}\\n\\n\\n\t// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it\\n\t// is looking for ad hoc lint patterns. We add .fud to Pratt\\'s model, which is\\n\t// like .nud except that it is only used on the first token of a statement.\\n\t// Having .fud makes it much easier to define statement-oriented languages like\\n\t// JavaScript. I retained Pratt\\'s nomenclature.\\n\\n\t// .nud  Null denotation\\n\t// .fud  First null denotation\\n\t// .led  Left denotation\\n\t//  lbp  Left binding power\\n\t//  rbp  Right binding power\\n\\n\t// They are elements of the parsing method called Top Down Operator Precedence.\\n\\n\tfunction expression(rbp, initial) {\\n\t\tvar left, isArray = false, isObject = false;\\n\\n\t\tif (state.tokens.next.id === \"(end)\")\\n\t\t\terror(\"E006\", state.tokens.curr);\\n\\n\t\tadvance();\\n\\n\t\tif (initial) {\\n\t\t\tanonname = \"anonymous\";\\n\t\t\tfunct[\"(verb)\"] = state.tokens.curr.value;\\n\t\t}\\n\\n\t\tif (initial === true && state.tokens.curr.fud) {\\n\t\t\tleft = state.tokens.curr.fud();\\n\t\t} else {\\n\t\t\tif (state.tokens.curr.nud) {\\n\t\t\t\tleft = state.tokens.curr.nud();\\n\t\t\t} else {\\n\t\t\t\terror(\"E030\", state.tokens.curr, state.tokens.curr.id);\\n\t\t\t}\\n\\n\t\t\twhile (rbp < state.tokens.next.lbp) {\\n\t\t\t\tisArray = state.tokens.curr.value === \"Array\";\\n\t\t\t\tisObject = state.tokens.curr.value === \"Object\";\\n\\n\t\t\t\t// #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()\\n\t\t\t\t// Line breaks in IfStatement heads exist to satisfy the checkJSHint\\n\t\t\t\t// \"Line too long.\" error.\\n\t\t\t\tif (left && (left.value || (left.first && left.first.value))) {\\n\t\t\t\t\t// If the left.value is not \"new\", or the left.first.value is a \".\"\\n\t\t\t\t\t// then safely assume that this is not \"new Array()\" and possibly\\n\t\t\t\t\t// not \"new Object()\"...\\n\t\t\t\t\tif (left.value !== \"new\" ||\\n\t\t\t\t\t  (left.first && left.first.value && left.first.value === \".\")) {\\n\t\t\t\t\t\tisArray = false;\\n\t\t\t\t\t\t// ...In the case of Object, if the left.value and state.tokens.curr.value\\n\t\t\t\t\t\t// are not equal, then safely assume that this not \"new Object()\"\\n\t\t\t\t\t\tif (left.value !== state.tokens.curr.value) {\\n\t\t\t\t\t\t\tisObject = false;\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\tadvance();\\n\\n\t\t\t\tif (isArray && state.tokens.curr.id === \"(\" && state.tokens.next.id === \")\") {\\n\t\t\t\t\twarning(\"W009\", state.tokens.curr);\\n\t\t\t\t}\\n\\n\t\t\t\tif (isObject && state.tokens.curr.id === \"(\" && state.tokens.next.id === \")\") {\\n\t\t\t\t\twarning(\"W010\", state.tokens.curr);\\n\t\t\t\t}\\n\\n\t\t\t\tif (state.tokens.curr.led) {\\n\t\t\t\t\tleft = state.tokens.curr.led(left);\\n\t\t\t\t} else {\\n\t\t\t\t\terror(\"E033\", state.tokens.curr, state.tokens.curr.id);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\t\treturn left;\\n\t}\\n\\n\\n// Functions for conformance of style.\\n\\n\tfunction adjacent(left, right) {\\n\t\tleft = left || state.tokens.curr;\\n\t\tright = right || state.tokens.next;\\n\t\tif (state.option.white) {\\n\t\t\tif (left.character !== right.from && left.line === right.line) {\\n\t\t\t\tleft.from += (left.character - left.from);\\n\t\t\t\twarning(\"W011\", left, left.value);\\n\t\t\t}\\n\t\t}\\n\t}\\n\\n\tfunction nobreak(left, right) {\\n\t\tleft = left || state.tokens.curr;\\n\t\tright = right || state.tokens.next;\\n\t\tif (state.option.white && (left.character !== right.from || left.line !== right.line)) {\\n\t\t\twarning(\"W012\", right, right.value);\\n\t\t}\\n\t}\\n\\n\tfunction nospace(left, right) {\\n\t\tleft = left || state.tokens.curr;\\n\t\tright = right || state.tokens.next;\\n\t\tif (state.option.white && !left.comment) {\\n\t\t\tif (left.line === right.line) {\\n\t\t\t\tadjacent(left, right);\\n\t\t\t}\\n\t\t}\\n\t}\\n\\n\tfunction nonadjacent(left, right) {\\n\t\tif (state.option.white) {\\n\t\t\tleft = left || state.tokens.curr;\\n\t\t\tright = right || state.tokens.next;\\n\\n\t\t\tif (left.value === \";\" && right.value === \";\") {\\n\t\t\t\treturn;\\n\t\t\t}\\n\\n\t\t\tif (left.line === right.line && left.character === right.from) {\\n\t\t\t\tleft.from += (left.character - left.from);\\n\t\t\t\twarning(\"W013\", left, left.value);\\n\t\t\t}\\n\t\t}\\n\t}\\n\\n\tfunction nobreaknonadjacent(left, right) {\\n\t\tleft = left || state.tokens.curr;\\n\t\tright = right || state.tokens.next;\\n\t\tif (!state.option.laxbreak && left.line !== right.line) {\\n\t\t\twarning(\"W014\", right, right.id);\\n\t\t} else if (state.option.white) {\\n\t\t\tleft = left || state.tokens.curr;\\n\t\t\tright = right || state.tokens.next;\\n\t\t\tif (left.character === right.from) {\\n\t\t\t\tleft.from += (left.character - left.from);\\n\t\t\t\twarning(\"W013\", left, left.value);\\n\t\t\t}\\n\t\t}\\n\t}\\n\\n\tfunction indentation(bias) {\\n\t\tif (!state.option.white && !state.option[\"(explicitIndent)\"]) {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\tif (state.tokens.next.id === \"(end)\") {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\tvar i = indent + (bias || 0);\\n\t\tif (state.tokens.next.from !== i) {\\n\t\t\twarning(\"W015\", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);\\n\t\t}\\n\t}\\n\\n\tfunction nolinebreak(t) {\\n\t\tt = t || state.tokens.curr;\\n\t\tif (t.line !== state.tokens.next.line) {\\n\t\t\twarning(\"E022\", t, t.value);\\n\t\t}\\n\t}\\n\\n\\n\tfunction comma(opts) {\\n\t\topts = opts || {};\\n\\n\t\tif (state.tokens.curr.line !== state.tokens.next.line) {\\n\t\t\tif (!state.option.laxcomma) {\\n\t\t\t\tif (comma.first) {\\n\t\t\t\t\twarning(\"I001\");\\n\t\t\t\t\tcomma.first = false;\\n\t\t\t\t}\\n\t\t\t\twarning(\"W014\", state.tokens.curr, state.tokens.next.id);\\n\t\t\t}\\n\t\t} else if (!state.tokens.curr.comment &&\\n\t\t\t\tstate.tokens.curr.character !== state.tokens.next.from && state.option.white) {\\n\t\t\tstate.tokens.curr.from += (state.tokens.curr.character - state.tokens.curr.from);\\n\t\t\twarning(\"W011\", state.tokens.curr, state.tokens.curr.value);\\n\t\t}\\n\\n\t\tadvance(\",\");\\n\\n\t\t// TODO: This is a temporary solution to fight against false-positives in\\n\t\t// arrays and objects with trailing commas (see GH-363). The best solution\\n\t\t// would be to extract all whitespace rules out of parser.\\n\\n\t\tif (state.tokens.next.value !== \"]\" && state.tokens.next.value !== \"}\") {\\n\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t}\\n\\n\t\tif (state.tokens.next.identifier) {\\n\t\t\t// Keywords that cannot follow a comma operator.\\n\t\t\tswitch (state.tokens.next.value) {\\n\t\t\tcase \"break\":\\n\t\t\tcase \"case\":\\n\t\t\tcase \"catch\":\\n\t\t\tcase \"continue\":\\n\t\t\tcase \"default\":\\n\t\t\tcase \"do\":\\n\t\t\tcase \"else\":\\n\t\t\tcase \"finally\":\\n\t\t\tcase \"for\":\\n\t\t\tcase \"if\":\\n\t\t\tcase \"in\":\\n\t\t\tcase \"instanceof\":\\n\t\t\tcase \"return\":\\n\t\t\tcase \"switch\":\\n\t\t\tcase \"throw\":\\n\t\t\tcase \"try\":\\n\t\t\tcase \"var\":\\n\t\t\tcase \"while\":\\n\t\t\tcase \"with\":\\n\t\t\t\terror(\"E024\", state.tokens.next, state.tokens.next.value);\\n\t\t\t\treturn;\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (state.tokens.next.type === \"(punctuator)\") {\\n\t\t\tswitch (state.tokens.next.value) {\\n\t\t\tcase \"}\":\\n\t\t\tcase \"]\":\\n\t\t\tcase \",\":\\n\t\t\t\tif (opts.allowTrailing) {\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\t/* falls through */\\n\t\t\tcase \")\":\\n\t\t\t\terror(\"E024\", state.tokens.next, state.tokens.next.value);\\n\t\t\t}\\n\t\t}\\n\t}\\n\\n\t// Functional constructors for making the symbols that will be inherited by\\n\t// tokens.\\n\\n\tfunction symbol(s, p) {\\n\t\tvar x = state.syntax[s];\\n\t\tif (!x || typeof x !== \"object\") {\\n\t\t\tstate.syntax[s] = x = {\\n\t\t\t\tid: s,\\n\t\t\t\tlbp: p,\\n\t\t\t\tvalue: s\\n\t\t\t};\\n\t\t}\\n\t\treturn x;\\n\t}\\n\\n\tfunction delim(s) {\\n\t\treturn symbol(s, 0);\\n\t}\\n\\n\tfunction stmt(s, f) {\\n\t\tvar x = delim(s);\\n\t\tx.identifier = x.reserved = true;\\n\t\tx.fud = f;\\n\t\treturn x;\\n\t}\\n\\n\tfunction blockstmt(s, f) {\\n\t\tvar x = stmt(s, f);\\n\t\tx.block = true;\\n\t\treturn x;\\n\t}\\n\\n\tfunction reserveName(x) {\\n\t\tvar c = x.id.charAt(0);\\n\t\tif ((c >= \"a\" && c <= \"z\") || (c >= \"A\" && c <= \"Z\")) {\\n\t\t\tx.identifier = x.reserved = true;\\n\t\t}\\n\t\treturn x;\\n\t}\\n\\n\tfunction prefix(s, f) {\\n\t\tvar x = symbol(s, 150);\\n\t\treserveName(x);\\n\t\tx.nud = (typeof f === \"function\") ? f : function () {\\n\t\t\tthis.right = expression(150);\\n\t\t\tthis.arity = \"unary\";\\n\t\t\tif (this.id === \"++\" || this.id === \"--\") {\\n\t\t\t\tif (state.option.plusplus) {\\n\t\t\t\t\twarning(\"W016\", this, this.id);\\n\t\t\t\t} else if ((!this.right.identifier || isReserved(this.right)) &&\\n\t\t\t\t\t\tthis.right.id !== \".\" && this.right.id !== \"[\") {\\n\t\t\t\t\twarning(\"W017\", this);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\treturn this;\\n\t\t};\\n\t\treturn x;\\n\t}\\n\\n\tfunction type(s, f) {\\n\t\tvar x = delim(s);\\n\t\tx.type = s;\\n\t\tx.nud = f;\\n\t\treturn x;\\n\t}\\n\\n\tfunction reserve(name, func) {\\n\t\tvar x = type(name, func);\\n\t\tx.identifier = true;\\n\t\tx.reserved = true;\\n\t\treturn x;\\n\t}\\n\\n\tfunction FutureReservedWord(name, meta) {\\n\t\tvar x = type(name, function () {\\n\t\t\treturn this;\\n\t\t});\\n\\n\t\tmeta = meta || {};\\n\t\tmeta.isFutureReservedWord = true;\\n\\n\t\tx.value = name;\\n\t\tx.identifier = true;\\n\t\tx.reserved = true;\\n\t\tx.meta = meta;\\n\\n\t\treturn x;\\n\t}\\n\\n\tfunction reservevar(s, v) {\\n\t\treturn reserve(s, function () {\\n\t\t\tif (typeof v === \"function\") {\\n\t\t\t\tv(this);\\n\t\t\t}\\n\t\t\treturn this;\\n\t\t});\\n\t}\\n\\n\tfunction infix(s, f, p, w) {\\n\t\tvar x = symbol(s, p);\\n\t\treserveName(x);\\n\t\tx.led = function (left) {\\n\t\t\tif (!w) {\\n\t\t\t\tnobreaknonadjacent(state.tokens.prev, state.tokens.curr);\\n\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t}\\n\t\t\tif (s === \"in\" && left.id === \"!\") {\\n\t\t\t\twarning(\"W018\", left, \"!\");\\n\t\t\t}\\n\t\t\tif (typeof f === \"function\") {\\n\t\t\t\treturn f(left, this);\\n\t\t\t} else {\\n\t\t\t\tthis.left = left;\\n\t\t\t\tthis.right = expression(p);\\n\t\t\t\treturn this;\\n\t\t\t}\\n\t\t};\\n\t\treturn x;\\n\t}\\n\\n\tfunction relation(s, f) {\\n\t\tvar x = symbol(s, 100);\\n\\n\t\tx.led = function (left) {\\n\t\t\tnobreaknonadjacent(state.tokens.prev, state.tokens.curr);\\n\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\tvar right = expression(100);\\n\\n\t\t\tif (isIdentifier(left, \"NaN\") || isIdentifier(right, \"NaN\")) {\\n\t\t\t\twarning(\"W019\", this);\\n\t\t\t} else if (f) {\\n\t\t\t\tf.apply(this, [left, right]);\\n\t\t\t}\\n\\n\t\t\tif (!left || !right) {\\n\t\t\t\tquit(\"E041\", state.tokens.curr.line);\\n\t\t\t}\\n\\n\t\t\tif (left.id === \"!\") {\\n\t\t\t\twarning(\"W018\", left, \"!\");\\n\t\t\t}\\n\\n\t\t\tif (right.id === \"!\") {\\n\t\t\t\twarning(\"W018\", right, \"!\");\\n\t\t\t}\\n\\n\t\t\tthis.left = left;\\n\t\t\tthis.right = right;\\n\t\t\treturn this;\\n\t\t};\\n\t\treturn x;\\n\t}\\n\\n\tfunction isPoorRelation(node) {\\n\t\treturn node &&\\n\t\t\t  ((node.type === \"(number)\" && +node.value === 0) ||\\n\t\t\t   (node.type === \"(string)\" && node.value === \"\") ||\\n\t\t\t   (node.type === \"null\" && !state.option.eqnull) ||\\n\t\t\t\tnode.type === \"true\" ||\\n\t\t\t\tnode.type === \"false\" ||\\n\t\t\t\tnode.type === \"undefined\");\\n\t}\\n\\n\tfunction assignop(s) {\\n\t\tsymbol(s, 20).exps = true;\\n\\n\t\treturn infix(s, function (left, that) {\\n\t\t\tthat.left = left;\\n\\n\t\t\tif (predefined[left.value] === false &&\\n\t\t\t\t\tscope[left.value][\"(global)\"] === true) {\\n\t\t\t\twarning(\"W020\", left);\\n\t\t\t} else if (left[\"function\"]) {\\n\t\t\t\twarning(\"W021\", left, left.value);\\n\t\t\t}\\n\\n\t\t\tif (left) {\\n\t\t\t\tif (state.option.esnext && funct[left.value] === \"const\") {\\n\t\t\t\t\terror(\"E013\", left, left.value);\\n\t\t\t\t}\\n\\n\t\t\t\tif (left.id === \".\" || left.id === \"[\") {\\n\t\t\t\t\tif (!left.left || left.left.value === \"arguments\") {\\n\t\t\t\t\t\twarning(\"E031\", that);\\n\t\t\t\t\t}\\n\t\t\t\t\tthat.right = expression(19);\\n\t\t\t\t\treturn that;\\n\t\t\t\t} else if (left.identifier && !isReserved(left)) {\\n\t\t\t\t\tif (funct[left.value] === \"exception\") {\\n\t\t\t\t\t\twarning(\"W022\", left);\\n\t\t\t\t\t}\\n\t\t\t\t\tthat.right = expression(19);\\n\t\t\t\t\treturn that;\\n\t\t\t\t}\\n\\n\t\t\t\tif (left === state.syntax[\"function\"]) {\\n\t\t\t\t\twarning(\"W023\", state.tokens.curr);\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\terror(\"E031\", that);\\n\t\t}, 20);\\n\t}\\n\\n\\n\tfunction bitwise(s, f, p) {\\n\t\tvar x = symbol(s, p);\\n\t\treserveName(x);\\n\t\tx.led = (typeof f === \"function\") ? f : function (left) {\\n\t\t\tif (state.option.bitwise) {\\n\t\t\t\twarning(\"W016\", this, this.id);\\n\t\t\t}\\n\t\t\tthis.left = left;\\n\t\t\tthis.right = expression(p);\\n\t\t\treturn this;\\n\t\t};\\n\t\treturn x;\\n\t}\\n\\n\\n\tfunction bitwiseassignop(s) {\\n\t\tsymbol(s, 20).exps = true;\\n\t\treturn infix(s, function (left, that) {\\n\t\t\tif (state.option.bitwise) {\\n\t\t\t\twarning(\"W016\", that, that.id);\\n\t\t\t}\\n\t\t\tnonadjacent(state.tokens.prev, state.tokens.curr);\\n\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\tif (left) {\\n\t\t\t\tif (left.id === \".\" || left.id === \"[\" ||\\n\t\t\t\t\t\t(left.identifier && !isReserved(left))) {\\n\t\t\t\t\texpression(19);\\n\t\t\t\t\treturn that;\\n\t\t\t\t}\\n\t\t\t\tif (left === state.syntax[\"function\"]) {\\n\t\t\t\t\twarning(\"W023\", state.tokens.curr);\\n\t\t\t\t}\\n\t\t\t\treturn that;\\n\t\t\t}\\n\t\t\terror(\"E031\", that);\\n\t\t}, 20);\\n\t}\\n\\n\\n\tfunction suffix(s) {\\n\t\tvar x = symbol(s, 150);\\n\\n\t\tx.led = function (left) {\\n\t\t\tif (state.option.plusplus) {\\n\t\t\t\twarning(\"W016\", this, this.id);\\n\t\t\t} else if ((!left.identifier || isReserved(left)) && left.id !== \".\" && left.id !== \"[\") {\\n\t\t\t\twarning(\"W017\", this);\\n\t\t\t}\\n\\n\t\t\tthis.left = left;\\n\t\t\treturn this;\\n\t\t};\\n\t\treturn x;\\n\t}\\n\\n\t// fnparam means that this identifier is being defined as a function\\n\t// argument (see identifier())\\n\t// prop means that this identifier is that of an object property\\n\\n\tfunction optionalidentifier(fnparam, prop) {\\n\t\tif (!state.tokens.next.identifier) {\\n\t\t\treturn;\\n\t\t}\\n\\n\t\tadvance();\\n\\n\t\tvar curr = state.tokens.curr;\\n\t\tvar meta = curr.meta || {};\\n\t\tvar val  = state.tokens.curr.value;\\n\\n\t\tif (!isReserved(curr)) {\\n\t\t\treturn val;\\n\t\t}\\n\\n\t\tif (prop) {\\n\t\t\tif (state.option.es5 || meta.isFutureReservedWord) {\\n\t\t\t\treturn val;\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (fnparam && val === \"undefined\") {\\n\t\t\treturn val;\\n\t\t}\\n\\n\t\twarning(\"W024\", state.tokens.curr, state.tokens.curr.id);\\n\t\treturn val;\\n\t}\\n\\n\t// fnparam means that this identifier is being defined as a function\\n\t// argument\\n\t// prop means that this identifier is that of an object property\\n\tfunction identifier(fnparam, prop) {\\n\t\tvar i = optionalidentifier(fnparam, prop);\\n\t\tif (i) {\\n\t\t\treturn i;\\n\t\t}\\n\t\tif (state.tokens.curr.id === \"function\" && state.tokens.next.id === \"(\") {\\n\t\t\twarning(\"W025\");\\n\t\t} else {\\n\t\t\terror(\"E030\", state.tokens.next, state.tokens.next.value);\\n\t\t}\\n\t}\\n\\n\\n\tfunction reachable(s) {\\n\t\tvar i = 0, t;\\n\t\tif (state.tokens.next.id !== \";\" || noreach) {\\n\t\t\treturn;\\n\t\t}\\n\t\tfor (;;) {\\n\t\t\tt = peek(i);\\n\t\t\tif (t.reach) {\\n\t\t\t\treturn;\\n\t\t\t}\\n\t\t\tif (t.id !== \"(endline)\") {\\n\t\t\t\tif (t.id === \"function\") {\\n\t\t\t\t\tif (!state.option.latedef) {\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t}\\n\\n\t\t\t\t\twarning(\"W026\", t);\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\\n\t\t\t\twarning(\"W027\", t, t.value, s);\\n\t\t\t\tbreak;\\n\t\t\t}\\n\t\t\ti += 1;\\n\t\t}\\n\t}\\n\\n\\n\tfunction statement(noindent) {\\n\t\tvar i = indent, r, s = scope, t = state.tokens.next;\\n\\n\t\tif (t.id === \";\") {\\n\t\t\tadvance(\";\");\\n\t\t\treturn;\\n\t\t}\\n\\n\t\t// Is this a labelled statement?\\n\t\tvar res = isReserved(t);\\n\\n\t\t// We\\'re being more tolerant here: if someone uses\\n\t\t// a FutureReservedWord as a label, we warn but proceed\\n\t\t// anyway.\\n\\n\t\tif (res && t.meta && t.meta.isFutureReservedWord) {\\n\t\t\twarning(\"W024\", t, t.id);\\n\t\t\tres = false;\\n\t\t}\\n\\n\t\tif (t.identifier && !res && peek().id === \":\") {\\n\t\t\tadvance();\\n\t\t\tadvance(\":\");\\n\t\t\tscope = Object.create(s);\\n\t\t\taddlabel(t.value, \"label\");\\n\\n\t\t\tif (!state.tokens.next.labelled && state.tokens.next.value !== \"{\") {\\n\t\t\t\twarning(\"W028\", state.tokens.next, t.value, state.tokens.next.value);\\n\t\t\t}\\n\\n\t\t\tif (reg.javascriptURL.test(t.value + \":\")) {\\n\t\t\t\twarning(\"W029\", t, t.value);\\n\t\t\t}\\n\\n\t\t\tstate.tokens.next.label = t.value;\\n\t\t\tt = state.tokens.next;\\n\t\t}\\n\\n\t\t// Is it a lonely block?\\n\\n\t\tif (t.id === \"{\") {\\n\t\t\tblock(true, true);\\n\t\t\treturn;\\n\t\t}\\n\\n\t\t// Parse the statement.\\n\\n\t\tif (!noindent) {\\n\t\t\tindentation();\\n\t\t}\\n\t\tr = expression(0, true);\\n\\n\t\t// Look for the final semicolon.\\n\\n\t\tif (!t.block) {\\n\t\t\tif (!state.option.expr && (!r || !r.exps)) {\\n\t\t\t\twarning(\"W030\", state.tokens.curr);\\n\t\t\t} else if (state.option.nonew && r.id === \"(\" && r.left.id === \"new\") {\\n\t\t\t\twarning(\"W031\", t);\\n\t\t\t}\\n\\n\t\t\tif (state.tokens.next.id === \",\") {\\n\t\t\t\treturn comma();\\n\t\t\t}\\n\\n\t\t\tif (state.tokens.next.id !== \";\") {\\n\t\t\t\tif (!state.option.asi) {\\n\t\t\t\t\t// If this is the last statement in a block that ends on\\n\t\t\t\t\t// the same line *and* option lastsemic is on, ignore the warning.\\n\t\t\t\t\t// Otherwise, complain about missing semicolon.\\n\t\t\t\t\tif (!state.option.lastsemic || state.tokens.next.id !== \"}\" ||\\n\t\t\t\t\t\tstate.tokens.next.line !== state.tokens.curr.line) {\\n\t\t\t\t\t\twarningAt(\"W033\", state.tokens.curr.line, state.tokens.curr.character);\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t} else {\\n\t\t\t\tadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\tadvance(\";\");\\n\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t}\\n\t\t}\\n\\n\t\t// Restore the indentation.\\n\\n\t\tindent = i;\\n\t\tscope = s;\\n\t\treturn r;\\n\t}\\n\\n\\n\tfunction statements(startLine) {\\n\t\tvar a = [], p;\\n\\n\t\twhile (!state.tokens.next.reach && state.tokens.next.id !== \"(end)\") {\\n\t\t\tif (state.tokens.next.id === \";\") {\\n\t\t\t\tp = peek();\\n\\n\t\t\t\tif (!p || (p.id !== \"(\" && p.id !== \"[\")) {\\n\t\t\t\t\twarning(\"W032\");\\n\t\t\t\t}\\n\\n\t\t\t\tadvance(\";\");\\n\t\t\t} else {\\n\t\t\t\ta.push(statement(startLine === state.tokens.next.line));\\n\t\t\t}\\n\t\t}\\n\t\treturn a;\\n\t}\\n\\n\\n\t/*\\n\t * read all directives\\n\t * recognizes a simple form of asi, but always\\n\t * warns, if it is used\\n\t */\\n\tfunction directives() {\\n\t\tvar i, p, pn;\\n\\n\t\tfor (;;) {\\n\t\t\tif (state.tokens.next.id === \"(string)\") {\\n\t\t\t\tp = peek(0);\\n\t\t\t\tif (p.id === \"(endline)\") {\\n\t\t\t\t\ti = 1;\\n\t\t\t\t\tdo {\\n\t\t\t\t\t\tpn = peek(i);\\n\t\t\t\t\t\ti = i + 1;\\n\t\t\t\t\t} while (pn.id === \"(endline)\");\\n\\n\t\t\t\t\tif (pn.id !== \";\") {\\n\t\t\t\t\t\tif (pn.id !== \"(string)\" && pn.id !== \"(number)\" &&\\n\t\t\t\t\t\t\tpn.id !== \"(regexp)\" && pn.identifier !== true &&\\n\t\t\t\t\t\t\tpn.id !== \"}\") {\\n\t\t\t\t\t\t\tbreak;\\n\t\t\t\t\t\t}\\n\t\t\t\t\t\twarning(\"W033\", state.tokens.next);\\n\t\t\t\t\t} else {\\n\t\t\t\t\t\tp = pn;\\n\t\t\t\t\t}\\n\t\t\t\t} else if (p.id === \"}\") {\\n\t\t\t\t\t// Directive with no other statements, warn about missing semicolon\\n\t\t\t\t\twarning(\"W033\", p);\\n\t\t\t\t} else if (p.id !== \";\") {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\\n\t\t\t\tindentation();\\n\t\t\t\tadvance();\\n\t\t\t\tif (state.directive[state.tokens.curr.value]) {\\n\t\t\t\t\twarning(\"W034\", state.tokens.curr, state.tokens.curr.value);\\n\t\t\t\t}\\n\\n\t\t\t\tif (state.tokens.curr.value === \"use strict\") {\\n\t\t\t\t\tif (!state.option[\"(explicitNewcap)\"])\\n\t\t\t\t\t\tstate.option.newcap = true;\\n\t\t\t\t\tstate.option.undef = true;\\n\t\t\t\t}\\n\\n\t\t\t\t// there\\'s no directive negation, so always set to true\\n\t\t\t\tstate.directive[state.tokens.curr.value] = true;\\n\\n\t\t\t\tif (p.id === \";\") {\\n\t\t\t\t\tadvance(\";\");\\n\t\t\t\t}\\n\t\t\t\tcontinue;\\n\t\t\t}\\n\t\t\tbreak;\\n\t\t}\\n\t}\\n\\n\\n\t/*\\n\t * Parses a single block. A block is a sequence of statements wrapped in\\n\t * braces.\\n\t *\\n\t * ordinary - true for everything but function bodies and try blocks.\\n\t * stmt\t\t- true if block can be a single statement (e.g. in if/for/while).\\n\t * isfunc\t- true if block is a function body\\n\t */\\n\tfunction block(ordinary, stmt, isfunc) {\\n\t\tvar a,\\n\t\t\tb = inblock,\\n\t\t\told_indent = indent,\\n\t\t\tm,\\n\t\t\ts = scope,\\n\t\t\tt,\\n\t\t\tline,\\n\t\t\td;\\n\\n\t\tinblock = ordinary;\\n\\n\t\tif (!ordinary || !state.option.funcscope)\\n\t\t\tscope = Object.create(scope);\\n\\n\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\tt = state.tokens.next;\\n\\n\t\tvar metrics = funct[\"(metrics)\"];\\n\t\tmetrics.nestedBlockDepth += 1;\\n\t\tmetrics.verifyMaxNestedBlockDepthPerFunction();\\n\\n\t\tif (state.tokens.next.id === \"{\") {\\n\t\t\tadvance(\"{\");\\n\t\t\tline = state.tokens.curr.line;\\n\t\t\tif (state.tokens.next.id !== \"}\") {\\n\t\t\t\tindent += state.option.indent;\\n\t\t\t\twhile (!ordinary && state.tokens.next.from > indent) {\\n\t\t\t\t\tindent += state.option.indent;\\n\t\t\t\t}\\n\\n\t\t\t\tif (isfunc) {\\n\t\t\t\t\tm = {};\\n\t\t\t\t\tfor (d in state.directive) {\\n\t\t\t\t\t\tif (_.has(state.directive, d)) {\\n\t\t\t\t\t\t\tm[d] = state.directive[d];\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\t\t\t\t\tdirectives();\\n\\n\t\t\t\t\tif (state.option.strict && funct[\"(context)\"][\"(global)\"]) {\\n\t\t\t\t\t\tif (!m[\"use strict\"] && !state.directive[\"use strict\"]) {\\n\t\t\t\t\t\t\twarning(\"E007\");\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\ta = statements(line);\\n\\n\t\t\t\tmetrics.statementCount += a.length;\\n\\n\t\t\t\tif (isfunc) {\\n\t\t\t\t\tstate.directive = m;\\n\t\t\t\t}\\n\\n\t\t\t\tindent -= state.option.indent;\\n\t\t\t\tif (line !== state.tokens.next.line) {\\n\t\t\t\t\tindentation();\\n\t\t\t\t}\\n\t\t\t} else if (line !== state.tokens.next.line) {\\n\t\t\t\tindentation();\\n\t\t\t}\\n\t\t\tadvance(\"}\", t);\\n\t\t\tindent = old_indent;\\n\t\t} else if (!ordinary) {\\n\t\t\terror(\"E021\", state.tokens.next, \"{\", state.tokens.next.value);\\n\t\t} else {\\n\t\t\tif (!stmt || state.option.curly) {\\n\t\t\t\twarning(\"W116\", state.tokens.next, \"{\", state.tokens.next.value);\\n\t\t\t}\\n\\n\t\t\tnoreach = true;\\n\t\t\tindent += state.option.indent;\\n\t\t\t// test indentation only if statement is in new line\\n\t\t\ta = [statement(state.tokens.next.line === state.tokens.curr.line)];\\n\t\t\tindent -= state.option.indent;\\n\t\t\tnoreach = false;\\n\t\t}\\n\t\tfunct[\"(verb)\"] = null;\\n\t\tif (!ordinary || !state.option.funcscope) scope = s;\\n\t\tinblock = b;\\n\t\tif (ordinary && state.option.noempty && (!a || a.length === 0)) {\\n\t\t\twarning(\"W035\");\\n\t\t}\\n\t\tmetrics.nestedBlockDepth -= 1;\\n\t\treturn a;\\n\t}\\n\\n\\n\tfunction countMember(m) {\\n\t\tif (membersOnly && typeof membersOnly[m] !== \"boolean\") {\\n\t\t\twarning(\"W036\", state.tokens.curr, m);\\n\t\t}\\n\t\tif (typeof member[m] === \"number\") {\\n\t\t\tmember[m] += 1;\\n\t\t} else {\\n\t\t\tmember[m] = 1;\\n\t\t}\\n\t}\\n\\n\\n\tfunction note_implied(tkn) {\\n\t\tvar name = tkn.value, line = tkn.line, a = implied[name];\\n\t\tif (typeof a === \"function\") {\\n\t\t\ta = false;\\n\t\t}\\n\\n\t\tif (!a) {\\n\t\t\ta = [line];\\n\t\t\timplied[name] = a;\\n\t\t} else if (a[a.length - 1] !== line) {\\n\t\t\ta.push(line);\\n\t\t}\\n\t}\\n\\n\\n\t// Build the syntax table by declaring the syntactic elements of the language.\\n\\n\ttype(\"(number)\", function () {\\n\t\treturn this;\\n\t});\\n\\n\ttype(\"(string)\", function () {\\n\t\treturn this;\\n\t});\\n\\n\tstate.syntax[\"(identifier)\"] = {\\n\t\ttype: \"(identifier)\",\\n\t\tlbp: 0,\\n\t\tidentifier: true,\\n\t\tnud: function () {\\n\t\t\tvar v = this.value,\\n\t\t\t\ts = scope[v],\\n\t\t\t\tf;\\n\\n\t\t\tif (typeof s === \"function\") {\\n\t\t\t\t// Protection against accidental inheritance.\\n\t\t\t\ts = undefined;\\n\t\t\t} else if (typeof s === \"boolean\") {\\n\t\t\t\tf = funct;\\n\t\t\t\tfunct = functions[0];\\n\t\t\t\taddlabel(v, \"var\");\\n\t\t\t\ts = funct;\\n\t\t\t\tfunct = f;\\n\t\t\t}\\n\\n\t\t\t// The name is in scope and defined in the current function.\\n\t\t\tif (funct === s) {\\n\t\t\t\t// Change \\'unused\\' to \\'var\\', and reject labels.\\n\t\t\t\tswitch (funct[v]) {\\n\t\t\t\tcase \"unused\":\\n\t\t\t\t\tfunct[v] = \"var\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"unction\":\\n\t\t\t\t\tfunct[v] = \"function\";\\n\t\t\t\t\tthis[\"function\"] = true;\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"function\":\\n\t\t\t\t\tthis[\"function\"] = true;\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"label\":\\n\t\t\t\t\twarning(\"W037\", state.tokens.curr, v);\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t} else if (funct[\"(global)\"]) {\\n\t\t\t\t// The name is not defined in the function.  If we are in the global\\n\t\t\t\t// scope, then we have an undefined variable.\\n\t\t\t\t//\\n\t\t\t\t// Operators typeof and delete do not raise runtime errors even if\\n\t\t\t\t// the base object of a reference is null so no need to display warning\\n\t\t\t\t// if we\\'re inside of typeof or delete.\\n\\n\t\t\t\tif (typeof predefined[v] !== \"boolean\") {\\n\t\t\t\t\t// Attempting to subscript a null reference will throw an\\n\t\t\t\t\t// error, even within the typeof and delete operators\\n\t\t\t\t\tif (!(anonname === \"typeof\" || anonname === \"delete\") ||\\n\t\t\t\t\t\t(state.tokens.next && (state.tokens.next.value === \".\" ||\\n\t\t\t\t\t\t\tstate.tokens.next.value === \"[\"))) {\\n\\n\t\t\t\t\t\tisundef(funct, \"W117\", state.tokens.curr, v);\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\tnote_implied(state.tokens.curr);\\n\t\t\t} else {\\n\t\t\t\t// If the name is already defined in the current\\n\t\t\t\t// function, but not as outer, then there is a scope error.\\n\\n\t\t\t\tswitch (funct[v]) {\\n\t\t\t\tcase \"closure\":\\n\t\t\t\tcase \"function\":\\n\t\t\t\tcase \"var\":\\n\t\t\t\tcase \"unused\":\\n\t\t\t\t\twarning(\"W038\", state.tokens.curr, v);\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"label\":\\n\t\t\t\t\twarning(\"W037\", state.tokens.curr, v);\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"outer\":\\n\t\t\t\tcase \"global\":\\n\t\t\t\t\tbreak;\\n\t\t\t\tdefault:\\n\t\t\t\t\t// If the name is defined in an outer function, make an outer entry,\\n\t\t\t\t\t// and if it was unused, make it var.\\n\t\t\t\t\tif (s === true) {\\n\t\t\t\t\t\tfunct[v] = true;\\n\t\t\t\t\t} else if (s === null) {\\n\t\t\t\t\t\twarning(\"W039\", state.tokens.curr, v);\\n\t\t\t\t\t\tnote_implied(state.tokens.curr);\\n\t\t\t\t\t} else if (typeof s !== \"object\") {\\n\t\t\t\t\t\t// Operators typeof and delete do not raise runtime errors even\\n\t\t\t\t\t\t// if the base object of a reference is null so no need to\\n\t\t\t\t\t\t//\\n\t\t\t\t\t\t// display warning if we\\'re inside of typeof or delete.\\n\t\t\t\t\t\t// Attempting to subscript a null reference will throw an\\n\t\t\t\t\t\t// error, even within the typeof and delete operators\\n\t\t\t\t\t\tif (!(anonname === \"typeof\" || anonname === \"delete\") ||\\n\t\t\t\t\t\t\t(state.tokens.next &&\\n\t\t\t\t\t\t\t\t(state.tokens.next.value === \".\" || state.tokens.next.value === \"[\"))) {\\n\\n\t\t\t\t\t\t\tisundef(funct, \"W117\", state.tokens.curr, v);\\n\t\t\t\t\t\t}\\n\t\t\t\t\t\tfunct[v] = true;\\n\t\t\t\t\t\tnote_implied(state.tokens.curr);\\n\t\t\t\t\t} else {\\n\t\t\t\t\t\tswitch (s[v]) {\\n\t\t\t\t\t\tcase \"function\":\\n\t\t\t\t\t\tcase \"unction\":\\n\t\t\t\t\t\t\tthis[\"function\"] = true;\\n\t\t\t\t\t\t\ts[v] = \"closure\";\\n\t\t\t\t\t\t\tfunct[v] = s[\"(global)\"] ? \"global\" : \"outer\";\\n\t\t\t\t\t\t\tbreak;\\n\t\t\t\t\t\tcase \"var\":\\n\t\t\t\t\t\tcase \"unused\":\\n\t\t\t\t\t\t\ts[v] = \"closure\";\\n\t\t\t\t\t\t\tfunct[v] = s[\"(global)\"] ? \"global\" : \"outer\";\\n\t\t\t\t\t\t\tbreak;\\n\t\t\t\t\t\tcase \"closure\":\\n\t\t\t\t\t\t\tfunct[v] = s[\"(global)\"] ? \"global\" : \"outer\";\\n\t\t\t\t\t\t\tbreak;\\n\t\t\t\t\t\tcase \"label\":\\n\t\t\t\t\t\t\twarning(\"W037\", state.tokens.curr, v);\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\treturn this;\\n\t\t},\\n\t\tled: function () {\\n\t\t\terror(\"E033\", state.tokens.next, state.tokens.next.value);\\n\t\t}\\n\t};\\n\\n\ttype(\"(regexp)\", function () {\\n\t\treturn this;\\n\t});\\n\\n\t// ECMAScript parser\\n\\n\tdelim(\"(endline)\");\\n\tdelim(\"(begin)\");\\n\tdelim(\"(end)\").reach = true;\\n\tdelim(\"(error)\").reach = true;\\n\tdelim(\"}\").reach = true;\\n\tdelim(\")\");\\n\tdelim(\"]\");\\n\tdelim(\"\\\\\"\").reach = true;\\n\tdelim(\"\\'\").reach = true;\\n\tdelim(\";\");\\n\tdelim(\":\").reach = true;\\n\tdelim(\",\");\\n\tdelim(\"#\");\\n\\n\treserve(\"else\");\\n\treserve(\"case\").reach = true;\\n\treserve(\"catch\");\\n\treserve(\"default\").reach = true;\\n\treserve(\"finally\");\\n\treservevar(\"arguments\", function (x) {\\n\t\tif (state.directive[\"use strict\"] && funct[\"(global)\"]) {\\n\t\t\twarning(\"E008\", x);\\n\t\t}\\n\t});\\n\treservevar(\"eval\");\\n\treservevar(\"false\");\\n\treservevar(\"Infinity\");\\n\treservevar(\"null\");\\n\treservevar(\"this\", function (x) {\\n\t\tif (state.directive[\"use strict\"] && !state.option.validthis && ((funct[\"(statement)\"] &&\\n\t\t\t\tfunct[\"(name)\"].charAt(0) > \"Z\") || funct[\"(global)\"])) {\\n\t\t\twarning(\"W040\", x);\\n\t\t}\\n\t});\\n\treservevar(\"true\");\\n\treservevar(\"undefined\");\\n\\n\tassignop(\"=\", \"assign\", 20);\\n\tassignop(\"+=\", \"assignadd\", 20);\\n\tassignop(\"-=\", \"assignsub\", 20);\\n\tassignop(\"*=\", \"assignmult\", 20);\\n\tassignop(\"/=\", \"assigndiv\", 20).nud = function () {\\n\t\terror(\"E014\");\\n\t};\\n\tassignop(\"%=\", \"assignmod\", 20);\\n\\n\tbitwiseassignop(\"&=\", \"assignbitand\", 20);\\n\tbitwiseassignop(\"|=\", \"assignbitor\", 20);\\n\tbitwiseassignop(\"^=\", \"assignbitxor\", 20);\\n\tbitwiseassignop(\"<<=\", \"assignshiftleft\", 20);\\n\tbitwiseassignop(\">>=\", \"assignshiftright\", 20);\\n\tbitwiseassignop(\">>>=\", \"assignshiftrightunsigned\", 20);\\n\tinfix(\"?\", function (left, that) {\\n\t\tthat.left = left;\\n\t\tthat.right = expression(10);\\n\t\tadvance(\":\");\\n\t\tthat[\"else\"] = expression(10);\\n\t\treturn that;\\n\t}, 30);\\n\\n\tinfix(\"||\", \"or\", 40);\\n\tinfix(\"&&\", \"and\", 50);\\n\tbitwise(\"|\", \"bitor\", 70);\\n\tbitwise(\"^\", \"bitxor\", 80);\\n\tbitwise(\"&\", \"bitand\", 90);\\n\trelation(\"==\", function (left, right) {\\n\t\tvar eqnull = state.option.eqnull && (left.value === \"null\" || right.value === \"null\");\\n\\n\t\tif (!eqnull && state.option.eqeqeq)\\n\t\t\twarning(\"W116\", this, \"===\", \"==\");\\n\t\telse if (isPoorRelation(left))\\n\t\t\twarning(\"W041\", this, \"===\", left.value);\\n\t\telse if (isPoorRelation(right))\\n\t\t\twarning(\"W041\", this, \"===\", right.value);\\n\\n\t\treturn this;\\n\t});\\n\trelation(\"===\");\\n\trelation(\"!=\", function (left, right) {\\n\t\tvar eqnull = state.option.eqnull &&\\n\t\t\t\t(left.value === \"null\" || right.value === \"null\");\\n\\n\t\tif (!eqnull && state.option.eqeqeq) {\\n\t\t\twarning(\"W116\", this, \"!==\", \"!=\");\\n\t\t} else if (isPoorRelation(left)) {\\n\t\t\twarning(\"W041\", this, \"!==\", left.value);\\n\t\t} else if (isPoorRelation(right)) {\\n\t\t\twarning(\"W041\", this, \"!==\", right.value);\\n\t\t}\\n\t\treturn this;\\n\t});\\n\trelation(\"!==\");\\n\trelation(\"<\");\\n\trelation(\">\");\\n\trelation(\"<=\");\\n\trelation(\">=\");\\n\tbitwise(\"<<\", \"shiftleft\", 120);\\n\tbitwise(\">>\", \"shiftright\", 120);\\n\tbitwise(\">>>\", \"shiftrightunsigned\", 120);\\n\tinfix(\"in\", \"in\", 120);\\n\tinfix(\"instanceof\", \"instanceof\", 120);\\n\tinfix(\"+\", function (left, that) {\\n\t\tvar right = expression(130);\\n\t\tif (left && right && left.id === \"(string)\" && right.id === \"(string)\") {\\n\t\t\tleft.value += right.value;\\n\t\t\tleft.character = right.character;\\n\t\t\tif (!state.option.scripturl && reg.javascriptURL.test(left.value)) {\\n\t\t\t\twarning(\"W050\", left);\\n\t\t\t}\\n\t\t\treturn left;\\n\t\t}\\n\t\tthat.left = left;\\n\t\tthat.right = right;\\n\t\treturn that;\\n\t}, 130);\\n\tprefix(\"+\", \"num\");\\n\tprefix(\"+++\", function () {\\n\t\twarning(\"W007\");\\n\t\tthis.right = expression(150);\\n\t\tthis.arity = \"unary\";\\n\t\treturn this;\\n\t});\\n\tinfix(\"+++\", function (left) {\\n\t\twarning(\"W007\");\\n\t\tthis.left = left;\\n\t\tthis.right = expression(130);\\n\t\treturn this;\\n\t}, 130);\\n\tinfix(\"-\", \"sub\", 130);\\n\tprefix(\"-\", \"neg\");\\n\tprefix(\"---\", function () {\\n\t\twarning(\"W006\");\\n\t\tthis.right = expression(150);\\n\t\tthis.arity = \"unary\";\\n\t\treturn this;\\n\t});\\n\tinfix(\"---\", function (left) {\\n\t\twarning(\"W006\");\\n\t\tthis.left = left;\\n\t\tthis.right = expression(130);\\n\t\treturn this;\\n\t}, 130);\\n\tinfix(\"*\", \"mult\", 140);\\n\tinfix(\"/\", \"div\", 140);\\n\tinfix(\"%\", \"mod\", 140);\\n\\n\tsuffix(\"++\", \"postinc\");\\n\tprefix(\"++\", \"preinc\");\\n\tstate.syntax[\"++\"].exps = true;\\n\\n\tsuffix(\"--\", \"postdec\");\\n\tprefix(\"--\", \"predec\");\\n\tstate.syntax[\"--\"].exps = true;\\n\tprefix(\"delete\", function () {\\n\t\tvar p = expression(0);\\n\t\tif (!p || (p.id !== \".\" && p.id !== \"[\")) {\\n\t\t\twarning(\"W051\");\\n\t\t}\\n\t\tthis.first = p;\\n\t\treturn this;\\n\t}).exps = true;\\n\\n\tprefix(\"~\", function () {\\n\t\tif (state.option.bitwise) {\\n\t\t\twarning(\"W052\", this, \"~\");\\n\t\t}\\n\t\texpression(150);\\n\t\treturn this;\\n\t});\\n\\n\tprefix(\"!\", function () {\\n\t\tthis.right = expression(150);\\n\t\tthis.arity = \"unary\";\\n\\n\t\tif (!this.right) { // \\'!\\' followed by nothing? Give up.\\n\t\t\tquit(\"E041\", this.line || 0);\\n\t\t}\\n\\n\t\tif (bang[this.right.id] === true) {\\n\t\t\twarning(\"W018\", this, \"!\");\\n\t\t}\\n\t\treturn this;\\n\t});\\n\\n\tprefix(\"typeof\", \"typeof\");\\n\tprefix(\"new\", function () {\\n\t\tvar c = expression(155), i;\\n\t\tif (c && c.id !== \"function\") {\\n\t\t\tif (c.identifier) {\\n\t\t\t\tc[\"new\"] = true;\\n\t\t\t\tswitch (c.value) {\\n\t\t\t\tcase \"Number\":\\n\t\t\t\tcase \"String\":\\n\t\t\t\tcase \"Boolean\":\\n\t\t\t\tcase \"Math\":\\n\t\t\t\tcase \"JSON\":\\n\t\t\t\t\twarning(\"W053\", state.tokens.prev, c.value);\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"Function\":\\n\t\t\t\t\tif (!state.option.evil) {\\n\t\t\t\t\t\twarning(\"W054\");\\n\t\t\t\t\t}\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"Date\":\\n\t\t\t\tcase \"RegExp\":\\n\t\t\t\t\tbreak;\\n\t\t\t\tdefault:\\n\t\t\t\t\tif (c.id !== \"function\") {\\n\t\t\t\t\t\ti = c.value.substr(0, 1);\\n\t\t\t\t\t\tif (state.option.newcap && (i < \"A\" || i > \"Z\") && !_.has(global, c.value)) {\\n\t\t\t\t\t\t\twarning(\"W055\", state.tokens.curr);\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t} else {\\n\t\t\t\tif (c.id !== \".\" && c.id !== \"[\" && c.id !== \"(\") {\\n\t\t\t\t\twarning(\"W056\", state.tokens.curr);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t} else {\\n\t\t\tif (!state.option.supernew)\\n\t\t\t\twarning(\"W057\", this);\\n\t\t}\\n\t\tadjacent(state.tokens.curr, state.tokens.next);\\n\t\tif (state.tokens.next.id !== \"(\" && !state.option.supernew) {\\n\t\t\twarning(\"W058\", state.tokens.curr, state.tokens.curr.value);\\n\t\t}\\n\t\tthis.first = c;\\n\t\treturn this;\\n\t});\\n\tstate.syntax[\"new\"].exps = true;\\n\\n\tprefix(\"void\").exps = true;\\n\\n\tinfix(\".\", function (left, that) {\\n\t\tadjacent(state.tokens.prev, state.tokens.curr);\\n\t\tnobreak();\\n\t\tvar m = identifier(false, true);\\n\\n\t\tif (typeof m === \"string\") {\\n\t\t\tcountMember(m);\\n\t\t}\\n\\n\t\tthat.left = left;\\n\t\tthat.right = m;\\n\\n\t\tif (m && m === \"hasOwnProperty\" && state.tokens.next.value === \"=\") {\\n\t\t\twarning(\"W001\");\\n\t\t}\\n\\n\t\tif (left && left.value === \"arguments\" && (m === \"callee\" || m === \"caller\")) {\\n\t\t\tif (state.option.noarg)\\n\t\t\t\twarning(\"W059\", left, m);\\n\t\t\telse if (state.directive[\"use strict\"])\\n\t\t\t\terror(\"E008\");\\n\t\t} else if (!state.option.evil && left && left.value === \"document\" &&\\n\t\t\t\t(m === \"write\" || m === \"writeln\")) {\\n\t\t\twarning(\"W060\", left);\\n\t\t}\\n\\n\t\tif (!state.option.evil && (m === \"eval\" || m === \"execScript\")) {\\n\t\t\twarning(\"W061\");\\n\t\t}\\n\\n\t\treturn that;\\n\t}, 160, true);\\n\\n\tinfix(\"(\", function (left, that) {\\n\t\tif (state.tokens.prev.id !== \"}\" && state.tokens.prev.id !== \")\") {\\n\t\t\tnobreak(state.tokens.prev, state.tokens.curr);\\n\t\t}\\n\\n\t\tnospace();\\n\t\tif (state.option.immed && !left.immed && left.id === \"function\") {\\n\t\t\twarning(\"W062\");\\n\t\t}\\n\\n\t\tvar n = 0;\\n\t\tvar p = [];\\n\\n\t\tif (left) {\\n\t\t\tif (left.type === \"(identifier)\") {\\n\t\t\t\tif (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\\n\t\t\t\t\tif (\"Number String Boolean Date Object\".indexOf(left.value) === -1) {\\n\t\t\t\t\t\tif (left.value === \"Math\") {\\n\t\t\t\t\t\t\twarning(\"W063\", left);\\n\t\t\t\t\t\t} else if (state.option.newcap) {\\n\t\t\t\t\t\t\twarning(\"W064\", left);\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (state.tokens.next.id !== \")\") {\\n\t\t\tfor (;;) {\\n\t\t\t\tp[p.length] = expression(10);\\n\t\t\t\tn += 1;\\n\t\t\t\tif (state.tokens.next.id !== \",\") {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t\tcomma();\\n\t\t\t}\\n\t\t}\\n\\n\t\tadvance(\")\");\\n\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\\n\t\tif (typeof left === \"object\") {\\n\t\t\tif (left.value === \"parseInt\" && n === 1) {\\n\t\t\t\twarning(\"W065\", state.tokens.curr);\\n\t\t\t}\\n\t\t\tif (!state.option.evil) {\\n\t\t\t\tif (left.value === \"eval\" || left.value === \"Function\" ||\\n\t\t\t\t\t\tleft.value === \"execScript\") {\\n\t\t\t\t\twarning(\"W061\", left);\\n\\n\t\t\t\t\tif (p[0] && [0].id === \"(string)\") {\\n\t\t\t\t\t\taddInternalSrc(left, p[0].value);\\n\t\t\t\t\t}\\n\t\t\t\t} else if (p[0] && p[0].id === \"(string)\" &&\\n\t\t\t\t\t   (left.value === \"setTimeout\" ||\\n\t\t\t\t\t\tleft.value === \"setInterval\")) {\\n\t\t\t\t\twarning(\"W066\", left);\\n\t\t\t\t\taddInternalSrc(left, p[0].value);\\n\\n\t\t\t\t// window.setTimeout/setInterval\\n\t\t\t\t} else if (p[0] && p[0].id === \"(string)\" &&\\n\t\t\t\t\t   left.value === \".\" &&\\n\t\t\t\t\t   left.left.value === \"window\" &&\\n\t\t\t\t\t   (left.right === \"setTimeout\" ||\\n\t\t\t\t\t\tleft.right === \"setInterval\")) {\\n\t\t\t\t\twarning(\"W066\", left);\\n\t\t\t\t\taddInternalSrc(left, p[0].value);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\tif (!left.identifier && left.id !== \".\" && left.id !== \"[\" &&\\n\t\t\t\t\tleft.id !== \"(\" && left.id !== \"&&\" && left.id !== \"||\" &&\\n\t\t\t\t\tleft.id !== \"?\") {\\n\t\t\t\twarning(\"W067\", left);\\n\t\t\t}\\n\t\t}\\n\\n\t\tthat.left = left;\\n\t\treturn that;\\n\t}, 155, true).exps = true;\\n\\n\tprefix(\"(\", function () {\\n\t\tnospace();\\n\\n\t\tif (state.tokens.next.id === \"function\") {\\n\t\t\tstate.tokens.next.immed = true;\\n\t\t}\\n\\n\t\tvar exprs = [];\\n\\n\t\tif (state.tokens.next.id !== \")\") {\\n\t\t\tfor (;;) {\\n\t\t\t\texprs.push(expression(0));\\n\t\t\t\tif (state.tokens.next.id !== \",\") {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t\tcomma();\\n\t\t\t}\\n\t\t}\\n\\n\t\tadvance(\")\", this);\\n\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\tif (state.option.immed && exprs[0].id === \"function\") {\\n\t\t\tif (state.tokens.next.id !== \"(\" &&\\n\t\t\t  (state.tokens.next.id !== \".\" || (peek().value !== \"call\" && peek().value !== \"apply\"))) {\\n\t\t\t\twarning(\"W068\", this);\\n\t\t\t}\\n\t\t}\\n\\n\t\treturn exprs[0];\\n\t});\\n\\n\tinfix(\"[\", function (left, that) {\\n\t\tnobreak(state.tokens.prev, state.tokens.curr);\\n\t\tnospace();\\n\t\tvar e = expression(0), s;\\n\t\tif (e && e.type === \"(string)\") {\\n\t\t\tif (!state.option.evil && (e.value === \"eval\" || e.value === \"execScript\")) {\\n\t\t\t\twarning(\"W061\", that);\\n\t\t\t}\\n\\n\t\t\tcountMember(e.value);\\n\t\t\tif (!state.option.sub && reg.identifier.test(e.value)) {\\n\t\t\t\ts = state.syntax[e.value];\\n\t\t\t\tif (!s || !isReserved(s)) {\\n\t\t\t\t\twarning(\"W069\", state.tokens.prev, e.value);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\t\tadvance(\"]\", that);\\n\\n\t\tif (e && e.value === \"hasOwnProperty\" && state.tokens.next.value === \"=\") {\\n\t\t\twarning(\"W001\");\\n\t\t}\\n\\n\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\tthat.left = left;\\n\t\tthat.right = e;\\n\t\treturn that;\\n\t}, 160, true);\\n\\n\tprefix(\"[\", function () {\\n\t\tvar b = state.tokens.curr.line !== state.tokens.next.line;\\n\t\tthis.first = [];\\n\t\tif (b) {\\n\t\t\tindent += state.option.indent;\\n\t\t\tif (state.tokens.next.from === indent + state.option.indent) {\\n\t\t\t\tindent += state.option.indent;\\n\t\t\t}\\n\t\t}\\n\t\twhile (state.tokens.next.id !== \"(end)\") {\\n\t\t\twhile (state.tokens.next.id === \",\") {\\n\t\t\t\tif (!state.option.es5)\\n\t\t\t\t\twarning(\"W070\");\\n\t\t\t\tadvance(\",\");\\n\t\t\t}\\n\t\t\tif (state.tokens.next.id === \"]\") {\\n\t\t\t\tbreak;\\n\t\t\t}\\n\t\t\tif (b && state.tokens.curr.line !== state.tokens.next.line) {\\n\t\t\t\tindentation();\\n\t\t\t}\\n\t\t\tthis.first.push(expression(10));\\n\t\t\tif (state.tokens.next.id === \",\") {\\n\t\t\t\tcomma({ allowTrailing: true });\\n\t\t\t\tif (state.tokens.next.id === \"]\" && !state.option.es5) {\\n\t\t\t\t\twarning(\"W070\", state.tokens.curr);\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t} else {\\n\t\t\t\tbreak;\\n\t\t\t}\\n\t\t}\\n\t\tif (b) {\\n\t\t\tindent -= state.option.indent;\\n\t\t\tindentation();\\n\t\t}\\n\t\tadvance(\"]\", this);\\n\t\treturn this;\\n\t}, 160);\\n\\n\\n\tfunction property_name() {\\n\t\tvar id = optionalidentifier(false, true);\\n\\n\t\tif (!id) {\\n\t\t\tif (state.tokens.next.id === \"(string)\") {\\n\t\t\t\tid = state.tokens.next.value;\\n\t\t\t\tadvance();\\n\t\t\t} else if (state.tokens.next.id === \"(number)\") {\\n\t\t\t\tid = state.tokens.next.value.toString();\\n\t\t\t\tadvance();\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (id === \"hasOwnProperty\") {\\n\t\t\twarning(\"W001\");\\n\t\t}\\n\\n\t\treturn id;\\n\t}\\n\\n\\n\tfunction functionparams() {\\n\t\tvar next   = state.tokens.next;\\n\t\tvar params = [];\\n\t\tvar ident;\\n\\n\t\tadvance(\"(\");\\n\t\tnospace();\\n\\n\t\tif (state.tokens.next.id === \")\") {\\n\t\t\tadvance(\")\");\\n\t\t\treturn;\\n\t\t}\\n\\n\t\tfor (;;) {\\n\t\t\tident = identifier(true);\\n\t\t\tparams.push(ident);\\n\t\t\taddlabel(ident, \"unused\", state.tokens.curr);\\n\t\t\tif (state.tokens.next.id === \",\") {\\n\t\t\t\tcomma();\\n\t\t\t} else {\\n\t\t\t\tadvance(\")\", next);\\n\t\t\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\t\t\treturn params;\\n\t\t\t}\\n\t\t}\\n\t}\\n\\n\\n\tfunction doFunction(name, statement) {\\n\t\tvar f;\\n\t\tvar oldOption = state.option;\\n\t\tvar oldScope  = scope;\\n\\n\t\tstate.option = Object.create(state.option);\\n\t\tscope  = Object.create(scope);\\n\\n\t\tfunct = {\\n\t\t\t\"(name)\"     : name || \"\\\\\"\" + anonname + \"\\\\\"\",\\n\t\t\t\"(line)\"     : state.tokens.next.line,\\n\t\t\t\"(character)\": state.tokens.next.character,\\n\t\t\t\"(context)\"  : funct,\\n\t\t\t\"(breakage)\" : 0,\\n\t\t\t\"(loopage)\"  : 0,\\n\t\t\t\"(metrics)\"  : createMetrics(state.tokens.next),\\n\t\t\t\"(scope)\"    : scope,\\n\t\t\t\"(statement)\": statement,\\n\t\t\t\"(tokens)\"   : {}\\n\t\t};\\n\\n\t\tf = funct;\\n\t\tstate.tokens.curr.funct = funct;\\n\\n\t\tfunctions.push(funct);\\n\\n\t\tif (name) {\\n\t\t\taddlabel(name, \"function\");\\n\t\t}\\n\\n\t\tfunct[\"(params)\"] = functionparams();\\n\t\tfunct[\"(metrics)\"].verifyMaxParametersPerFunction(funct[\"(params)\"]);\\n\\n\t\tblock(false, false, true);\\n\\n\t\tfunct[\"(metrics)\"].verifyMaxStatementsPerFunction();\\n\t\tfunct[\"(metrics)\"].verifyMaxComplexityPerFunction();\\n\t\tfunct[\"(unusedOption)\"] = state.option.unused;\\n\\n\t\tscope = oldScope;\\n\t\tstate.option = oldOption;\\n\t\tfunct[\"(last)\"] = state.tokens.curr.line;\\n\t\tfunct[\"(lastcharacter)\"] = state.tokens.curr.character;\\n\t\tfunct = funct[\"(context)\"];\\n\\n\t\treturn f;\\n\t}\\n\\n\tfunction createMetrics(functionStartToken) {\\n\t\treturn {\\n\t\t\tstatementCount: 0,\\n\t\t\tnestedBlockDepth: -1,\\n\t\t\tComplexityCount: 1,\\n\t\t\tverifyMaxStatementsPerFunction: function () {\\n\t\t\t\tif (state.option.maxstatements &&\\n\t\t\t\t\tthis.statementCount > state.option.maxstatements) {\\n\t\t\t\t\twarning(\"W071\", functionStartToken, this.statementCount);\\n\t\t\t\t}\\n\t\t\t},\\n\\n\t\t\tverifyMaxParametersPerFunction: function (params) {\\n\t\t\t\tparams = params || [];\\n\\n\t\t\t\tif (state.option.maxparams && params.length > state.option.maxparams) {\\n\t\t\t\t\twarning(\"W072\", functionStartToken, params.length);\\n\t\t\t\t}\\n\t\t\t},\\n\\n\t\t\tverifyMaxNestedBlockDepthPerFunction: function () {\\n\t\t\t\tif (state.option.maxdepth &&\\n\t\t\t\t\tthis.nestedBlockDepth > 0 &&\\n\t\t\t\t\tthis.nestedBlockDepth === state.option.maxdepth + 1) {\\n\t\t\t\t\twarning(\"W073\", null, this.nestedBlockDepth);\\n\t\t\t\t}\\n\t\t\t},\\n\\n\t\t\tverifyMaxComplexityPerFunction: function () {\\n\t\t\t\tvar max = state.option.maxcomplexity;\\n\t\t\t\tvar cc = this.ComplexityCount;\\n\t\t\t\tif (max && cc > max) {\\n\t\t\t\t\twarning(\"W074\", functionStartToken, cc);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t};\\n\t}\\n\\n\tfunction increaseComplexityCount() {\\n\t\tfunct[\"(metrics)\"].ComplexityCount += 1;\\n\t}\\n\\n\t// Parse assignments that were found instead of conditionals.\\n\t// For example: if (a = 1) { ... }\\n\\n\tfunction parseCondAssignment() {\\n\t\tswitch (state.tokens.next.id) {\\n\t\tcase \"=\":\\n\t\tcase \"+=\":\\n\t\tcase \"-=\":\\n\t\tcase \"*=\":\\n\t\tcase \"%=\":\\n\t\tcase \"&=\":\\n\t\tcase \"|=\":\\n\t\tcase \"^=\":\\n\t\tcase \"/=\":\\n\t\t\tif (!state.option.boss) {\\n\t\t\t\twarning(\"W084\");\\n\t\t\t}\\n\\n\t\t\tadvance(state.tokens.next.id);\\n\t\t\texpression(20);\\n\t\t}\\n\t}\\n\\n\\n\t(function (x) {\\n\t\tx.nud = function () {\\n\t\t\tvar b, f, i, p, t;\\n\t\t\tvar props = {}; // All properties, including accessors\\n\\n\t\t\tfunction saveProperty(name, tkn) {\\n\t\t\t\tif (props[name] && _.has(props, name))\\n\t\t\t\t\twarning(\"W075\", state.tokens.next, i);\\n\t\t\t\telse\\n\t\t\t\t\tprops[name] = {};\\n\\n\t\t\t\tprops[name].basic = true;\\n\t\t\t\tprops[name].basictkn = tkn;\\n\t\t\t}\\n\\n\t\t\tfunction saveSetter(name, tkn) {\\n\t\t\t\tif (props[name] && _.has(props, name)) {\\n\t\t\t\t\tif (props[name].basic || props[name].setter)\\n\t\t\t\t\t\twarning(\"W075\", state.tokens.next, i);\\n\t\t\t\t} else {\\n\t\t\t\t\tprops[name] = {};\\n\t\t\t\t}\\n\\n\t\t\t\tprops[name].setter = true;\\n\t\t\t\tprops[name].setterToken = tkn;\\n\t\t\t}\\n\\n\t\t\tfunction saveGetter(name) {\\n\t\t\t\tif (props[name] && _.has(props, name)) {\\n\t\t\t\t\tif (props[name].basic || props[name].getter)\\n\t\t\t\t\t\twarning(\"W075\", state.tokens.next, i);\\n\t\t\t\t} else {\\n\t\t\t\t\tprops[name] = {};\\n\t\t\t\t}\\n\\n\t\t\t\tprops[name].getter = true;\\n\t\t\t\tprops[name].getterToken = state.tokens.curr;\\n\t\t\t}\\n\\n\t\t\tb = state.tokens.curr.line !== state.tokens.next.line;\\n\t\t\tif (b) {\\n\t\t\t\tindent += state.option.indent;\\n\t\t\t\tif (state.tokens.next.from === indent + state.option.indent) {\\n\t\t\t\t\tindent += state.option.indent;\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tfor (;;) {\\n\t\t\t\tif (state.tokens.next.id === \"}\") {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\\n\t\t\t\tif (b) {\\n\t\t\t\t\tindentation();\\n\t\t\t\t}\\n\\n\t\t\t\tif (state.tokens.next.value === \"get\" && peek().id !== \":\") {\\n\t\t\t\t\tadvance(\"get\");\\n\\n\t\t\t\t\tif (!state.option.es5) {\\n\t\t\t\t\t\terror(\"E034\");\\n\t\t\t\t\t}\\n\\n\t\t\t\t\ti = property_name();\\n\t\t\t\t\tif (!i) {\\n\t\t\t\t\t\terror(\"E035\");\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tsaveGetter(i);\\n\t\t\t\t\tt = state.tokens.next;\\n\t\t\t\t\tadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\t\tf = doFunction();\\n\t\t\t\t\tp = f[\"(params)\"];\\n\\n\t\t\t\t\tif (p) {\\n\t\t\t\t\t\twarning(\"W076\", t, p[0], i);\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\t} else if (state.tokens.next.value === \"set\" && peek().id !== \":\") {\\n\t\t\t\t\tadvance(\"set\");\\n\\n\t\t\t\t\tif (!state.option.es5) {\\n\t\t\t\t\t\terror(\"E034\");\\n\t\t\t\t\t}\\n\\n\t\t\t\t\ti = property_name();\\n\t\t\t\t\tif (!i) {\\n\t\t\t\t\t\terror(\"E035\");\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tsaveSetter(i, state.tokens.next);\\n\t\t\t\t\tt = state.tokens.next;\\n\t\t\t\t\tadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\t\tf = doFunction();\\n\t\t\t\t\tp = f[\"(params)\"];\\n\\n\t\t\t\t\tif (!p || p.length !== 1) {\\n\t\t\t\t\t\twarning(\"W077\", t, i);\\n\t\t\t\t\t}\\n\t\t\t\t} else {\\n\t\t\t\t\ti = property_name();\\n\t\t\t\t\tsaveProperty(i, state.tokens.next);\\n\\n\t\t\t\t\tif (typeof i !== \"string\") {\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tadvance(\":\");\\n\t\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\t\texpression(10);\\n\t\t\t\t}\\n\\n\t\t\t\tcountMember(i);\\n\t\t\t\tif (state.tokens.next.id === \",\") {\\n\t\t\t\t\tcomma({ allowTrailing: true });\\n\t\t\t\t\tif (state.tokens.next.id === \",\") {\\n\t\t\t\t\t\twarning(\"W070\", state.tokens.curr);\\n\t\t\t\t\t} else if (state.tokens.next.id === \"}\" && !state.option.es5) {\\n\t\t\t\t\t\twarning(\"W070\", state.tokens.curr);\\n\t\t\t\t\t}\\n\t\t\t\t} else {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\tif (b) {\\n\t\t\t\tindent -= state.option.indent;\\n\t\t\t\tindentation();\\n\t\t\t}\\n\t\t\tadvance(\"}\", this);\\n\\n\t\t\t// Check for lonely setters if in the ES5 mode.\\n\t\t\tif (state.option.es5) {\\n\t\t\t\tfor (var name in props) {\\n\t\t\t\t\tif (_.has(props, name) && props[name].setter && !props[name].getter) {\\n\t\t\t\t\t\twarning(\"W078\", props[name].setterToken);\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\treturn this;\\n\t\t};\\n\t\tx.fud = function () {\\n\t\t\terror(\"E036\", state.tokens.curr);\\n\t\t};\\n\t}(delim(\"{\")));\\n\\n\t// This Function is called when esnext option is set to true\\n\t// it adds the `const` statement to JSHINT\\n\\n\tuseESNextSyntax = function () {\\n\t\tvar conststatement = stmt(\"const\", function (prefix) {\\n\t\t\tvar id, name, value;\\n\\n\t\t\tthis.first = [];\\n\t\t\tfor (;;) {\\n\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\tid = identifier();\\n\t\t\t\tif (funct[id] === \"const\") {\\n\t\t\t\t\twarning(\"E011\", null, id);\\n\t\t\t\t}\\n\t\t\t\tif (funct[\"(global)\"] && predefined[id] === false) {\\n\t\t\t\t\twarning(\"W079\", state.tokens.curr, id);\\n\t\t\t\t}\\n\t\t\t\taddlabel(id, \"const\");\\n\t\t\t\tif (prefix) {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t\tname = state.tokens.curr;\\n\t\t\t\tthis.first.push(state.tokens.curr);\\n\\n\t\t\t\tif (state.tokens.next.id !== \"=\") {\\n\t\t\t\t\twarning(\"E012\", state.tokens.curr, id);\\n\t\t\t\t}\\n\\n\t\t\t\tif (state.tokens.next.id === \"=\") {\\n\t\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\t\tadvance(\"=\");\\n\t\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\t\tif (state.tokens.next.id === \"undefined\") {\\n\t\t\t\t\t\twarning(\"W080\", state.tokens.curr, id);\\n\t\t\t\t\t}\\n\t\t\t\t\tif (peek(0).id === \"=\" && state.tokens.next.identifier) {\\n\t\t\t\t\t\terror(\"E037\", state.tokens.next, state.tokens.next.value);\\n\t\t\t\t\t}\\n\t\t\t\t\tvalue = expression(0);\\n\t\t\t\t\tname.first = value;\\n\t\t\t\t}\\n\\n\t\t\t\tif (state.tokens.next.id !== \",\") {\\n\t\t\t\t\tbreak;\\n\t\t\t\t}\\n\t\t\t\tcomma();\\n\t\t\t}\\n\t\t\treturn this;\\n\t\t});\\n\t\tconststatement.exps = true;\\n\t};\\n\\n\tvar varstatement = stmt(\"var\", function (prefix) {\\n\t\t// JavaScript does not have block scope. It only has function scope. So,\\n\t\t// declaring a variable in a block can have unexpected consequences.\\n\t\tvar id, name, value;\\n\\n\t\tif (funct[\"(onevar)\"] && state.option.onevar) {\\n\t\t\twarning(\"W081\");\\n\t\t} else if (!funct[\"(global)\"]) {\\n\t\t\tfunct[\"(onevar)\"] = true;\\n\t\t}\\n\\n\t\tthis.first = [];\\n\\n\t\tfor (;;) {\\n\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\tid = identifier();\\n\\n\t\t\tif (state.option.esnext && funct[id] === \"const\") {\\n\t\t\t\twarning(\"E011\", null, id);\\n\t\t\t}\\n\\n\t\t\tif (funct[\"(global)\"] && predefined[id] === false) {\\n\t\t\t\twarning(\"W079\", state.tokens.curr, id);\\n\t\t\t}\\n\\n\t\t\taddlabel(id, \"unused\", state.tokens.curr);\\n\\n\t\t\tif (prefix) {\\n\t\t\t\tbreak;\\n\t\t\t}\\n\\n\t\t\tname = state.tokens.curr;\\n\t\t\tthis.first.push(state.tokens.curr);\\n\\n\t\t\tif (state.tokens.next.id === \"=\") {\\n\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\tadvance(\"=\");\\n\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\tif (state.tokens.next.id === \"undefined\") {\\n\t\t\t\t\twarning(\"W080\", state.tokens.curr, id);\\n\t\t\t\t}\\n\t\t\t\tif (peek(0).id === \"=\" && state.tokens.next.identifier) {\\n\t\t\t\t\terror(\"E038\", state.tokens.next, state.tokens.next.value);\\n\t\t\t\t}\\n\t\t\t\tvalue = expression(0);\\n\t\t\t\tname.first = value;\\n\t\t\t}\\n\t\t\tif (state.tokens.next.id !== \",\") {\\n\t\t\t\tbreak;\\n\t\t\t}\\n\t\t\tcomma();\\n\t\t}\\n\t\treturn this;\\n\t});\\n\tvarstatement.exps = true;\\n\\n\tblockstmt(\"function\", function () {\\n\t\tif (inblock) {\\n\t\t\twarning(\"W082\", state.tokens.curr);\\n\\n\t\t}\\n\t\tvar i = identifier();\\n\t\tif (state.option.esnext && funct[i] === \"const\") {\\n\t\t\twarning(\"E011\", null, i);\\n\t\t}\\n\t\tadjacent(state.tokens.curr, state.tokens.next);\\n\t\taddlabel(i, \"unction\", state.tokens.curr);\\n\\n\t\tdoFunction(i, { statement: true });\\n\t\tif (state.tokens.next.id === \"(\" && state.tokens.next.line === state.tokens.curr.line) {\\n\t\t\terror(\"E039\");\\n\t\t}\\n\t\treturn this;\\n\t});\\n\\n\tprefix(\"function\", function () {\\n\t\tvar i = optionalidentifier();\\n\t\tif (i || state.option.gcl) {\\n\t\t\tadjacent(state.tokens.curr, state.tokens.next);\\n\t\t} else {\\n\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t}\\n\t\tdoFunction(i);\\n\t\tif (!state.option.loopfunc && funct[\"(loopage)\"]) {\\n\t\t\twarning(\"W083\");\\n\t\t}\\n\t\treturn this;\\n\t});\\n\\n\tblockstmt(\"if\", function () {\\n\t\tvar t = state.tokens.next;\\n\t\tincreaseComplexityCount();\\n\t\tadvance(\"(\");\\n\t\tnonadjacent(this, t);\\n\t\tnospace();\\n\t\texpression(20);\\n\t\tparseCondAssignment();\\n\t\tadvance(\")\", t);\\n\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\tblock(true, true);\\n\t\tif (state.tokens.next.id === \"else\") {\\n\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\tadvance(\"else\");\\n\t\t\tif (state.tokens.next.id === \"if\" || state.tokens.next.id === \"switch\") {\\n\t\t\t\tstatement(true);\\n\t\t\t} else {\\n\t\t\t\tblock(true, true);\\n\t\t\t}\\n\t\t}\\n\t\treturn this;\\n\t});\\n\\n\tblockstmt(\"try\", function () {\\n\t\tvar b;\\n\\n\t\tfunction doCatch() {\\n\t\t\tvar oldScope = scope;\\n\t\t\tvar e;\\n\\n\t\t\tadvance(\"catch\");\\n\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\tadvance(\"(\");\\n\\n\t\t\tscope = Object.create(oldScope);\\n\\n\t\t\te = state.tokens.next.value;\\n\t\t\tif (state.tokens.next.type !== \"(identifier)\") {\\n\t\t\t\te = null;\\n\t\t\t\twarning(\"E030\", state.tokens.next, e);\\n\t\t\t}\\n\\n\t\t\tadvance();\\n\t\t\tadvance(\")\");\\n\\n\t\t\tfunct = {\\n\t\t\t\t\"(name)\"     : \"(catch)\",\\n\t\t\t\t\"(line)\"     : state.tokens.next.line,\\n\t\t\t\t\"(character)\": state.tokens.next.character,\\n\t\t\t\t\"(context)\"  : funct,\\n\t\t\t\t\"(breakage)\" : funct[\"(breakage)\"],\\n\t\t\t\t\"(loopage)\"  : funct[\"(loopage)\"],\\n\t\t\t\t\"(scope)\"    : scope,\\n\t\t\t\t\"(statement)\": false,\\n\t\t\t\t\"(metrics)\"  : createMetrics(state.tokens.next),\\n\t\t\t\t\"(catch)\"    : true,\\n\t\t\t\t\"(tokens)\"   : {}\\n\t\t\t};\\n\\n\t\t\tif (e) {\\n\t\t\t\taddlabel(e, \"exception\");\\n\t\t\t}\\n\\n\t\t\tstate.tokens.curr.funct = funct;\\n\t\t\tfunctions.push(funct);\\n\\n\t\t\tblock(false);\\n\\n\t\t\tscope = oldScope;\\n\\n\t\t\tfunct[\"(last)\"] = state.tokens.curr.line;\\n\t\t\tfunct[\"(lastcharacter)\"] = state.tokens.curr.character;\\n\t\t\tfunct = funct[\"(context)\"];\\n\t\t}\\n\\n\t\tblock(false);\\n\\n\t\tif (state.tokens.next.id === \"catch\") {\\n\t\t\tincreaseComplexityCount();\\n\t\t\tdoCatch();\\n\t\t\tb = true;\\n\t\t}\\n\\n\t\tif (state.tokens.next.id === \"finally\") {\\n\t\t\tadvance(\"finally\");\\n\t\t\tblock(false);\\n\t\t\treturn;\\n\t\t} else if (!b) {\\n\t\t\terror(\"E021\", state.tokens.next, \"catch\", state.tokens.next.value);\\n\t\t}\\n\\n\t\treturn this;\\n\t});\\n\\n\tblockstmt(\"while\", function () {\\n\t\tvar t = state.tokens.next;\\n\t\tfunct[\"(breakage)\"] += 1;\\n\t\tfunct[\"(loopage)\"] += 1;\\n\t\tincreaseComplexityCount();\\n\t\tadvance(\"(\");\\n\t\tnonadjacent(this, t);\\n\t\tnospace();\\n\t\texpression(20);\\n\t\tparseCondAssignment();\\n\t\tadvance(\")\", t);\\n\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\tblock(true, true);\\n\t\tfunct[\"(breakage)\"] -= 1;\\n\t\tfunct[\"(loopage)\"] -= 1;\\n\t\treturn this;\\n\t}).labelled = true;\\n\\n\tblockstmt(\"with\", function () {\\n\t\tvar t = state.tokens.next;\\n\t\tif (state.directive[\"use strict\"]) {\\n\t\t\terror(\"E010\", state.tokens.curr);\\n\t\t} else if (!state.option.withstmt) {\\n\t\t\twarning(\"W085\", state.tokens.curr);\\n\t\t}\\n\\n\t\tadvance(\"(\");\\n\t\tnonadjacent(this, t);\\n\t\tnospace();\\n\t\texpression(0);\\n\t\tadvance(\")\", t);\\n\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\tblock(true, true);\\n\\n\t\treturn this;\\n\t});\\n\\n\tblockstmt(\"switch\", function () {\\n\t\tvar t = state.tokens.next,\\n\t\t\tg = false;\\n\t\tfunct[\"(breakage)\"] += 1;\\n\t\tadvance(\"(\");\\n\t\tnonadjacent(this, t);\\n\t\tnospace();\\n\t\tthis.condition = expression(20);\\n\t\tadvance(\")\", t);\\n\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\tt = state.tokens.next;\\n\t\tadvance(\"{\");\\n\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\tindent += state.option.indent;\\n\t\tthis.cases = [];\\n\\n\t\tfor (;;) {\\n\t\t\tswitch (state.tokens.next.id) {\\n\t\t\tcase \"case\":\\n\t\t\t\tswitch (funct[\"(verb)\"]) {\\n\t\t\t\tcase \"break\":\\n\t\t\t\tcase \"case\":\\n\t\t\t\tcase \"continue\":\\n\t\t\t\tcase \"return\":\\n\t\t\t\tcase \"switch\":\\n\t\t\t\tcase \"throw\":\\n\t\t\t\t\tbreak;\\n\t\t\t\tdefault:\\n\t\t\t\t\t// You can tell JSHint that you don\\'t use break intentionally by\\n\t\t\t\t\t// adding a comment /* falls through */ on a line just before\\n\t\t\t\t\t// the next `case`.\\n\t\t\t\t\tif (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {\\n\t\t\t\t\t\twarning(\"W086\", state.tokens.curr, \"case\");\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t\tindentation(-state.option.indent);\\n\t\t\t\tadvance(\"case\");\\n\t\t\t\tthis.cases.push(expression(20));\\n\t\t\t\tincreaseComplexityCount();\\n\t\t\t\tg = true;\\n\t\t\t\tadvance(\":\");\\n\t\t\t\tfunct[\"(verb)\"] = \"case\";\\n\t\t\t\tbreak;\\n\t\t\tcase \"default\":\\n\t\t\t\tswitch (funct[\"(verb)\"]) {\\n\t\t\t\tcase \"break\":\\n\t\t\t\tcase \"continue\":\\n\t\t\t\tcase \"return\":\\n\t\t\t\tcase \"throw\":\\n\t\t\t\t\tbreak;\\n\t\t\t\tdefault:\\n\t\t\t\t\t// Do not display a warning if \\'default\\' is the first statement or if\\n\t\t\t\t\t// there is a special /* falls through */ comment.\\n\t\t\t\t\tif (this.cases.length) {\\n\t\t\t\t\t\tif (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {\\n\t\t\t\t\t\t\twarning(\"W086\", state.tokens.curr, \"default\");\\n\t\t\t\t\t\t}\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t\tindentation(-state.option.indent);\\n\t\t\t\tadvance(\"default\");\\n\t\t\t\tg = true;\\n\t\t\t\tadvance(\":\");\\n\t\t\t\tbreak;\\n\t\t\tcase \"}\":\\n\t\t\t\tindent -= state.option.indent;\\n\t\t\t\tindentation();\\n\t\t\t\tadvance(\"}\", t);\\n\t\t\t\tfunct[\"(breakage)\"] -= 1;\\n\t\t\t\tfunct[\"(verb)\"] = undefined;\\n\t\t\t\treturn;\\n\t\t\tcase \"(end)\":\\n\t\t\t\terror(\"E023\", state.tokens.next, \"}\");\\n\t\t\t\treturn;\\n\t\t\tdefault:\\n\t\t\t\tif (g) {\\n\t\t\t\t\tswitch (state.tokens.curr.id) {\\n\t\t\t\t\tcase \",\":\\n\t\t\t\t\t\terror(\"E040\");\\n\t\t\t\t\t\treturn;\\n\t\t\t\t\tcase \":\":\\n\t\t\t\t\t\tg = false;\\n\t\t\t\t\t\tstatements();\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\tdefault:\\n\t\t\t\t\t\terror(\"E025\", state.tokens.curr);\\n\t\t\t\t\t\treturn;\\n\t\t\t\t\t}\\n\t\t\t\t} else {\\n\t\t\t\t\tif (state.tokens.curr.id === \":\") {\\n\t\t\t\t\t\tadvance(\":\");\\n\t\t\t\t\t\terror(\"E024\", state.tokens.curr, \":\");\\n\t\t\t\t\t\tstatements();\\n\t\t\t\t\t} else {\\n\t\t\t\t\t\terror(\"E021\", state.tokens.next, \"case\", state.tokens.next.value);\\n\t\t\t\t\t\treturn;\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\t}).labelled = true;\\n\\n\tstmt(\"debugger\", function () {\\n\t\tif (!state.option.debug) {\\n\t\t\twarning(\"W087\");\\n\t\t}\\n\t\treturn this;\\n\t}).exps = true;\\n\\n\t(function () {\\n\t\tvar x = stmt(\"do\", function () {\\n\t\t\tfunct[\"(breakage)\"] += 1;\\n\t\t\tfunct[\"(loopage)\"] += 1;\\n\t\t\tincreaseComplexityCount();\\n\\n\t\t\tthis.first = block(true);\\n\t\t\tadvance(\"while\");\\n\t\t\tvar t = state.tokens.next;\\n\t\t\tnonadjacent(state.tokens.curr, t);\\n\t\t\tadvance(\"(\");\\n\t\t\tnospace();\\n\t\t\texpression(20);\\n\t\t\tparseCondAssignment();\\n\t\t\tadvance(\")\", t);\\n\t\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\t\tfunct[\"(breakage)\"] -= 1;\\n\t\t\tfunct[\"(loopage)\"] -= 1;\\n\t\t\treturn this;\\n\t\t});\\n\t\tx.labelled = true;\\n\t\tx.exps = true;\\n\t}());\\n\\n\tblockstmt(\"for\", function () {\\n\t\tvar s, t = state.tokens.next;\\n\t\tfunct[\"(breakage)\"] += 1;\\n\t\tfunct[\"(loopage)\"] += 1;\\n\t\tincreaseComplexityCount();\\n\t\tadvance(\"(\");\\n\t\tnonadjacent(this, t);\\n\t\tnospace();\\n\t\tif (peek(state.tokens.next.id === \"var\" ? 1 : 0).id === \"in\") {\\n\t\t\tif (state.tokens.next.id === \"var\") {\\n\t\t\t\tadvance(\"var\");\\n\t\t\t\tvarstatement.fud.call(varstatement, true);\\n\t\t\t} else {\\n\t\t\t\tswitch (funct[state.tokens.next.value]) {\\n\t\t\t\tcase \"unused\":\\n\t\t\t\t\tfunct[state.tokens.next.value] = \"var\";\\n\t\t\t\t\tbreak;\\n\t\t\t\tcase \"var\":\\n\t\t\t\t\tbreak;\\n\t\t\t\tdefault:\\n\t\t\t\t\twarning(\"W088\", state.tokens.next, state.tokens.next.value);\\n\t\t\t\t}\\n\t\t\t\tadvance();\\n\t\t\t}\\n\t\t\tadvance(\"in\");\\n\t\t\texpression(20);\\n\t\t\tadvance(\")\", t);\\n\t\t\ts = block(true, true);\\n\t\t\tif (state.option.forin && s && (s.length > 1 || typeof s[0] !== \"object\" ||\\n\t\t\t\t\ts[0].value !== \"if\")) {\\n\t\t\t\twarning(\"W089\", this);\\n\t\t\t}\\n\t\t\tfunct[\"(breakage)\"] -= 1;\\n\t\t\tfunct[\"(loopage)\"] -= 1;\\n\t\t\treturn this;\\n\t\t} else {\\n\t\t\tif (state.tokens.next.id !== \";\") {\\n\t\t\t\tif (state.tokens.next.id === \"var\") {\\n\t\t\t\t\tadvance(\"var\");\\n\t\t\t\t\tvarstatement.fud.call(varstatement);\\n\t\t\t\t} else {\\n\t\t\t\t\tfor (;;) {\\n\t\t\t\t\t\texpression(0, \"for\");\\n\t\t\t\t\t\tif (state.tokens.next.id !== \",\") {\\n\t\t\t\t\t\t\tbreak;\\n\t\t\t\t\t\t}\\n\t\t\t\t\t\tcomma();\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\tnolinebreak(state.tokens.curr);\\n\t\t\tadvance(\";\");\\n\t\t\tif (state.tokens.next.id !== \";\") {\\n\t\t\t\texpression(20);\\n\t\t\t\tparseCondAssignment();\\n\t\t\t}\\n\t\t\tnolinebreak(state.tokens.curr);\\n\t\t\tadvance(\";\");\\n\t\t\tif (state.tokens.next.id === \";\") {\\n\t\t\t\terror(\"E021\", state.tokens.next, \")\", \";\");\\n\t\t\t}\\n\t\t\tif (state.tokens.next.id !== \")\") {\\n\t\t\t\tfor (;;) {\\n\t\t\t\t\texpression(0, \"for\");\\n\t\t\t\t\tif (state.tokens.next.id !== \",\") {\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t}\\n\t\t\t\t\tcomma();\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\tadvance(\")\", t);\\n\t\t\tnospace(state.tokens.prev, state.tokens.curr);\\n\t\t\tblock(true, true);\\n\t\t\tfunct[\"(breakage)\"] -= 1;\\n\t\t\tfunct[\"(loopage)\"] -= 1;\\n\t\t\treturn this;\\n\t\t}\\n\t}).labelled = true;\\n\\n\\n\tstmt(\"break\", function () {\\n\t\tvar v = state.tokens.next.value;\\n\\n\t\tif (funct[\"(breakage)\"] === 0)\\n\t\t\twarning(\"W052\", state.tokens.next, this.value);\\n\\n\t\tif (!state.option.asi)\\n\t\t\tnolinebreak(this);\\n\\n\t\tif (state.tokens.next.id !== \";\") {\\n\t\t\tif (state.tokens.curr.line === state.tokens.next.line) {\\n\t\t\t\tif (funct[v] !== \"label\") {\\n\t\t\t\t\twarning(\"W090\", state.tokens.next, v);\\n\t\t\t\t} else if (scope[v] !== funct) {\\n\t\t\t\t\twarning(\"W091\", state.tokens.next, v);\\n\t\t\t\t}\\n\t\t\t\tthis.first = state.tokens.next;\\n\t\t\t\tadvance();\\n\t\t\t}\\n\t\t}\\n\t\treachable(\"break\");\\n\t\treturn this;\\n\t}).exps = true;\\n\\n\\n\tstmt(\"continue\", function () {\\n\t\tvar v = state.tokens.next.value;\\n\\n\t\tif (funct[\"(breakage)\"] === 0)\\n\t\t\twarning(\"W052\", state.tokens.next, this.value);\\n\\n\t\tif (!state.option.asi)\\n\t\t\tnolinebreak(this);\\n\\n\t\tif (state.tokens.next.id !== \";\") {\\n\t\t\tif (state.tokens.curr.line === state.tokens.next.line) {\\n\t\t\t\tif (funct[v] !== \"label\") {\\n\t\t\t\t\twarning(\"W090\", state.tokens.next, v);\\n\t\t\t\t} else if (scope[v] !== funct) {\\n\t\t\t\t\twarning(\"W091\", state.tokens.next, v);\\n\t\t\t\t}\\n\t\t\t\tthis.first = state.tokens.next;\\n\t\t\t\tadvance();\\n\t\t\t}\\n\t\t} else if (!funct[\"(loopage)\"]) {\\n\t\t\twarning(\"W052\", state.tokens.next, this.value);\\n\t\t}\\n\t\treachable(\"continue\");\\n\t\treturn this;\\n\t}).exps = true;\\n\\n\\n\tstmt(\"return\", function () {\\n\t\tif (this.line === state.tokens.next.line) {\\n\t\t\tif (state.tokens.next.id === \"(regexp)\")\\n\t\t\t\twarning(\"W092\");\\n\\n\t\t\tif (state.tokens.next.id !== \";\" && !state.tokens.next.reach) {\\n\t\t\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\t\tthis.first = expression(0);\\n\\n\t\t\t\tif (this.first.type === \"(punctuator)\" && this.first.value === \"=\" && !state.option.boss) {\\n\t\t\t\t\twarningAt(\"W093\", this.first.line, this.first.character);\\n\t\t\t\t}\\n\t\t\t}\\n\t\t} else if (!state.option.asi) {\\n\t\t\tnolinebreak(this); // always warn (Line breaking error)\\n\t\t}\\n\t\treachable(\"return\");\\n\t\treturn this;\\n\t}).exps = true;\\n\\n\\n\tstmt(\"throw\", function () {\\n\t\tnolinebreak(this);\\n\t\tnonadjacent(state.tokens.curr, state.tokens.next);\\n\t\tthis.first = expression(20);\\n\t\treachable(\"throw\");\\n\t\treturn this;\\n\t}).exps = true;\\n\\n\t// Future Reserved Words\\n\\n\tFutureReservedWord(\"abstract\");\\n\tFutureReservedWord(\"boolean\");\\n\tFutureReservedWord(\"byte\");\\n\tFutureReservedWord(\"char\");\\n\tFutureReservedWord(\"class\", { es5: true });\\n\tFutureReservedWord(\"double\");\\n\tFutureReservedWord(\"enum\", { es5: true });\\n\tFutureReservedWord(\"export\", { es5: true });\\n\tFutureReservedWord(\"extends\", { es5: true });\\n\tFutureReservedWord(\"final\");\\n\tFutureReservedWord(\"float\");\\n\tFutureReservedWord(\"goto\");\\n\tFutureReservedWord(\"implements\", { es5: true, strictOnly: true });\\n\tFutureReservedWord(\"import\", { es5: true });\\n\tFutureReservedWord(\"int\");\\n\tFutureReservedWord(\"interface\");\\n\tFutureReservedWord(\"let\", { es5: true, strictOnly: true });\\n\tFutureReservedWord(\"long\");\\n\tFutureReservedWord(\"native\");\\n\tFutureReservedWord(\"package\", { es5: true, strictOnly: true });\\n\tFutureReservedWord(\"private\", { es5: true, strictOnly: true });\\n\tFutureReservedWord(\"protected\", { es5: true, strictOnly: true });\\n\tFutureReservedWord(\"public\", { es5: true, strictOnly: true });\\n\tFutureReservedWord(\"short\");\\n\tFutureReservedWord(\"static\", { es5: true, strictOnly: true });\\n\tFutureReservedWord(\"super\", { es5: true });\\n\tFutureReservedWord(\"synchronized\");\\n\tFutureReservedWord(\"throws\");\\n\tFutureReservedWord(\"transient\");\\n\tFutureReservedWord(\"volatile\");\\n\tFutureReservedWord(\"yield\", { es5: true, strictOnly: true });\\n\\n\t// Parse JSON\\n\\n\tfunction jsonValue() {\\n\\n\t\tfunction jsonObject() {\\n\t\t\tvar o = {}, t = state.tokens.next;\\n\t\t\tadvance(\"{\");\\n\t\t\tif (state.tokens.next.id !== \"}\") {\\n\t\t\t\tfor (;;) {\\n\t\t\t\t\tif (state.tokens.next.id === \"(end)\") {\\n\t\t\t\t\t\terror(\"E026\", state.tokens.next, t.line);\\n\t\t\t\t\t} else if (state.tokens.next.id === \"}\") {\\n\t\t\t\t\t\twarning(\"W094\", state.tokens.curr);\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t} else if (state.tokens.next.id === \",\") {\\n\t\t\t\t\t\terror(\"E028\", state.tokens.next);\\n\t\t\t\t\t} else if (state.tokens.next.id !== \"(string)\") {\\n\t\t\t\t\t\twarning(\"W095\", state.tokens.next, state.tokens.next.value);\\n\t\t\t\t\t}\\n\t\t\t\t\tif (o[state.tokens.next.value] === true) {\\n\t\t\t\t\t\twarning(\"W075\", state.tokens.next, state.tokens.next.value);\\n\t\t\t\t\t} else if ((state.tokens.next.value === \"__proto__\" &&\\n\t\t\t\t\t\t!state.option.proto) || (state.tokens.next.value === \"__iterator__\" &&\\n\t\t\t\t\t\t!state.option.iterator)) {\\n\t\t\t\t\t\twarning(\"W096\", state.tokens.next, state.tokens.next.value);\\n\t\t\t\t\t} else {\\n\t\t\t\t\t\to[state.tokens.next.value] = true;\\n\t\t\t\t\t}\\n\t\t\t\t\tadvance();\\n\t\t\t\t\tadvance(\":\");\\n\t\t\t\t\tjsonValue();\\n\t\t\t\t\tif (state.tokens.next.id !== \",\") {\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t}\\n\t\t\t\t\tadvance(\",\");\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\tadvance(\"}\");\\n\t\t}\\n\\n\t\tfunction jsonArray() {\\n\t\t\tvar t = state.tokens.next;\\n\t\t\tadvance(\"[\");\\n\t\t\tif (state.tokens.next.id !== \"]\") {\\n\t\t\t\tfor (;;) {\\n\t\t\t\t\tif (state.tokens.next.id === \"(end)\") {\\n\t\t\t\t\t\terror(\"E027\", state.tokens.next, t.line);\\n\t\t\t\t\t} else if (state.tokens.next.id === \"]\") {\\n\t\t\t\t\t\twarning(\"W094\", state.tokens.curr);\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t} else if (state.tokens.next.id === \",\") {\\n\t\t\t\t\t\terror(\"E028\", state.tokens.next);\\n\t\t\t\t\t}\\n\t\t\t\t\tjsonValue();\\n\t\t\t\t\tif (state.tokens.next.id !== \",\") {\\n\t\t\t\t\t\tbreak;\\n\t\t\t\t\t}\\n\t\t\t\t\tadvance(\",\");\\n\t\t\t\t}\\n\t\t\t}\\n\t\t\tadvance(\"]\");\\n\t\t}\\n\\n\t\tswitch (state.tokens.next.id) {\\n\t\tcase \"{\":\\n\t\t\tjsonObject();\\n\t\t\tbreak;\\n\t\tcase \"[\":\\n\t\t\tjsonArray();\\n\t\t\tbreak;\\n\t\tcase \"true\":\\n\t\tcase \"false\":\\n\t\tcase \"null\":\\n\t\tcase \"(number)\":\\n\t\tcase \"(string)\":\\n\t\t\tadvance();\\n\t\t\tbreak;\\n\t\tcase \"-\":\\n\t\t\tadvance(\"-\");\\n\t\t\tif (state.tokens.curr.character !== state.tokens.next.from) {\\n\t\t\t\twarning(\"W011\", state.tokens.curr);\\n\t\t\t}\\n\t\t\tadjacent(state.tokens.curr, state.tokens.next);\\n\t\t\tadvance(\"(number)\");\\n\t\t\tbreak;\\n\t\tdefault:\\n\t\t\terror(\"E003\", state.tokens.next);\\n\t\t}\\n\t}\\n\\n\\n\t// The actual JSHINT function itself.\\n\tvar itself = function (s, o, g) {\\n\t\tvar a, i, k, x;\\n\t\tvar optionKeys;\\n\t\tvar newOptionObj = {};\\n\\n\t\tstate.reset();\\n\\n\t\tif (o && o.scope) {\\n\t\t\tJSHINT.scope = o.scope;\\n\t\t} else {\\n\t\t\tJSHINT.errors = [];\\n\t\t\tJSHINT.undefs = [];\\n\t\t\tJSHINT.internals = [];\\n\t\t\tJSHINT.blacklist = {};\\n\t\t\tJSHINT.scope = \"(main)\";\\n\t\t}\\n\\n\t\tpredefined = Object.create(null);\\n\t\tcombine(predefined, vars.ecmaIdentifiers);\\n\t\tcombine(predefined, vars.reservedVars);\\n\\n\t\tcombine(predefined, g || {});\\n\\n\t\tdeclared = Object.create(null);\\n\t\texported = Object.create(null);\\n\t\tignored = Object.create(null);\\n\\n\t\tif (o) {\\n\t\t\ta = o.predef;\\n\t\t\tif (a) {\\n\t\t\t\tif (!Array.isArray(a) && typeof a === \"object\") {\\n\t\t\t\t\ta = Object.keys(a);\\n\t\t\t\t}\\n\\n\t\t\t\ta.forEach(function (item) {\\n\t\t\t\t\tvar slice, prop;\\n\\n\t\t\t\t\tif (item[0] === \"-\") {\\n\t\t\t\t\t\tslice = item.slice(1);\\n\t\t\t\t\t\tJSHINT.blacklist[slice] = slice;\\n\t\t\t\t\t} else {\\n\t\t\t\t\t\tprop = Object.getOwnPropertyDescriptor(o.predef, item);\\n\t\t\t\t\t\tpredefined[item] = prop ? prop.value : false;\\n\t\t\t\t\t}\\n\t\t\t\t});\\n\t\t\t}\\n\\n\t\t\toptionKeys = Object.keys(o);\\n\t\t\tfor (x = 0; x < optionKeys.length; x++) {\\n\t\t\t\tif (/^-W\\\\d{3}$/g.test(optionKeys[x])) {\\n\t\t\t\t\tignored[optionKeys[x].slice(1)] = true;\\n\t\t\t\t} else {\\n\t\t\t\t\tnewOptionObj[optionKeys[x]] = o[optionKeys[x]];\\n\\n\t\t\t\t\tif (optionKeys[x] === \"newcap\" && o[optionKeys[x]] === false)\\n\t\t\t\t\t\tnewOptionObj[\"(explicitNewcap)\"] = true;\\n\\n\t\t\t\t\tif (optionKeys[x] === \"indent\")\\n\t\t\t\t\t\tnewOptionObj[\"(explicitIndent)\"] = true;\\n\t\t\t\t}\\n\t\t\t}\\n\t\t}\\n\\n\t\tstate.option = newOptionObj;\\n\\n\t\tstate.option.indent = state.option.indent || 4;\\n\t\tstate.option.maxerr = state.option.maxerr || 50;\\n\\n\t\tindent = 1;\\n\t\tglobal = Object.create(predefined);\\n\t\tscope = global;\\n\t\tfunct = {\\n\t\t\t\"(global)\":   true,\\n\t\t\t\"(name)\":\t  \"(global)\",\\n\t\t\t\"(scope)\":\t  scope,\\n\t\t\t\"(breakage)\": 0,\\n\t\t\t\"(loopage)\":  0,\\n\t\t\t\"(tokens)\":   {},\\n\t\t\t\"(metrics)\":   createMetrics(state.tokens.next)\\n\t\t};\\n\t\tfunctions = [funct];\\n\t\turls = [];\\n\t\tstack = null;\\n\t\tmember = {};\\n\t\tmembersOnly = null;\\n\t\timplied = {};\\n\t\tinblock = false;\\n\t\tlookahead = [];\\n\t\twarnings = 0;\\n\t\tunuseds = [];\\n\\n\t\tif (!isString(s) && !Array.isArray(s)) {\\n\t\t\terrorAt(\"E004\", 0);\\n\t\t\treturn false;\\n\t\t}\\n\\n\t\tvar api = {\\n\t\t\tget isJSON() {\\n\t\t\t\treturn state.jsonMode;\\n\t\t\t},\\n\\n\t\t\tgetOption: function (name) {\\n\t\t\t\treturn state.option[name] || null;\\n\t\t\t},\\n\\n\t\t\tgetCache: function (name) {\\n\t\t\t\treturn state.cache[name];\\n\t\t\t},\\n\\n\t\t\tsetCache: function (name, value) {\\n\t\t\t\tstate.cache[name] = value;\\n\t\t\t},\\n\\n\t\t\twarn: function (code, data) {\\n\t\t\t\twarningAt.apply(null, [ code, data.line, data.char ].concat(data.data));\\n\t\t\t},\\n\\n\t\t\ton: function (names, listener) {\\n\t\t\t\tnames.split(\" \").forEach(function (name) {\\n\t\t\t\t\temitter.on(name, listener);\\n\t\t\t\t}.bind(this));\\n\t\t\t}\\n\t\t};\\n\\n\t\temitter.removeAllListeners();\\n\t\t(extraModules || []).forEach(function (func) {\\n\t\t\tfunc(api);\\n\t\t});\\n\\n\t\tstate.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax[\"(begin)\"];\\n\\n\t\tlex = new Lexer(s);\\n\\n\t\tlex.on(\"warning\", function (ev) {\\n\t\t\twarningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));\\n\t\t});\\n\\n\t\tlex.on(\"error\", function (ev) {\\n\t\t\terrorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));\\n\t\t});\\n\\n\t\tlex.on(\"fatal\", function (ev) {\\n\t\t\tquit(\"E041\", ev.line, ev.from);\\n\t\t});\\n\\n\t\tlex.on(\"Identifier\", function (ev) {\\n\t\t\temitter.emit(\"Identifier\", ev);\\n\t\t});\\n\\n\t\tlex.on(\"String\", function (ev) {\\n\t\t\temitter.emit(\"String\", ev);\\n\t\t});\\n\\n\t\tlex.on(\"Number\", function (ev) {\\n\t\t\temitter.emit(\"Number\", ev);\\n\t\t});\\n\\n\t\tlex.start();\\n\\n\t\t// Check options\\n\t\tfor (var name in o) {\\n\t\t\tif (_.has(o, name)) {\\n\t\t\t\tcheckOption(name, state.tokens.curr);\\n\t\t\t}\\n\t\t}\\n\\n\t\tassume();\\n\\n\t\t// combine the passed globals after we\\'ve assumed all our options\\n\t\tcombine(predefined, g || {});\\n\\n\t\t//reset values\\n\t\tcomma.first = true;\\n\\n\t\ttry {\\n\t\t\tadvance();\\n\t\t\tswitch (state.tokens.next.id) {\\n\t\t\tcase \"{\":\\n\t\t\tcase \"[\":\\n\t\t\t\tstate.option.laxbreak = true;\\n\t\t\t\tstate.jsonMode = true;\\n\t\t\t\tjsonValue();\\n\t\t\t\tbreak;\\n\t\t\tdefault:\\n\t\t\t\tdirectives();\\n\\n\t\t\t\tif (state.directive[\"use strict\"]) {\\n\t\t\t\t\tif (!state.option.globalstrict && !state.option.node) {\\n\t\t\t\t\t\twarning(\"W097\", state.tokens.prev);\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\tstatements();\\n\t\t\t}\\n\t\t\tadvance((state.tokens.next && state.tokens.next.value !== \".\")\t? \"(end)\" : undefined);\\n\\n\t\t\tvar markDefined = function (name, context) {\\n\t\t\t\tdo {\\n\t\t\t\t\tif (typeof context[name] === \"string\") {\\n\t\t\t\t\t\t// JSHINT marks unused variables as \\'unused\\' and\\n\t\t\t\t\t\t// unused function declaration as \\'unction\\'. This\\n\t\t\t\t\t\t// code changes such instances back \\'var\\' and\\n\t\t\t\t\t\t// \\'closure\\' so that the code in JSHINT.data()\\n\t\t\t\t\t\t// doesn\\'t think they\\'re unused.\\n\\n\t\t\t\t\t\tif (context[name] === \"unused\")\\n\t\t\t\t\t\t\tcontext[name] = \"var\";\\n\t\t\t\t\t\telse if (context[name] === \"unction\")\\n\t\t\t\t\t\t\tcontext[name] = \"closure\";\\n\\n\t\t\t\t\t\treturn true;\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tcontext = context[\"(context)\"];\\n\t\t\t\t} while (context);\\n\\n\t\t\t\treturn false;\\n\t\t\t};\\n\\n\t\t\tvar clearImplied = function (name, line) {\\n\t\t\t\tif (!implied[name])\\n\t\t\t\t\treturn;\\n\\n\t\t\t\tvar newImplied = [];\\n\t\t\t\tfor (var i = 0; i < implied[name].length; i += 1) {\\n\t\t\t\t\tif (implied[name][i] !== line)\\n\t\t\t\t\t\tnewImplied.push(implied[name][i]);\\n\t\t\t\t}\\n\\n\t\t\t\tif (newImplied.length === 0)\\n\t\t\t\t\tdelete implied[name];\\n\t\t\t\telse\\n\t\t\t\t\timplied[name] = newImplied;\\n\t\t\t};\\n\\n\t\t\tvar warnUnused = function (name, tkn, type, unused_opt) {\\n\t\t\t\tvar line = tkn.line;\\n\t\t\t\tvar chr  = tkn.character;\\n\\n\t\t\t\tif (unused_opt === undefined) {\\n\t\t\t\t\tunused_opt = state.option.unused;\\n\t\t\t\t}\\n\\n\t\t\t\tif (unused_opt === true) {\\n\t\t\t\t\tunused_opt = \"last-param\";\\n\t\t\t\t}\\n\\n\t\t\t\tvar warnable_types = {\\n\t\t\t\t\t\"vars\": [\"var\"],\\n\t\t\t\t\t\"last-param\": [\"var\", \"last-param\"],\\n\t\t\t\t\t\"strict\": [\"var\", \"param\", \"last-param\"]\\n\t\t\t\t};\\n\\n\t\t\t\tif (unused_opt) {\\n\t\t\t\t\tif (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {\\n\t\t\t\t\t\twarningAt(\"W098\", line, chr, name);\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\tunuseds.push({\\n\t\t\t\t\tname: name,\\n\t\t\t\t\tline: line,\\n\t\t\t\t\tcharacter: chr\\n\t\t\t\t});\\n\t\t\t};\\n\\n\t\t\tvar checkUnused = function (func, key) {\\n\t\t\t\tvar type = func[key];\\n\t\t\t\tvar tkn = func[\"(tokens)\"][key];\\n\\n\t\t\t\tif (key.charAt(0) === \"(\")\\n\t\t\t\t\treturn;\\n\\n\t\t\t\tif (type !== \"unused\" && type !== \"unction\")\\n\t\t\t\t\treturn;\\n\\n\t\t\t\t// Params are checked separately from other variables.\\n\t\t\t\tif (func[\"(params)\"] && func[\"(params)\"].indexOf(key) !== -1)\\n\t\t\t\t\treturn;\\n\\n\t\t\t\t// Variable is in global scope and defined as exported.\\n\t\t\t\tif (func[\"(global)\"] && _.has(exported, key)) {\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\twarnUnused(key, tkn, \"var\");\\n\t\t\t};\\n\\n\t\t\t// Check queued \\'x is not defined\\' instances to see if they\\'re still undefined.\\n\t\t\tfor (i = 0; i < JSHINT.undefs.length; i += 1) {\\n\t\t\t\tk = JSHINT.undefs[i].slice(0);\\n\\n\t\t\t\tif (markDefined(k[2].value, k[0])) {\\n\t\t\t\t\tclearImplied(k[2].value, k[2].line);\\n\t\t\t\t} else if (state.option.undef) {\\n\t\t\t\t\twarning.apply(warning, k.slice(1));\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tfunctions.forEach(function (func) {\\n\t\t\t\tif (func[\"(unusedOption)\"] === false) {\\n\t\t\t\t\treturn;\\n\t\t\t\t}\\n\\n\t\t\t\tfor (var key in func) {\\n\t\t\t\t\tif (_.has(func, key)) {\\n\t\t\t\t\t\tcheckUnused(func, key);\\n\t\t\t\t\t}\\n\t\t\t\t}\\n\\n\t\t\t\tif (!func[\"(params)\"])\\n\t\t\t\t\treturn;\\n\\n\t\t\t\tvar params = func[\"(params)\"].slice();\\n\t\t\t\tvar param  = params.pop();\\n\t\t\t\tvar type, unused_type;\\n\\n\t\t\t\twhile (param) {\\n\t\t\t\t\ttype = func[param];\\n\t\t\t\t\tunused_type = (params.length === func[\"(params)\"].length - 1 ? \"last-param\" : \"param\");\\n\\n\t\t\t\t\t// \\'undefined\\' is a special case for (function (window, undefined) { ... })();\\n\t\t\t\t\t// patterns.\\n\\n\t\t\t\t\tif (param === \"undefined\")\\n\t\t\t\t\t\treturn;\\n\\n\t\t\t\t\tif (type === \"unused\" || type === \"unction\") {\\n\t\t\t\t\t\twarnUnused(param, func[\"(tokens)\"][param], unused_type, func[\"(unusedOption)\"]);\\n\t\t\t\t\t}\\n\\n\t\t\t\t\tparam = params.pop();\\n\t\t\t\t}\\n\t\t\t});\\n\\n\t\t\tfor (var key in declared) {\\n\t\t\t\tif (_.has(declared, key) && !_.has(global, key)) {\\n\t\t\t\t\twarnUnused(key, declared[key], \"var\");\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t} catch (err) {\\n\t\t\tif (err && err.name === \"JSHintError\") {\\n\t\t\t\tvar nt = state.tokens.next || {};\\n\t\t\t\tJSHINT.errors.push({\\n\t\t\t\t\tscope     : \"(main)\",\\n\t\t\t\t\traw       : err.raw,\\n\t\t\t\t\treason    : err.message,\\n\t\t\t\t\tline      : err.line || nt.line,\\n\t\t\t\t\tcharacter : err.character || nt.from\\n\t\t\t\t}, null);\\n\t\t\t} else {\\n\t\t\t\tthrow err;\\n\t\t\t}\\n\t\t}\\n\\n\t\t// Loop over the listed \"internals\", and check them as well.\\n\\n\t\tif (JSHINT.scope === \"(main)\") {\\n\t\t\to = o || {};\\n\\n\t\t\tfor (i = 0; i < JSHINT.internals.length; i += 1) {\\n\t\t\t\tk = JSHINT.internals[i];\\n\t\t\t\to.scope = k.elem;\\n\t\t\t\titself(k.value, o, g);\\n\t\t\t}\\n\t\t}\\n\\n\t\treturn JSHINT.errors.length === 0;\\n\t};\\n\\n\t// Modules.\\n\titself.addModule = function (func) {\\n\t\textraModules.push(func);\\n\t};\\n\\n\titself.addModule(style.register);\\n\\n\t// Data summary.\\n\titself.data = function () {\\n\t\tvar data = {\\n\t\t\tfunctions: [],\\n\t\t\toptions: state.option\\n\t\t};\\n\t\tvar implieds = [];\\n\t\tvar members = [];\\n\t\tvar fu, f, i, j, n, globals;\\n\\n\t\tif (itself.errors.length) {\\n\t\t\tdata.errors = itself.errors;\\n\t\t}\\n\\n\t\tif (state.jsonMode) {\\n\t\t\tdata.json = true;\\n\t\t}\\n\\n\t\tfor (n in implied) {\\n\t\t\tif (_.has(implied, n)) {\\n\t\t\t\timplieds.push({\\n\t\t\t\t\tname: n,\\n\t\t\t\t\tline: implied[n]\\n\t\t\t\t});\\n\t\t\t}\\n\t\t}\\n\\n\t\tif (implieds.length > 0) {\\n\t\t\tdata.implieds = implieds;\\n\t\t}\\n\\n\t\tif (urls.length > 0) {\\n\t\t\tdata.urls = urls;\\n\t\t}\\n\\n\t\tglobals = Object.keys(scope);\\n\t\tif (globals.length > 0) {\\n\t\t\tdata.globals = globals;\\n\t\t}\\n\\n\t\tfor (i = 1; i < functions.length; i += 1) {\\n\t\t\tf = functions[i];\\n\t\t\tfu = {};\\n\\n\t\t\tfor (j = 0; j < functionicity.length; j += 1) {\\n\t\t\t\tfu[functionicity[j]] = [];\\n\t\t\t}\\n\\n\t\t\tfor (j = 0; j < functionicity.length; j += 1) {\\n\t\t\t\tif (fu[functionicity[j]].length === 0) {\\n\t\t\t\t\tdelete fu[functionicity[j]];\\n\t\t\t\t}\\n\t\t\t}\\n\\n\t\t\tfu.name = f[\"(name)\"];\\n\t\t\tfu.param = f[\"(params)\"];\\n\t\t\tfu.line = f[\"(line)\"];\\n\t\t\tfu.character = f[\"(character)\"];\\n\t\t\tfu.last = f[\"(last)\"];\\n\t\t\tfu.lastcharacter = f[\"(lastcharacter)\"];\\n\t\t\tdata.functions.push(fu);\\n\t\t}\\n\\n\t\tif (unuseds.length > 0) {\\n\t\t\tdata.unused = unuseds;\\n\t\t}\\n\\n\t\tmembers = [];\\n\t\tfor (n in member) {\\n\t\t\tif (typeof member[n] === \"number\") {\\n\t\t\t\tdata.member = member;\\n\t\t\t\tbreak;\\n\t\t\t}\\n\t\t}\\n\\n\t\treturn data;\\n\t};\\n\\n\titself.jshint = itself;\\n\\n\treturn itself;\\n}());\\n\\n// Make JSHINT a Node module, if possible.\\nif (typeof exports === \"object\" && exports) {\\n\texports.JSHINT = JSHINT;\\n}\\n\\n//@ sourceURL=/src/stable/jshint.js'));\nrequire(\"/src/stable/jshint.js\");JSHINT=require(\"/src/stable/jshint.js\").JSHINT})();\n/* END INSERT */\n\nrealExports.JSHINT = JSHINT;\nexports = realExports;\n\n// jshint-endignore\n\n})(typeof exports == \"undefined\" ? (typeof doctest == \"undefined\" ? doctest = {} : doctest) : exports);\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/examples/examples-2.html",
    "content": "<!DOCTEST html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Example</title>\n    <script src=\"../doctest.js\"></script>\n    <script type=\"text/javascript\" src=\"../.resources/toc.js\"></script>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../.resources/doc.css\" />\n    <script src=\"../.resources/esprima/esprima.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doctest.css\" type=\"text/css\">\n  </head>\n  <body class=\"autodoctest\">\n\n<!-- HEADER -->\n<!-- /HEADER -->\n<pre class=\"doctest\">\n$ print('hey you')\nhey you\n$ print({'whatever': 'example', something: [1, 2, 3]});\n{something: [1, 2, 3], whatever: \"example\"}\n$ print(1/0)\nNaN\n$ function foo() {\n>   console.log({hey: 'you'});\n>   throw 'whatever';\n> }\n> foo();\nError: whatever\n</pre>\n\n<pre class=\"test\">\nprint(1+2)\n/* =>\n   3\n*/\n\nfunction testme() {\n  setTimeout(function () {\n    print('hey you!');\n  }, 10);\n}\ntestme();\nwait(200);\n/* => hey you! */\n</pre>\n\n<pre class=\"test\" href=\"./examples-2.js\"></pre>\n\n<pre class=\"test\">\nfunction stop() {\n  throw Abort();\n}\n\nprint(1+2);\n/* => 3 */\n\nstop();\n/* => something */\n\nprint(5+5);\n/* => 12 */\n</pre>\n\n<!-- FOOTER -->\n<!-- /FOOTER -->\n\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/examples/examples-2.js",
    "content": "function factorial(n) {\n  if (n == 1) {\n    return n;\n  }\n  return n * factorial(n-1);\n}\n\nprint(factorial(4));\n/* => 24 */\nprint(factorial(3));\n/* =>\n   20\n*/"
  },
  {
    "path": "togetherjs/tests/doctestjs/examples/examples.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<title>Doctest.js: examples</title>\n<script type=\"text/javascript\" src=\"../doctest.js\"></script>\n<script type=\"text/javascript\" src=\"../.resources/toc.js\"></script>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"../.resources/doc.css\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"../doctest.css\" />\n\n</head>\n<body class=\"autodoctest\">\n\n<!-- HEADER --><a href=\"http://github.com/ianb/doctestjs\"><img\nstyle=\"position: absolute; top: 0; right: 0; border: 0;\"\nsrc=\"http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png\"\nalt=\"Fork me on GitHub\" /></a>\n\n<div id=\"container\">\n\n<div class=\"download\">\n <a href=\"http://github.com/ianb/doctestjs/zipball/master\">\n  <img border=\"0\" width=\"90\"\n   src=\"http://github.com/images/modules/download/zip.png\" /></a>\n <a href=\"http://github.com/ianb/doctestjs/tarball/master\">\n  <img border=\"0\" width=\"90\"\n   src=\"http://github.com/images/modules/download/tar.png\" /></a>\n</div>\n\n<h1 class=\"title\"><a href=\"http://github.com/ianb/doctestjs\">doctest.js</a>\n <span class=\"small\">by\n <a href=\"http://blog.ianbicking.org\">Ian Bicking</a></span>\n</h1>\n\n<div>\n<!-- /HEADER -->\n\n<h2>Doctest.js: examples</h2>\n\n<div id=\"contents\"></div>\n\n<div id=\"doctest-output\"></div>\n\n<h3>Web Service</h3>\n\n<div>\n  You can use doctest.js to test APIs; in fact, it's reasonable to use\n  it for acceptance tests of the web APIs themselves, not just to test\n  the Javascript wrappers around those APIs.\n</div>\n\n<div class=\"test\">\n  In this example we'll access the <a\n  href=\"http://www.geonames.org/export/web-services.html\">Geonames\n  API</a>.  First we'll want some routines to help us later on.  You\n  could put these into a separate <code>.js</code> file and include\n  it, but often (especially in an example ;) it's best to be fully\n  transparent and list all the routines out in the open...\n\n<pre class=\"doctest\">\n$ apiLocation = 'http://ws.geonames.org/';\n$ function query(endpoint, q) {\n>   var url = apiLocation + endpoint;\n>   jQuery.ajax({\n>     url: url,\n>     data: q,\n>     dataType: \"json\",\n>     success: Spy('success', {wait: true, ignoreThis: true}),\n>     error: Spy('error')\n>   });\n> }\n</pre>\n\n  Some things to notice about this example:\n\n  <ul>\n    <li><code>apiLocation</code> is hard coded, but you could read it\n    from the query string, allowing something like\n    <code>test.html?apiLocation=http://localhost:8080</code>.\n    </li>\n\n    <li>We create a Spy for both success and failure, as we want to\n    track both of these.  We could just use functions, but mostly\n    there's an advantage to being able to watch <code>.called</code>.\n    If you used <code>{writes: true}</code> you might not need the\n    <code>.applies</code> functions.\n    </li>\n\n    <li><code>wait</code> can be called from anywhere.  That means\n    when you call this function doctest will wait until something is\n    called, and will test all the output since that time (either the\n    success or failure <code>writeln()</code>).  Timeout is the other\n    possibility.\n    </li>\n  </ul>\n\n</div>\n\n<div>\n  Now we'll use the routine to actually run a test:\n\n<pre class=\"doctest\">\n$ query('postalCodeSearchJSON', {postalcode: 9011, maxRows: 5});\nsuccess({\n  postalCodes: [\n    {...}\n  ]\n}, ...)\n</pre>\n\n</div>\n\n<h3>Web Service/XML</h3>\n\n<div class=\"test\">\n  What we do for JSON, we can also do for XML; in this case\n  it's just fetching a static XML Atom document.\n\n<pre class=\"test\">\n$.ajax({\n  url: './.resources/example.xml',\n  dataType: 'xml',\n  success: function (doc) {\n    gdoc = doc;\n    writeln(repr(doc));\n  },\n  error: Spy('error')\n});\nwait(0.5);\n/* =>\n&lt;feed xmlns=\"http://www.w3.org/2005/Atom\">\n  &lt;title>Example Feed&lt;/title>\n  ...\n&lt;/feed>\n*/\n\n</pre>\n\n</div>\n\n<h3>Deferred/Promise</h3>\n\n<div class=\"test\">\n\n  You can also\n  print <a href=\"http://api.jquery.com/category/deferred-object/\">jquery.Deferred</a>\n  (promise) objects once they've resolved, using\n  the <code>printResolved()</code> function.  This also implicitly\n  calls <code>wait()</code> with the condition that all the promises\n  be resolved.  Both errors and resolved values are printed.\n\n  <pre class=\"test\">\nvar def1 = $.Deferred();\nvar def2 = $.Deferred();\ndef1.resolve(\"Value 1!\", \"Value2!\");\nsetTimeout(function () {\n  def2.reject(\"sucka\");\n}, 500);\nprintResolved(\"def1\", def1, \"def2\", def2);\n// => def1 Value 1! Value2! def2 Error: sucka\n  </pre>\n</div>\n\n<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js\"></script>\n\n<!-- FOOTER --></div>\n\n<h3>Download</h3>\n<p>\n You can download this project in either\n <a href=\"http://github.com/ianb/doctestjs/zipball/master\">zip</a> or\n <a href=\"http://github.com/ianb/doctestjs/tarball/master\">tar</a> formats.\n</p>\n\n<p>You can also clone the project with <a href=\"http://git-scm.com\">Git</a>\n by running:\n <pre>$ git clone git://github.com/ianb/doctestjs</pre>\n</p>\n\n<div class=\"footer\">\n get the source code on GitHub:\n <a href=\"http://github.com/ianb/doctestjs\">ianb/doctestjs</a>\n</div>\n\n</div>\n\n<script type=\"text/javascript\">\nvar gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\ndocument.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n</script>\n<script type=\"text/javascript\">\ntry {\nvar pageTracker = _gat._getTracker(\"UA-6731441-12\");\npageTracker._trackPageview();\n} catch(err) {}</script>\n<!-- /FOOTER -->\n\n</body> </html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/examples/long-running-tests.html",
    "content": "<!DOCTEST html>\n<html>\n    <head>\n        <meta charset=\"UTF-8\">\n        <title>Example</title>\n        <script src=\"../doctest.js\"></script>\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"../.resources/doc.css\" />\n        <script src=\"../.resources/esprima/esprima.js\"></script>\n        <link rel=\"stylesheet\" href=\"../doctest.css\" type=\"text/css\">\n    </head>\n    <body class=\"autodoctest\">\n        This is an example of tests that:\n        <ul>\n            <li>wait on long running processes</li>\n            <li>use an external javascript file</li>\n            <li>sections in the tests that will make them run in sequence</li>\n        </ul>\n\n        <pre class=\"test\" href=\"long-running-tests.js\"></pre>\n\n    </body>\n</html>"
  },
  {
    "path": "togetherjs/tests/doctestjs/examples/long-running-tests.js",
    "content": "// = SECTION First\nvar done = false;\nfunction foo() {\n    window.setTimeout(function() {\n        done = true;\n        some_var = true;\n    }, 2000);\n    wait(function(){return done;});\n}\nfoo();\nprint(done);\n// => false\n\n// = SECTION check output 1\nprint(done);\n// => true\nprint(some_var);\n// => true\n\n// = SECTION Second\ndone = false;\nfunction foo2() {\n    window.setTimeout(function() {\n        done = true;\n        another_var = true;\n    }, 2000);\n    wait(function(){return done;});\n}\nfoo2();\nprint(done);\n// => false\n\n// = SECTION check output 2\nprint(done);\n// => true\nprint(another_var);\n// => true\nprint(some_var);\n// => true\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/index.html",
    "content": "<!DOCTYPE html>\n<html class=\"no-js\">\n  <head>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" href=\"doctest.css\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <title>Doctest.js: the humane Javascript test framework</title>\n    <meta name=\"description\" content=\"Doctest.js is a Javascript testing framework\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/normalize.min.css\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/main.css\">\n    <link rel=\"stylesheet\" href=\".resources/doc.css\">\n    <script src=\".resources/boilerplate/js/vendor/modernizr-2.6.1.min.js\"></script>\n    <script src=\"doctest.js\"></script>\n    <!-- EXTRA_HEAD -->\n<script type=\"text/javascript\" src=\"./.resources/toc.js\"></script>\n<script>\n  if (location.href.search(/^http:\\/\\/ianb.github.com/) == 0) {\n    location.href = 'http://doctestjs.org';\n  }\n</script>\n<!-- /EXTRA_HEAD -->\n  </head>\n  <body class=\"autodoctest\">\n\n    <div class=\"header-container\">\n      <header class=\"wrapper clearfix\">\n        <h1 class=\"title\"><a href=\"/\">Doctest.js</a>: <!-- TITLE -->A Humane Javascript Test Framework<!-- /TITLE --></h1>\n\n        <nav>\n          <ul>\n            <li><a href=\"https://github.com/ianb/doctestjs\">Github</a></li>\n            <li><a href=\"/reference.html\">Reference</a></li>\n            <li><a href=\"/tutorial.html\">Tutorial</a></li>\n          </ul>\n        </nav>\n\n      </header>\n    </div>\n\n    <div class=\"main-container\">\n      <div class=\"main wrapper clearfix\">\n\n\n     <!-- BODY -->\n\n\n<p><strong>Doctest.js</strong> is a test runner and testing framework for Javascript.</p>\n\n<p>Doctest uses a novel approach to testing: <em>example</em> and <em>expected result</em>.  Each test is a chunk of code that prints out results and side effects, and then the expected result is matched against that to see if the test passed or failed.</p>\n\n<p>An example (note: these are live examples &mdash; you can also try your own via the <a href=\"try.html\">live demo</a>):\n\n<pre class=\"test\">\nfunction capitalize(words) {\n  return words.replace(/\\b[a-z]/g, function (m) {\n    return m[0].toUpperCase();\n  });\n}\n\nprint(capitalize('some words'));\n// => Some Words\n\nprint(capitalize('some 4ward words'));\n// => Some 4ward Words\n</pre>\n</p>\n\n<p>This is similar to something like <code>assertEqual(capitalize('some words'), 'Some Words')</code> &mdash; there's a kind of \"equal\" check every time you print something.  Instead of doing stuff then testing every detail of what happened or what was returned, testing almost happens for you &mdash; you print out what you are interested in, and you can even punt: you can start by simply exercising everything that matters, and then inspecting that what happens is what you expect, and copying those results into the test.  For instance:\n\n<pre class=\"test\">\nfunction getProperties(obj) {\n  var result = [];\n  for (i in obj) {\n    result.push(i);\n  }\n  result.sort();\n  return result;\n}\n\nprint(getProperties({b: 1, a: 2}));\n// =>\n\nprint(getProperties(\"a\"));\n// =>\n</pre>\n\n</p>\n\n<p>Look: the first example worked great, <code>[\"a\", \"b\"]</code>.  The second example though wasn't right at all.  <code>\"0\"</code>?  Once we have a better idea we can adjust those tests:\n\n<pre class=\"test\">\nfunction getProperties(obj) {\n  var result = [];\n  for (i in obj) {\n    if (obj.hasOwnProperty(i)) {\n      result.push(i);\n    }\n  }\n  result.sort();\n  return result;\n}\n\nprint(getProperties({b: 1, a: 2}));\n// => [\"a\", \"b\"]\n\nprint(getProperties(\"a\"));\n// => []\n</pre>\n\nWell, that wasn't quite enough, but this kind of incremental development is exactly why doctest.js is so helpful: it shows you what you've done, it shows you both <em>presence</em> and <em>absence</em>. Most test frameworks only give you tools to test what <em>is</em> there, and not ensure that the things you don't want aren't there.</p>\n\n<h3>Async testing made easy!</h3>\n\n<p>The other <strong>great</strong> feature of doctest.js is how it lets you test async code.</p>\n\n<p>Async code is a bit tricky for all test runners.  When you run the test, the <em>result</em> of the test won't be known until after you wait some time.  Test runners might have ways to pause the test process while the test code completes.  They also need ways to test that everything you wanted to happen will happen.  Something that is often tricky in test code is to <em>make sure</em> that some callback was called &mdash; it's relatively easier to test that the callback was called correctly.</p>\n\n<p>Here doctest's ability to test both what's present and what's missing shines.  And the test runner also gives you a great way to serialize your asynchronous tests.</p>\n\n<p>The core feature here is <code>wait()</code> &mdash; this lets you register a callback that will tell the test runner when this block of code is fully finished.  An example:\n\n<pre class=\"test\">\nvar now = Date.now();\nvar done = false;\n\nsetTimeout(function () {\n  done = true;\n  print('The timeout finished!', Date.now() - now);\n}, 300);\n\nwait(function () {return done;});\n// => The timeout finished! ...\n</pre>\n\n(Notice we use <code>...</code> to ignore the specific number that is printed: ellipsis act as a kind of wildcard)\n\n</p>\n\n<p>With Doctest you don't have to use fake <code>setTimeout</code> or fake async anywhere &mdash; you always use the real thing, and it's nearly as easy to test as async code.  Frameworks that make this code synchronous are cheating you, because asynchronous code is the hardest of code and deserves to be tested accurately.  But when a test framework makes synchronous easy and asynchronous hard, it's all too easy when in the depth of test development to take shortcuts.</p>\n\n<h3>Mocking with Spy</h3>\n\n<p>In addition there's a simply mocking framework in doctest with Spy. This lets you create a function that records over time it is called &mdash; and each time it is called it prints out how it is called. It also makes it easy to wait on the Spy to be called:\n\n<pre class=\"test\">\nvar button = $('&lt;button>&lt;/button>');\n$('body').append(button);\nbutton.click(Spy('button.click'));\nbutton.click();\nSpy('button.click').wait();\n/* =>\n&lt;button />.button.click({...})\n*/\n</pre>\n\nYou'll notice here that we also ignored the details of the object passed to the callback.  We could use wildcards to match no part or any specific part of the argument called.  Also note that the value of <code>this</code> is shown: people usually forget that <code>this</code> is a kind of implicit argument to many functions, but again doctest makes the implicit explicit.  Also note that the <em>actual</em> output is always displayed, so you can use this to inspect aspects of the environment even if you don't want to test all fo them.\n</p>\n\n\n<h3>Lineage</h3>\n\n<p>Doctest is based on the Python <a href=\"http://docs.python.org/library/doctest.html\">doctest module</a> originally written by Tim Peters.  Spy was inspired some by Jasmine's <a href=\"http://pivotal.github.com/jasmine/jsdoc/symbols/jasmine.Spy.html\">Spy class</a>, and carries over ideas from <a href=\"http://pypi.python.org/pypi/MiniMock\">MiniMock</a>.</p>\n\n<p>If you've used Python's doctest and found it annoying or not widely useful for doctest: <strong>doctest.js fixes all those problems</strong>: see <a href=\"http://blog.ianbicking.org/2012/10/02/why-doctest-js-is-better-than-pythons-doctest/\">this post for more</a>.</p>\n\n\n<div style=\"display: none\">\n  <div id=\"doctest-output\"></div>\n</div>\n\n\n<!-- /BODY -->\n\n      </div> <!-- #main -->\n\n    </div> <!-- #main-container -->\n\n    <div class=\"footer-container\">\n      <footer class=\"wrapper\">\n        <h3 class=\"no-toc\">doctest.js is by <a href=\"http://ianbicking.org\">Ian Bicking</a>.\n          It's on <a href=\"https://github.com/ianb/doctestjs\">github</a>!</h3>\n      </footer>\n    </div>\n\n<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js\"></script>\n<script>\nwindow.jQuery || document.write('<script src=\".resources/boilerplate/js/vendor/jquery-1.8.1.min.js\"><\\/script>')\n</script>\n\n<script src=\".resources/boilerplate/js/main.js\"></script>\n\n<script type=\"text/javascript\">\n\n  var _gaq = _gaq || [];\n  _gaq.push(['_setAccount', 'UA-34921728-1']);\n  _gaq.push(['_trackPageview']);\n\n  (function() {\n    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n  })();\n\n</script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/package.json",
    "content": "{\n  \"name\": \"doctestjs\",\n  \"version\": \"0.3.0\",\n  \"main\": \"doctest\",\n  \"bin\": {\n    \"doctest\": \"./bin/doctest\"\n  },\n  \"description\": \"Example-based testing framework\",\n  \"keywords\": [],\n  \"author\": {\n    \"name\": \"Ian Bicking\",\n    \"email\": \"ian@ianbicking.org\",\n    \"web\": \"http://ianbicking.org\",\n    \"twitter\": \"ianbicking\"\n  },\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/ianb/doctestjs.git\"\n  }\n}\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/reference.html",
    "content": "<!DOCTYPE html>\n<html class=\"no-js\">\n  <head>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" href=\"doctest.css\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <title>Doctest.js: The Reference</title>\n    <meta name=\"description\" content=\"Doctest.js is a Javascript testing framework\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/normalize.min.css\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/main.css\">\n    <link rel=\"stylesheet\" href=\".resources/doc.css\">\n    <script src=\".resources/boilerplate/js/vendor/modernizr-2.6.1.min.js\"></script>\n    <script src=\"doctest.js\"></script>\n    <!-- EXTRA_HEAD -->\n<script type=\"text/javascript\" src=\"./.resources/toc.js\"></script>\n<!-- /EXTRA_HEAD -->\n  </head>\n  <body class=\"autodoctest\">\n\n    <div class=\"header-container\">\n      <header class=\"wrapper clearfix\">\n        <h1 class=\"title\"><a href=\"/\">Doctest.js</a>: <!-- TITLE -->The Reference<!-- /TITLE --></h1>\n\n        <nav>\n          <ul>\n            <li><a href=\"https://github.com/ianb/doctestjs\">Github</a></li>\n            <li><a href=\"/reference.html\">Reference</a></li>\n            <li><a href=\"/tutorial.html\">Tutorial</a></li>\n          </ul>\n        </nav>\n\n      </header>\n    </div>\n\n    <div class=\"main-container\">\n      <div class=\"main wrapper clearfix\">\n\n\n     <!-- BODY -->\n\n\n<p>\nAuthor: Ian Bicking,\n<a href=\"mailto:ian@ianbicking.org\">ian@ianbicking.org</a>\n</p>\n\n<div id=\"contents\"></div>\n\n<h3 id=\"html\">HTML page</h3>\n\n<p>Your HTML page needs just a couple things to set it up for a test:\n\n<pre>\n&lt;html>\n &lt;head>\n  &lt;script src=\"doctestjs/doctest.js\">&lt;/script>\n  &lt;link href=\"doctestjs/doctest.css\" rel=\"stylesheet\">\n &lt;/head>\n &lt;body class=\"autodoctest\">\n\n  &lt;pre class=\"test / doctest\">\n    test\n  &lt;/pre>\n &lt;/body>\n&lt;/html>\n</pre>\n\n</p>\n\n<p>Notably you need <code>&lt;body <strong>class=\"autodoctest\"</strong>></code> to get the tests to run automatically on page load.  If you were invoking doctest explicitly (like is done on the <a href=\"try.html\">Try It</a> page) then you might leave this off.</p>\n\n<h4 id=\"external\">External code</h4>\n\n<p>Often you won't want to write your test code inside the test itself.  Instead you'll want to put it in its own <code>.js</code> file.  Especially with <a href=\"#format-test\"><code>test</code></a> the code is valid Javascript, and you will probably want syntax highlighting and all that.</p>\n\n<p>To do this, use an <code>href</code> attribtue on your <code>&lt;pre></code> element, like:\n\n<pre>\n&lt;pre class=\"test\" href=\"./tests.js\">&lt;/pre>\n</pre>\n\nThe contents of the element don't matter.  The test will be loaded from that location (which could be a full URL but you'll probably have <a href=\"http://www.w3.org/TR/cors/\">cross-origin</a> errors if you tried that &mdash; this doesn't use <code>&lt;script></code> tags to load those scripts, it uses XMLHttpRequest).  Note that the class is still required!</p>\n\n<p>You can also load it from a variable location, using query string parameters to find the file.  The most common pattern would be like this:\n\n<pre>\n&lt;pre class=\"test\" data-href-pattern=\"./{test-name|default.js}\">&lt;/pre>\n</pre>\n\nAny URL parameters (like <code>{test-name}</code>) get filled in by the query string (<code>?test-name=example.js</code>).  By default these values can only contain letters, numbers, <code>_</code>, <code>-</code> and <code>.</code> &mdash; this is to protect against loading scripts from unexpected locations via an implicitly unsafe parameters in the query string.</p>\n\n<p>If you want to use a different restriction on a variable name, use <code>{variable-name:regular_expression}</code> &mdash; and use <code>^</code> and <code>$</code> to make sure to match the entire string.</p>\n\n<p>If you want a default (if the parameter isn't set or is empty) use <code>|</code> to separate out the default.  The default should come after the regular expression.  In the example the default is <code>default.js</code>.  Don't use extra spaces around <code>|</code>!</p>\n\n<p>Note this works well with relative addresses like <code>&lt;a href=\"?test-name=foo.js\">foo.js&lt;/a></code></p>\n\n<h3 id=\"format\">Format of test</h3>\n\n<p>There are two formats that a doctest can take.  You've probably seen the <code>test</code> format, there is also the more traditional <code>doctest</code> format.</p>\n\n<h4 id=\"format-doctest\"><code>doctest</code> format</h4>\n\n<p>This format is used like:\n\n<pre>\n&lt;pre class=\"doctest\">\n$ first_line();\n> continuation line\noutput\n&lt;/pre>\n</pre>\n\n</p>\n\n<p>The first line of course starts wtih <code>$</code> and a space. Think of it like a Unix command line.  And also similar to a command line shell the continuation line is <code>></code>.  Any line <em>without</em> a leading <code>$</code> or <code>></code> is considered expected output.</p>\n\n<p>Note you can still have multiple statements using a continuation line.  The only difference between two lines with <code>$</code> and one with a <code>$</code> followed by <code>></code> is that in the latter case the two lines are executed <em>together</em> and the output from both is combined into what is expected.</p>\n\n<h4 id=\"format-test\"><code>test</code> format</h4>\n\n<p>In this format the expected output is in a comment, like:\n\n<pre>\n&lt;pre class=\"test\">\nstatement_1();\nstatement_2();\n// Some other comment\n// => expected output\n\nMore statements\n\n/* =>\nexpected output\n*/\n</pre>\n\n</p>\n\n<p>Basically the test is split up by using the <code>// =></code> comments.  Each chunk is executed independently, and the test may be paused at the point where the expected output is found.</p>\n\n<h4 id=\"sections\">Test sections</h4>\n\n<p><em>If</em> you are using <a href=\"#external\">external test code</a> (and <code>test</code>) you can include <em>section headers</em> like:\n\n<pre>\n// == SECTION A section header\n</pre>\n\n</p>\n\n<p>You can have one or more <code>=</code>'s.  The text <code>A section header</code> will become a header.  Each section header turns into a new <code>&lt;pre></code> element.</p>\n\n<h4 id=\"compact\">Compact <code>&lt;pre></code>'s</h4>\n\n<p>Sometimes you'll have boilerplate code that sets up the test environment, and you'll be uninterested in that code (unless it fails).  This might define helper functions, or run some really routine sanity tests.  You can use this to make those test blocks small:\n\n<pre>\n&lt;pre class=\"test expand-on-failure\">\n  ...\n&lt;/pre>\n</pre>\n\nThis will make the test 3em tall unless there's a failure, at which point it expands to its full size.</p>\n\n<h3 id=\"print\">Printing/writing</h3>\n\n<p>The <code>print()</code> function is pretty important, of course. (Note it also was called <code>writeln()</code>, a name which is still supported).</p>\n\n<p><code>print()</code> will print out any strings given to it, and the <code>repr()</code> of any other objects, with a space between each argument.</p>\n\n<p>You can make a <strong>custom <code>repr()</code></strong> for any object by adding a <code>.repr()</code> method.  It should look like:\n\n<pre>\nMyObject.prototype.repr = function () {\n  return '[MyObject attr: ' + repr(this.attr) + ']';\n};\n</pre>\n\n</p>\n\n<p>If you can't add a method to your object, you can also add a stringifier using <code>repr.register()</code>.</p>\n\n<p>You might do this like:\n\n<pre>\nrepr.register(\n  function (o) {\n    return o instanceof MyClass;\n  },\n  function (o, indentString) {\n    return '[MyClass attr: ' + repr(o.attr) + ']';\n  }\n);\n</pre>\n\nThe first function is a <em>test</em> that is applied to objects.  If it returns true, then the second function is called to stringify the object.  <em>If</em> your representation uses multiple lines, then you should indent subsequent lines with the string, like <code>return '[Beginning\\n' + indentString + '  end\\n' + indentString + ']';</code>.  The beginning is never indented.\n\n</p>\n\n<p>Some of the objects that have custom representations:</p>\n\n<dl>\n  <dt>XML and DOM objects</dt>\n  <dd>These are displayed as the normal serialization, e.g., <code>&lt;input type=\"text\" /></code>.  XML-style endings for empty tags are always used.  Attributes are alphabetized.  HTML tags are upppercase and attributes are lowercase, because the DOM seems to like that.</dd>\n\n  <dt>XMLHttpRequest</dt>\n  <dd>These are displayed like <code>[XMLHttpRequest STATE [STATUS]]</code>.  The <code>STATE</code> is one of <code>UNSENT</code>, <code>OPENED</code>, <code>HEADERS_RECEIVED</code>, <code>LOADING</code> and <code>DONE</code>.  The <code>[STATUS]</code> is only displayed if the request has finished.</dd>\n\n</dl>\n\n<p>Arrays and objects are displayed like you'd think.  This might include objects that you might not think of as \"plain\" objects.  Also the object prototype is not displayed.  You'll have to use something like <code>print(o.constructor)</code> if you want to be specific about classes.</p>\n\n<h4 id=\"console\"><code>console.log()</code></h3>\n\n<p><code>console.log()</code> works a lot like <code>print()</code>. But unlike <code>print()</code> it doesn't make a test pass or fail, it's purely informative.</p>\n\n<p>All the methods on console should work, like <code>console.warn()</code>.  The underlying normal console function is called, but in addition on a test-by-test basis these are collected and displayed.</p>\n\n<h4 id=\"printResolved\"><code>printResolved()</code> for Deferred and Promises</h4>\n\n<p>There's special support for the jQuery <a href=\"http://api.jquery.com/category/deferred-object/\">Deferred</a> object, and generally <a href=\"http://wiki.commonjs.org/wiki/Promises/A\">Promises/A</a>.</p>\n\n<p>This support is through the <code>printResolved()</code> function, which is basically equivalent to <code>print()</code> except any promise arguments will be waited on to resolve (proper resolution or an error).  You can use it like this:</p>\n\n<pre class=\"test\">\nvar def = $.Deferred();\nsetTimeout(function () {\n  def.resolve(\"Resolved!\");\n});\nprintResolved(def);\n// => Resolved!\n</pre>\n\n<p>Errors are printed out with <code>Error:</code> before the value, and multiple arguments are printed out with spaces between them, or a placeholder if there's no arguments.  For instance:</p>\n\n<pre class=\"test\">\nvar def = $.Deferred();\ndef.reject({code: 1}, \"a message\");\nprintResolved(def);\n// => Error: {code: 1} a message\n// Or you might not have any value at all:\ndef = $.Deferred();\ndef.resolve();\nprintResolved(def);\n// => (resolved)\n</pre>\n\n<h3 id=\"matching\">Output matching</h3>\n\n<p>The <em>expected</em> output is compared with the output you actually <em>got</em> (received).</p>\n\n<p>First all whitespace is normalized.  Empty lines are removed from both sides.  Leading spaces are removed (i.e., indentation does not matter).  Multiple spaces are normalized to a single space.</p>\n\n<p>There are two wildcard patterns.  Ellipsis &mdash; <code>...</code> &mdash; means \"match anything\".  This will match zero character, or multiple lines.  You should be careful about matching <em>too</em> much.</p>\n\n<p>The shorter wildcard is <code>?</code>.  This matches letters, numbers, underscore, period, and question mark.  Note if you want to match a string with such characters you might have to use <code>\"?\"</code>.</p>\n\n<p>Also a special case, <code>&quot;</code> matches <code>'</code> and vice versa.  Since in most contexts these mean the same thing, this lets you be agnostic.</p>\n\n<p>When you have a large expected text and got a lot of text, and that text differs just a bit, you'll see a line-by-line comparison of the two, to help you identify exactly where the problem is.  Note if you use wildcards the line-by-line comparison might be very inaccurate.</p>\n\n<h3 id=\"wait\"><code>wait()</code>, async code, and pausing the tests</h3>\n\n<p>Often you'll want to let code run for a while on its own before you are done with testing a section of code.  I.e., you want to let all the requests complete, DOM elements update, and so forth.</p>\n\n<p>Each <em>section</em> of code can be paused at the end. <strong>Code cannot be paused in the middle of a section.</strong>  So before the output (i.e., before <code>// =></code>) the test runner can wait and collect output.<p>\n\n<p>Anytime you call <code>wait()</code> inside a section of code it tells the test runner to wait <em>at the end of the test</em>, either until some condition is true or until some time has passed.  If the condition doesn't complete an error/timeout message is <code>print()</code>'d.</p>\n\n<p>A half baked version of what happens is this:\n\n<pre>\nvar printed = [], waiting = null;\nfunction print(arg) {\n  printed.push(arg);\n}\nfunction wait(condition) {\n  waiting = condition;\n}\nfunction checkOutput() {\n  if (printed.join('\\n') != expectedOutput) {\n     fail();\n  }\n}\neval(exampleCode);\nhardTimeout = 5000; // 5 seconds\ncheckTime = 100; // check every 0.1 seconds\nif (waiting === null) {\n  checkOutput();\n} else if (typeof waiting == \"number\") {\n  setTimeout(checkOutput, waiting);\n} else {\n  var now = Date.now();\n  function checker() {\n    if (waiting()) {\n      checkOutput();\n    } else if (Date.now() - now > hardTimeout) {\n      print(\"Error: timed out\");\n      checkOutput();\n    } else {\n      setTimeout(checker, hardTimeout);\n    }\n  }\n  setTimeout(checker, 0);\n}\n</pre>\n\nNow you practically know how to write doctest yourself!\n</p>\n\n<p>Specifically this is how you can run <code>wait()</code>:</p>\n\n<dl>\n  <dt><code>wait()</code></dt>\n  <dd>This makes the test pause just for a moment.  It's the same as <code>wait(0)</code>.</dd>\n\n  <dt><code>wait(milliseconds)</code></dt>\n  <dd>This forces the test to pause for the given number of milliseconds.  Everything is always in milliseconds.</dd>\n\n  <dt><code>wait(condition)</code></dt>\n  <dd>This calls <code>condition()</code> frequently until it returns true.</dd>\n\n  <dt><code>wait(condition, timeout)</code></dt>\n  <dd>This calls condition up until <code>timeout</code> milliseconds. You can use this to extend the timeout.  The default timeout is 5 seconds (5000).</dd>\n</dl>\n\n<h3 id=\"spy\">Spy, mocking, and watching functions</h3>\n\n<p><code>Spy</code> is used to create a mock object/function that can be used to track calls and inspect call order and arguments.</p>\n\n<p>The basic use is like this:\n\n<pre class=\"test\">\nfunc = Spy('func');\nfunc(1, 2, 3);\n\nobj = {a: 1, func: func};\nobj.func();\n\n/* =>\nfunc(1, 2, 3)\n{a: 1, func: Spy('func')}.func()\n*/\n</pre>\n\n</p>\n\n<p>That is, every time the Spy is called it will print out the call, all its arguments, and if there was a bound <code>this</code> (as in the <code>obj.func()</code> example) then that value will be displayed as well.</p>\n\n<p>Each spy is <em>named</em>, and if you call <code>Spy(name)</code> with a name that has been used before you will get the same Spy object back.</p>\n\n<p><code>Spy</code> can be invoked in a couple ways:</p>\n\n<dl>\n  <dt><code>Spy(name)</code></dt>\n  <dd>Just creates/gets the Spy with the given name.</dd>\n\n  <dt><code>Spy(name, {options})</code></dt>\n  <dd>Create the Spy with some options (as described below)</dd>\n\n  <dt><code>Spy(name, function () {...})</code></dt>\n  <dd>Creates a Spy that wraps another function that you provide.  The Spy will be called first, and will print out the call, and then it will call the sub-function with the same arguments and <code>this</code>.</dd>\n\n  <dt><code>Spy(name, function () {...}, {options})</code></dt>\n  <dd>Create a Spy that wraps a function and has extra options.</dd>\n\n</dl>\n\n<p>Note that your function can raise an exception, and the Spy will pass it through (though also note the exception using <code>console.log()</code>).  You can use this to inspect how a library reacts to exceptions in callbacks.</p>\n\n<h4 id=\"spy-options\">Spy options</h4>\n\n<p>The options available:</p>\n\n<dl>\n  <dt><code>applies: function () {...}</code></dt>\n  <dd>This is the function that will be called when the Spy is called. It's the same as passing in the function as the second argument.</dd>\n\n  <dt><code>writes: false</code> (default <code>true</code>)</dt>\n  <dd>If this is false (default true) then it will <em>not</em> print out the call.</dd>\n\n  <dt><code>returns: value</code> (default <code>undefined</code>)</dt>\n  <dd>This is what the Spy returns when called (assuming you did not use <code>applies</code>).  By default it simply returns <code>undefined</code>, which is what a function returns when you have no explicit <code>return</code> statement.</dd>\n\n  <dt><code>throwError: exceptionObject</code></dt>\n  <dd>If given, when the Spy is called it'll do <code>throw exceptionObject</code></dd>\n\n  <dt><code>ignoreThis: true</code> (default <code>false</code>)</dt>\n  <dd>If true, then <code>this</code> won't be printed out regardless of whether it is bound.  This is useful when a library binds <code>this</code> carelessly.</dd>\n\n  <dt><code>wrapArgs: true</code> (default <code>false</code>)</dt>\n  <dd>If true then wrapping will be forced when the arguments are printed out.  Otherwise wrapping is only applied if an argument is longer than 80 columns (the default for printing generally).</dd>\n\n  <dt><code>wait: true</code> (default <code>false</code>)</dt>\n  <dd>This is equivalent to calling <code>Spy(name).wait()</code>. You can also pass in a number, which will be the millisecond timeout, e.g., <code>Spy(name, {wait: 10000})</code> to wait for 10 seconds for the Spy to be called.</dd>\n\n  <dt><code>methods: {...}</code></dt>\n  <dd>Equivalent to calling <code>Spy.methods({...})</code>.  See below for details.</dd>\n\n</dl>\n\n<p>You can also change <code>Spy.defaultOptions</code> if you want to override one option by default, for instance to turn off printing or ignore <code>this</code>.</p>\n\n<h4 id=\"spy-methods\">Spy methods</h4>\n\n<p>Several methods are available:</p>\n\n<dl>\n  <dt><code>Spy().wait([timeout])</code></dt>\n  <dd>This makes the test pause until the Spy has been called. Sometimes you <em>must</em> use the method instead of <code>Spy(name, {wait: true})</code>.  An example:\n\n    <pre>\nSomeAPI.onload = Spy('SomeAPI.onload', function (data) {\n  SomeOtherAPI.save(data, Spy('SomeOtherAPI.save'));\n};\nSpy('SomeOtherAPI.save').wait();\n/* =>\nSomeAPI.onlaod({...})\nSomeOtherAPI.save()\n*/\n</pre>\n\n    In this case the Spy is created <em>inside</em> another method, and that method is not called right away.  <code>wait: true</code> doesn't work in this case.  Instead you should call <code>Spy(name).wait()</code> later.  Since names are unique, this will be the same Spy object as referenced earlier.\n</dd>\n\n  <dt><code>Spy.on(\"obj.attr\", [applies/options])</code></dt>\n  <dd>This replaces the attribute <code>attr</code> on the object <code>obj</code> with a Spy.  The object must be defined at the top level (i.e., <code>eval(\"obj\")</code> must return the object).  This is basically the same as:\n\n<pre>\nobj = eval(\"obj\");\nspy = Spy(\"obj.attr\", [applies/options]);\nobj.attr = spy;\n</pre>\n\n</dd>\n\n  <dt><code>Spy.on(obj, \"obj.attr\", [applies/options])</code></dt>\n  <dd>This is the same as the previous form, except for use when <code>obj</code> is not a global variable.</dd>\n\n  <dt><code>aSpy.formatCall()</code></dt>\n  <dd>When the Spy is called, generally this does:\n\n    <pre>\nprint(aSpy.formatCall());\n</pre>\n\n    If you use <code>writes: false</code> then this might be helpful.\n  </dd>\n\n  <dt><code>aSpy.method(\"methodName\", [applies/options])</code></dt>\n  <dd>This creates an attribute <code>aSpy.methodName</code> and assigns a Spy to that attribute.  You may give the normal constructor arguments.</dd>\n\n  <dt><code>aSpy.methods({methodName: [true or options], ...})</code></dt>\n  <dd>This creates multiple attributes at once.  You may use <code>{methodName: true}</code> if you have no options to pass in.</dd>\n\n</dl>\n\n<h4 id=\"spy-attributes\">Spy attributes</h4>\n\n<p>Spies have several attributes to inspect how they have been called:</p>\n\n<dl>\n  <dt><code>aSpy.self</code> and <code>aSpy.selfList</code></dt>\n  <dd>This is the value of <code>this</code> as the spy was called. As the spy is called multiple times each <code>this</code> value is appended to <code>selfList</code>, forming a history.</dd>\n\n  <dt><code>aSpy.args</code> and <code>aSpy.argList</code></dt>\n  <dd>This is the list of arguments that the function was called with. <code>.argList</code> gives the history of past calls.</dd>\n\n</dl>\n\n\n<h3 id=\"abort\">Aborting your tests</h3>\n\n<p>Tests often has prerequesites.  Perhaps some browsers aren't supported.  Maybe you need a server setup.  Normally doctest will run through all the tests regardless of failures, but when basic prerequesites are missing this creates lots of chatter and failures with no purpose.</p>\n\n<p>To stop the tests from running call <code>Abort()</code>.  This will still run the rest of the test block (up until the next <code>// =></code>).</p>\n\n<h3 id=\"jshint\">jshint</h3>\n\n<p>A helper is provided to help you run <a href=\"http://www.jshint.com/\">JSHint</a> regularly on your code. Just do this:</p>\n\n<pre>\njshint(\"source-filename.js\", [jshint options]);\n</pre>\n\n<p>You can give a full URL, but you can also just give the filename. When given a filename then all the <code>&lt;script></code> tags are searched for that filename.  The source is fetched and JSHint is run on that source.</p>\n\n<p>You may <a href=\"http://www.jshint.com/docs/\">give options to suppress or enforce checks</a>.  In addition you may list the known issues that you wish to ignore: issues are printed out in order, and are matched like any other text.  You might want to use this to simply see the errors without checking them for anything in paticular:\n\n<pre>\njshint(\"source-filename\");\n// => ...\n</pre>\n\n</p>\n\n<h3 id=\"nosyxmlhttprequest\"><code>NosyXMLHttpRequest</code></h3>\n\n<p>Sometimes you may want to watch the progress of XMLHttpRequest requests &mdash; both how the request is constructed and its result. You can use <code>NosyXMLHttpRequest</code> to wrap request objects.</p>\n\n<p>You probably want to use it like:\n\n<pre>\nXMLHttpRequest = NosyXMLHttpRequest.factory(\"request\");\n</pre>\n</p>\n\n<p>The name will be used when showing output (e.g., <code>request.setRequestHeader('X-Something', 'value')</code>).</p>\n\n\n<h3 id=\"node\">Node.js</h3>\n\n<p>Doctest.js has some Node support.  You must use the <a href=\"#format-test\">comment-based test format</a> in stand-alone Javascript files.  Then:</p>\n\n<pre>\n$ npm install -g doctestjs\n$ doctest test.js\n</pre>\n\n<p>This will print a success or failure message, and will exit with a code (the number of failures) if the test does not pass.</p>\n\n<p>If you do not wish to install the package globally, do:</p>\n\n<pre>\n$ npm install doctestjs\n$ node_modules/.bin/doctest test.js\n</pre>\n\n\n\n<div style=\"display: none\">\n  <!-- This is where the summary goes, which we basically want to hide\n       on this page: -->\n  <div id=\"doctest-output\"></div>\n</div>\n\n\n\n\n\n\n\n<!-- /BODY -->\n\n      </div> <!-- #main -->\n\n    </div> <!-- #main-container -->\n\n    <div class=\"footer-container\">\n      <footer class=\"wrapper\">\n        <h3 class=\"no-toc\">doctest.js is by <a href=\"http://ianbicking.org\">Ian Bicking</a>.\n          It's on <a href=\"https://github.com/ianb/doctestjs\">github</a>!</h3>\n      </footer>\n    </div>\n\n<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js\"></script>\n<script>\nwindow.jQuery || document.write('<script src=\".resources/boilerplate/js/vendor/jquery-1.8.1.min.js\"><\\/script>')\n</script>\n\n<script src=\".resources/boilerplate/js/main.js\"></script>\n\n<script type=\"text/javascript\">\n\n  var _gaq = _gaq || [];\n  _gaq.push(['_setAccount', 'UA-34921728-1']);\n  _gaq.push(['_trackPageview']);\n\n  (function() {\n    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n  })();\n\n</script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/try.html",
    "content": "<!DOCTYPE html>\n<html class=\"no-js\">\n  <head>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" href=\"doctest.css\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <title>Doctest.js: Try It!</title>\n    <meta name=\"description\" content=\"Doctest.js is a Javascript testing framework\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/normalize.min.css\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/main.css\">\n    <link rel=\"stylesheet\" href=\".resources/doc.css\">\n    <script src=\".resources/boilerplate/js/vendor/modernizr-2.6.1.min.js\"></script>\n    <script src=\"doctest.js\"></script>\n    <!-- EXTRA_HEAD -->\n<style>\n#display {\n  width: 100%;\n}\n\n#editor {\n  width: 100%;\n  height: 15em;\n}\ntable#layout {\n  width: 100%;\n}\ntable#layout td {\n  vertical-align: top;\n  padding: 1em;\n}\ntable#layout pre.test {\n  margin-top: 0;\n}\n#doctest-output {\n  height: 4em;\n  margin-top: -0.3em;\n}\n</style>\n<script src=\".resources/try.js\"></script>\n<!-- /EXTRA_HEAD -->\n  </head>\n  <body class=\"autodoctest\">\n\n    <div class=\"header-container\">\n      <header class=\"wrapper clearfix\">\n        <h1 class=\"title\"><a href=\"/\">Doctest.js</a>: <!-- TITLE -->Try It!<!-- /TITLE --></h1>\n\n        <nav>\n          <ul>\n            <li><a href=\"https://github.com/ianb/doctestjs\">Github</a></li>\n            <li><a href=\"/reference.html\">Reference</a></li>\n            <li><a href=\"/tutorial.html\">Tutorial</a></li>\n          </ul>\n        </nav>\n\n      </header>\n    </div>\n\n    <div class=\"main-container\">\n      <div class=\"main wrapper clearfix\">\n\n\n     <!-- BODY -->\n\n<div id=\"doctest-output\"></div>\n\n<table id=\"layout\">\n  <tr>\n    <td style=\"width: 50%\">\n      <textarea id=\"editor\" style=\"width: 100%; height: 10em\">// Put your tests here\nfunction factorial(n) {\n  return n <= 0 ? 1 : n * factorial(n-1);\n}\n\nprint(factorial(3));\n// => 10\n</textarea>\n      <br>\n      <button id=\"testit\" type=\"button\">Test!</button>\n    </td>\n    <td>\n      <div id=\"display\">\n        <pre id=\"test-location\"></pre>\n      </div>\n    </td>\n  </tr>\n</table>\n\n<!-- /BODY -->\n\n      </div> <!-- #main -->\n\n    </div> <!-- #main-container -->\n\n    <div class=\"footer-container\">\n      <footer class=\"wrapper\">\n        <h3 class=\"no-toc\">doctest.js is by <a href=\"http://ianbicking.org\">Ian Bicking</a>.\n          It's on <a href=\"https://github.com/ianb/doctestjs\">github</a>!</h3>\n      </footer>\n    </div>\n\n<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js\"></script>\n<script>\nwindow.jQuery || document.write('<script src=\".resources/boilerplate/js/vendor/jquery-1.8.1.min.js\"><\\/script>')\n</script>\n\n<script src=\".resources/boilerplate/js/main.js\"></script>\n\n<script type=\"text/javascript\">\n\n  var _gaq = _gaq || [];\n  _gaq.push(['_setAccount', 'UA-34921728-1']);\n  _gaq.push(['_trackPageview']);\n\n  (function() {\n    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n  })();\n\n</script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/doctestjs/tutorial.html",
    "content": "<!DOCTYPE html>\n<html class=\"no-js\">\n  <head>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" href=\"doctest.css\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <title>A doctest.js tutorial</title>\n    <meta name=\"description\" content=\"An introduction to the Javascript testing framework, doctest.js\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/normalize.min.css\">\n    <link rel=\"stylesheet\" href=\".resources/boilerplate/css/main.css\">\n    <link rel=\"stylesheet\" href=\".resources/doc.css\">\n    <script src=\".resources/boilerplate/js/vendor/modernizr-2.6.1.min.js\"></script>\n    <script src=\"doctest.js\"></script>\n    <!-- EXTRA_HEAD -->\n      <script type=\"text/javascript\" src=\"./.resources/toc.js\"></script>\n      <!-- /EXTRA_HEAD -->\n  </head>\n  <body class=\"autodoctest\">\n\n    <div class=\"header-container\">\n      <header class=\"wrapper clearfix\">\n        <h1 class=\"title\"><a href=\"/\">Doctest.js</a>: <!-- TITLE -->A Tutorial <!-- /TITLE --></h1>\n\n        <nav>\n          <ul>\n            <li><a href=\"https://github.com/ianb/doctestjs\">Github</a></li>\n            <li><a href=\"/reference.html\">Reference</a></li>\n            <li><a href=\"/tutorial.html\">Tutorial</a></li>\n          </ul>\n        </nav>\n\n      </header>\n    </div>\n\n    <div class=\"main-container\">\n      <div class=\"main wrapper clearfix\">\n\n\n     <!-- BODY -->\n\n\n<aside>\n  <h3>Try it now!</h3>\n\n  <p>If you want to try writing/running your own tests (maybe as you read the tutorial) try the <strong><a href=\"try.html\">live demo</a></strong>.\n    </p>\n</aside>\n\n<div id=\"contents\"></div>\n\n          <article>\n            <section id=\"introduction\">\n              <header>\n                <h1 id=\"intro\">What's it like?</h1>\n              </header>\n\n<p>\n\nSo you've decided to finally get religion when it comes to testing your Javascript code?  Or, you feel like testing just isn't as easy as it could be, and want to find a better way to test your Javascript code?  Or even: you've thought about or tried doing Test Driven Development but you've found it hard to get going? Let's do this...\n\n</p>\n\n<p>\n\nDoctest.js is basically <em>example code</em> and then <em>expected output</em>.  This is really what most tests look like, but instead of lots of <code>assertEqual(example, expected)</code> this example/expected combination is embedded into the structure of the test.\n\n</p>\n\n<aside>\n  <h3 id=\"page-setup\">Page Setup</h3>\n\n  <p>\n    See <a href=\"#html\">Setting Up Your HTML</a> to see how to get your test running in the browser.\n  </p>\n</aside>\n\n<p>\n\nI'm going to get right into how the test code looks, but to actually <em>use</em> doctest.js you have to setup an HTML file in a specific format.  That is described later in the <a href=\"#html\">HTML section</a>.\n\n</p>\n\n<p>\n\nThe structure looks like something you've probably seen before.  We add one new function, <code>print()</code>, that works a lot like <code>console.log()</code>.  Then we have a comment that shows what we expect to be output.  A really simple example:\n\n    <pre class=\"test\">\nfunction factorial(n) {\n  if (typeof n != \"number\") {\n    throw \"You must give a number\";\n  }\n  if (n <= 0) {\n    return 1;\n  }\n  return n * factorial(n-1);\n}\n\nprint(factorial(4))\n// => 25\n    </pre>\n\n</p>\n\n<p>\n\nSee what I did there?  25 is totally the wrong answer!  Also see what happened, the test just ran and told us so!  There's also a summary of all the tests; if you do nothing it shows up at the top of the page, but in the interest of introducing the summary, here it is:\n\n</p>\n\n<p id=\"doctest-output\" style=\"border: 1px solid #999\"></p>\n\n<p>\n\nYou'll notice it shows a failure (or more than one &mdash; it's the summary for all the examples in this tutorial).  It also has a link to each failure, so you can jump to the problematic section.\n\n</p>\n\n<aside>\n  <h3 id=\"quoting\">Quoting</h3>\n\n  <p>\n    If you are writing your tests inline in the document, remember that you don't need to quote <code>></code> as <code>&amp;gt;</code>, that's only needed for <code>&lt;</code>\n  </p>\n</aside>\n\n<p>\n\nLet's look at what we did there: <code>print(factorial(4))</code> and <code>// => 25</code> &mdash; the output is just a comment that starts with <code>=></code>.\n\n</p>\n\n</section>\n\n<section id=\"errors\">\n  <header>\n    <h3 id=\"errors\">Testing for error conditions</h3>\n  </header>\n\n<p>\n\nYou can also test errors:\n\n<pre class=\"test\">\nprint(factorial(null));\n// => Error: You must give a number\n</pre>\n\nWhen an exception is thrown it will print out <code>Error: (error text)</code> which you can match against. This way you can test for error conditions just like you test how \"correct\" invocations work.  Note that the <code>print()</code> isn't really necessary here, you could do this just as well:\n\n<pre class=\"test\">\nfactorial(null);\n// => Error: You must give a number\n</pre>\n\n</p>\n\n</section>\n\n<section id=\"print\">\n  <header>\n    <h3 id=\"print\"><code>print()</code> and output matching</h3>\n  </header>\n\n<aside>\n  <p>For more detail on printing see <a href=\"reference.html#print\">the reference</a>.</p>\n</aside>\n\n<p>\n\n<code>print()</code> pretty-prints things.  This is important, because you have to \"expect\" the same output that <code>print()</code> produces.  You can give multiple arguments, like with <code>console.log</code>.\n\n<pre class=\"test\">\nprint({someProperty: 123, something: {a: 1, b: 2}, \"foo\": 123.1032, \"another-property\": [1,2,3,4]});\n/* =>\n{\n  \"another-property\": [1, 2, 3, 4],\n  foo: 123.1032,\n  someProperty: 123,\n  something: {a: 1, b: 2}\n}\n*/\n</pre>\n\nYou might notice that the attributes are alphabetized and are quoted only when necessary.  If it's a small object it stays on one line:\n\n<pre class=\"test\">\nprint({someProperty: 123});\n// => {someProperty: 123}\n</pre>\n\n</p>\n\n<p>\n\nBut sometimes the output is unpredictable; or rather you can predict it will change.  When that's the case you can basically put a wildcard in the expected output: <code>...</code> &mdash; that will match anything, including multiple lines.  In addition you can use <code>?</code> to match one word-like-thing (a number, symbol, etc; not <code>&quot;</code> or whitespace or other symbols).  You can use it like this:\n\n<pre class=\"test\">\nprint({\n  date: new Date(),\n  timestamp: Date.now()\n});\n\n// => {date: ..., timestamp: ?}\n</pre>\n\n</p>\n\n<p>\n\nYou might notice that it <em>passes</em>, but you still get to see the actual output.  This is a great way to show information that you can review, without actually testing.  For instance, you might be testing something that connects to a server, in that case you might want to do this:\n\n<pre class=\"test\">\nvar server = {url: \"http://localhost:8000\"} // or some calculated value\nprint(server.url);\n// => ...\n</pre>\n\nNow if everything seems breaky you can be 100% sure of what server you are connecting to.\n\n</p>\n\n<p>\n\nIf you have a variable that is dynamic but you still care about the value, you should do something like this:\n\n<pre class=\"test\">\nvar date = Date.now();\nprint(date == date, date);\n// => true ...\n</pre>\n\nThink of this pattern of <code>print(x == y)</code> as a kind of <code>assertEqual()</code> equivalent.\n\n</p>\n\n</section>\n\n<section id=\"async\">\n  <header>\n    <h3 id=\"async\">Testing async code</h3>\n  </header>\n\n<aside>\n  <p>For more on async and <code>wait</code> see <a href=\"reference.html#wait\">the reference</a>.</p>\n</aside>\n\n<p>\n\nThis is all well and good, but lots of code in Javascript is <em>asynchronous</em>, meaning that you don't just call a function that returns a value.  Doctest.js has an answer to that too: a great answer!\n\n</p>\n\n<p>\n\nFor our example we'll use <code>XMLHttpRequest</code>, a common source of asynchronosity.  We'll test a request (just a loopback request, but if you are testing a foreign service you'd need <a href=\"http://enable-cors.org/\">CORS access</a>).  When we instantiate and setup the request we don't have anything really to test &mdash; we want to test what happens when the request <em>completes</em>.\n\n</p>\n\n<p>\n\nTo do this we'll use <code>wait()</code> &mdash; when this function is called the test runner will wait at the point where it sees <code>// =></code>, for a certain amount of time or until a certain condition is met. Only then will it compare all the output that has happened to what was expected, and run the next chunk of test.\n\n</p>\n\n<p>\n\nYou can use this like: <code>wait(function () {return true when done})</code> or <code>wait(millisecondsToWait)</code>.  We'll use the first form, which is almost always better, since it allows the test to continue more quickly.  Tests also always time out eventually (by default the timeout is 5000 milliseconds, i.e., 5 seconds &mdash; by convention everything in Javascript is in milliseconds).\n\n<pre class=\"test\">\nvar endpoint = location.href;\nprint(endpoint);\n// => ...\n\nvar req = new XMLHttpRequest();\nreq.open(\"GET\", endpoint);\nreq.onreadystatechange = function () {\n  if (req.readyState != 4) {\n    // hasn't actually finished\n    return;\n  }\n  print(\"Result:\", req.status, req.getResponseHeader('content-type'));\n};\nreq.send();\n\nwait(function () {return req.readyState == 4;});\n\nprint(\"Current state:\", req.readyState);\n\n/* =>\nCurrent state: 1\nResult: 200 text/html\n*/\n</pre>\n\nI put in something tricky there to try to clarify what <code>wait()</code> really does.  You'll notice there's a call to <code>wait()</code> that makes sure that <code>req.readyState == 4</code> (that's the code that means the request is finished).  But right after when we do <code>print(req.readyState)</code> it shows a readyState of 1.  That's because the <em>entire</em> block is printed (from the previous <code>// =></code> output up until the next one).  But the test runner keeps collecting output and doesn't run the next section until that <code>wait()</code> clause returns true.\n\n</p>\n\n<p>\n\nAnother thing to note is that <code>wait()</code> needs to be called when that block of code is run &mdash; it can't be inside a function that isn't called.  That said, if you write test helper functions (and you should!), it often works well to put those calls in the helper function.  We'll see an example of that next...\n\n</p>\n\n</section>\n\n<section id=\"spy\">\n  <header>\n    <h3 id=\"spy\">The Spy</h3>\n  </header>\n\n<aside>\n  <p>For more information on <code>Spy</code> see <a href=\"reference.html#spy\">the reference</a>.</p>\n</aside>\n\n<p>\n\nNote: the next example will use some jQuery, just for the heck of it, though there is no special support for jQuery or other frameworks in Doctest.\n\n</p>\n\n<p>\n\nIf you use these tools you might end up writing code like this quite a lot:\n\n<pre class=\"test\">\n// We've embedded a button just below this element\nvar button = $('#example-button');\n// Just to highlight what we're working with:\nbutton.css({border: '1px dotted #f00'});\nbutton.click(function () {\n  print('Button clicked');\n});\n\n// Now we test that our event handler gets called when we do an artificial click of the button:\nbutton.click();\n// => Button clicked\n</pre>\n\n<button id=\"example-button\" type=\"button\">Example Button</button>\n\n</p>\n\n<p>\n\nBut maybe we are curious about the arguments passed to that handler &mdash; even though we ignored the arguments, there was one passed.  And we might want to show what <code>this</code> is bound to; <code>this</code> is kind of like an invisible extra argument passed to every function invocation.  We could make a fancier <code>print()</code> statement there.  But instead, there's also a handy tool for tracking calls: <code>Spy</code>.\n\n</p>\n\n<p>\n\nAn example:\n\n<pre class=\"test\">\nvar button = $('#example-button2');\nbutton.css({border: '1px dotted #00f'});\nbutton.click(Spy('button.click'));\nbutton.click();\n\n// => ...\n</pre>\n\n<button id=\"example-button2\" type=\"button\">Example Button 2</button>\n\n</p>\n\n<p>\n\nThat's a lot more information!  Let's break it down:\n\n<pre>\n<b style=\"color: #00a\">&lt;button id=\"example-button2\" style=\"border: 1px solid rgb(0, 0, 255); \" type=\"button\">Example Button 2&lt;/button>.</b><span style=\"color: #0a0\">button.click</span>({ ...\n</pre>\n\nThere's two bits of information here.  The first is the value (in <span style=\"color: #00a\">blue</span>) of <code>this</code>, which is the <code>#example-button2</code> element.  You'll notice it shows the HTML of the element.  If you want Spy to ignore this you can use <code>Spy('button.click', {ignoreThis: true})</code>.\n\n</p>\n\n<p>\n\nThe second value (in <span style=\"color: #0a0\">green</span>) is the name we gave the Spy when we created it. Note that Spy names are also identifiers, that is, <code>Spy('button.click') === Spy('button.click')</code>.\n\n</p>\n\n<p>\n\nNext of course is all the arguments.  There's a lot of arguments there.  They are... interesting.  You'll notice some references to <code>...recursive...</code> which is what you get when you have self-referencing data structures.  But maybe you want to test just a little of that structure without testing all of it.  You might do something like this:\n\n<pre class=\"test\">\n// Spy('button.click') fetches the same Spy we were using before, which still has all its call information\n// .formatCall() shows the way the Spy was last called.\nprint(Spy('button.click').formatCall());\n\n/* =>\n&lt;button...&lt;/button>.button.click({\n  currentTarget: &lt;button...\n  ...\n  timeStamp: ?,\n  type: \"click\"\n})\n*/\n\n</pre>\n\nSo we've tested that the <code>type</code> is click, that it has a timeStamp (though not the value) and that the <code>currentTarget</code> is a button (presumably the button we bound it to).  We still get to <em>see</em> all the other information, we just aren't <em>testing</em> it.  This can be helpful in the future when you realize there's more you want to test &mdash; you can look at the test output and transcribe more into the test.  Or when something fails later you might want to inspect that output to make sure everything is what you expect (and when you see something unexpected that's also a great time to expand your test).\n\n</p>\n\n<p>\n\nSpies have a bunch of options, and act as a kind of mock object as well.  You can pass in options as the second argument, like <code>Spy('name', {options...})</code>.  Some highlights:\n\n\n<dl>\n  <dt><code>applies</code></dt>\n  <dd>This is a function that the Spy \"wraps\".  So if you do <code>Spy('click', {applies: function (event) {this.remove(); return false;}})</code> then you'll get the same output printed, but you'll also run <code>this.remove()</code>.</dd>\n\n  <dt><code>writes</code></dt>\n  <dd>If you set this to <code>false</code> then it won't automatically print out the calls.  The values of the calls will still be recorded, and you can use <code>aSpy.formatCall()</code> to see them.</dd>\n\n  <dt><code>ignoreThis</code></dt>\n  <dd><p>Lots of code binds <code>this</code> without intending too.  It's really easy in Javascript to do this.  For instance, if you do <code>handlers[i]()</code> then <code>this</code> will be <code>handlers</code>.  (Instead you might do <code>var handler = handlers[i]; handler()</code>)</p>\n\n    <p>Anyway, sometimes you don't care about <code>this</code>, and using <code>{ignoreThis: true}</code> lets you do that.\n  </p></dd>\n\n  <dt><code>returns</code></dt>\n  <dd>If you want the Spy to return a value when its called, give the value here.  Normally it returns <code>undefined</code>.</dd>\n\n  <dt><code>throwError</code></dt>\n  <dd>This makes the Spy throw the given error anytime it is called.</dd>\n\n  <dt><code>wait</code></dt>\n  <dd>If you use <code>Spy('name', {wait: true})</code> then the test will wait until the Spy has been called. This is a pretty common pattern.  It's basically the same as <code>Spy('name').wait()</code>.</dd>\n\n</dl>\n\n</p>\n\n<p>\n\nYou can set values like <code>Spy.defaultOptions.writes = false</code> if you want to set one of these by default.\n\n</p>\n\n<p>\n\nIf you want to inspect how the Spy has been called, you can check a few attributes:\n\n<dl>\n\n  <dt><code>.called</code></dt>\n  <dd>True once this Spy has been called.</dd>\n\n  <dt><code>.self</code> and <code>.selfList</code></dt>\n  <dd>This is the value of <code>this</code>, or <code>.selfList</code> contains a history for each call.</dd>\n\n  <dt><code>.args</code> and <code>.argList</code></dt>\n  <dd>The arguments the function was called with, or <code>.argList</code> is a history of arguments.</dd>\n\n</dl>\n\n</p>\n\n</section>\n\n<section id=\"console\">\n  <header>\n    <h3 id=\"console-log\">console.log</h3>\n  </header>\n\n<p>\n\nThis isn't a feature you have to <em>do</em> anything about, it's just there for you, so I'm just going to point it out.\n\n</p>\n\n<p>\n\nWhen you use <code>console.log</code> (or any of its friends, like <code>console.warn</code>) those messages will be captured (in addition to going to the log as normal), and the output will be shown in the specific test where they happened.  A quick example:\n\n<pre class=\"test\">\nfunction enumProps(object) {\n  console.log('obj', object);\n  var result = {}\n  for (var attr in object) {\n    if (typeof object[attr] == \"number\" && attr.toUpperCase() == attr) {\n      result[object[attr]] = attr;\n    }\n  }\n  return result;\n}\n\nprint(enumProps($('#example-button')[0]));\n\n// => {...}\n\n</pre>\n\nYou can think of it a little like <code>print()</code> goes to stdout, and <code>console.log()</code> goes to stderr.\n\n</p>\n\n</section>\n\n<section id=\"abort\">\n  <header>\n    <h3 id=\"abort\">Giving Up</h3>\n  </header>\n\n<p>\n\nTests often require some feature or setup to be usable at all.  When it's not setup right you'll just get a bunch of meaningless failures.  For this reason there's a way to abort all your tests.  If you call <code>Abort()</code> then no further tests will be run.  If you want to connect to a server, for instance, you might check that the server is really there, and if not then just abort the rest of the tests.  For example:\n\n<pre>\n$.ajax({\n  url: '/ping',\n  success: Spy('ping', {wait: true, ignoreThis: true}),\n  error: function () {\n    Abort(\"Server isn't up\");\n  }\n});\n\n// => ping(...)\n</pre>\n\n</p>\n\n</section>\n\n<section id=\"html\">\n  <header>\n    <h2 id=\"html\">Setting Up Your HTML</h2>\n  </header>\n\n<aside>\n  <p>For more on the HTML setup see <a href=\"reference.html#format\">the reference documentation</a>.</p>\n</aside>\n\n<p>\n\nI wanted to show you all the cool features of doctest first, but you can't actually use any of them unless you set up a test runner page.  Luckily the page is pretty simple.  Let's say you've put doctest.js into <code>doctest/</code>:\n\n<pre>\n&lt;DOCTYPE html>\n&lt;html>\n  &lt;head>\n    &lt;meta charset=\"UTF-8\">\n    &lt;title>My Test&lt;/title>\n    &lt;script src=\"doctest/doctest.js\">&lt;/script>\n    &lt;link href=\"doctest/doctest.css\" rel=\"stylesheet\">\n    <b>&lt;script src=\"mylibrary.js\">&lt;/script></b>\n  &lt;/head>\n  &lt;body class=\"autodoctest\">\n\n  A test:\n\n&lt;pre class=\"test\">\ntest goes here\n&lt;/pre>\n\n  &lt;/body>&lt;/html>\n</pre>\n\n</p>\n\n<p>\n\nMostly it's just boilerplate: you have to include <code>doctest.js</code> and <code>doctest.css</code> and of course any libraries or dependencies of the thing you are testing.  You also must use <b><code>&lt;body class=\"autodoctest\"></code></b> &mdash; that's what tells doctest.js you want to find and run tests right away.\n\n</p>\n\n<p>\n\nEach test then is in a <code>&lt;pre class=\"test\"></code>.  You might not want to actully write your tests <em>inside</em> the HTML, and instead put them in a separate Javascript file.  To do that use:\n\n<pre>\n&lt;pre class=\"test\" href=\"./my_tests.js\">&lt;/pre>\n</pre>\n\nThis will load the test code from <code>./my_tests.js</code> and inline it into the element.  This is how I personally write most of my tests, though when moving between a narrative and tests (as I am doing in this tutorial) it is nice to keep the tests together with the descriptions.\n\n</p>\n\n<p>\n\nNote that specifically when you use <code>href=\"URL.js\"</code> you can split the tests into sections by including the comment <code><b>// == SECTION</b> Your Section Header Name</code> in the included file, and you'll get multiple elements with headers automatically.\n\n</p>\n\n<p>\n\nA pass/fail summary is automatically added to the top of the page, though you can use <code>&lt;div id=\"doctest-output\">&lt;/div></code> to position it someplace specific (as we did in this tutorial).\n\n</p>\n\n</section>\n\n\n<section id=\"feedback\">\n  <header>\n    <h2 id=\"feedback\">Feedback?</h2>\n  </header>\n\n<p>Was something in this tutorial confusing?  Is there a testing problem or pattern you think this tutorial should talk about?  Please give feedback in the form of an <a href=\"https://github.com/ianb/doctestjs/issues/new\">new issue</a>.  Thanks!</p>\n\n</section>\n\n\n<h3 href=\"try.html\">Live Demo...</h3>\n\n          </article>\n\n          <!--\n          <aside>\n            <h3>aside</h3>\n\n            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sodales urna non odio egestas tempor. Nunc vel vehicula ante. Etiam bibendum iaculis libero, eget molestie nisl pharetra in. In semper consequat est, eu porta velit mollis nec. Curabitur posuere enim eget turpis feugiat tempor. Etiam ullamcorper lorem dapibus velit suscipit ultrices.</p>\n\n          </aside>\n          -->\n\n<!-- /BODY -->\n\n      </div> <!-- #main -->\n\n    </div> <!-- #main-container -->\n\n    <div class=\"footer-container\">\n      <footer class=\"wrapper\">\n        <h3 class=\"no-toc\">doctest.js is by <a href=\"http://ianbicking.org\">Ian Bicking</a>.\n          It's on <a href=\"https://github.com/ianb/doctestjs\">github</a>!</h3>\n      </footer>\n    </div>\n\n<script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js\"></script>\n<script>\nwindow.jQuery || document.write('<script src=\".resources/boilerplate/js/vendor/jquery-1.8.1.min.js\"><\\/script>')\n</script>\n\n<script src=\".resources/boilerplate/js/main.js\"></script>\n\n<script type=\"text/javascript\">\n\n  var _gaq = _gaq || [];\n  _gaq.push(['_setAccount', 'UA-34921728-1']);\n  _gaq.push(['_trackPageview']);\n\n  (function() {\n    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n  })();\n\n</script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/func_ace.js",
    "content": "// =SECTION Setup\n\n$(\"#fixture\").empty();\nvar aceSrc = \"./ace.js\";\nvar script = $(\"<script>\").attr(\"onload\", Spy(\"aceLoad\", {wait: true})).attr(\"src\", aceSrc);\n$(document.head).append(script);\n\n// => <script />.aceLoad(0)\n\n// Not sure why I have to additionally wait:\nwait(function () {return typeof ace != \"undefined\";});\n\n// =>\n\nprint(ace);\n\n// => {...}\n\nvar div = $('<div><pre id=\"ace-editor\" style=\"width: 200px; height: 200px; position: absolute; bottom: 10px; left: 10px;\"></pre></div>');\ndiv.find(\"pre\").text(\"function square(x) {\\n  return x * x;\\n}\\n\");\n$(\"#fixture\").append(div);\nwait();\n// =>\n\nprint($(\"#ace-editor\")[0]);\nvar editor = ace.edit(\"ace-editor\");\neditor.setTheme(\"ace/theme/textmate\");\neditor.getSession().setMode(\"ace/mode/javascript\");\n\nTest.require(\"forms\", \"session\", \"ui\", \"templates-en-US\");\n/* =>\n<pre...</pre>\nLoaded modules: ...\n*/\n\nTest.normalStartup();\n// => ...\n\nprint(editor.getValue());\n\n// => function square...\n\n// =SECTION Setup peer\n\nTest.waitMessage(\"form-init\");\nTest.incoming({\n  type: \"hello\",\n  clientId: \"faker\",\n  url: location.href.replace(/\\#.*/, \"\"),\n  urlHash: \"\",\n  name: \"Faker\",\n  avatar: TogetherJS.baseUrl + \"/togetherjs/images/robot-avatar.png\",\n  color: \"#ff0000\",\n  title: document.title,\n  rtcSupported: false\n});\n\n/* =>\n\nsend: hello-back...\nsend: form-init\n  clientId: \"me\",\n  pageAge: ?,\n  updates: [\n   {\n      basis: 1,\n      element: \"#ace-editor\",\n      tracker: \"AceEditor\",\n      value: \"function square(x) {\\n  return x * x;\\n}\\n\"\n   }\n  ]\n*/\n\n// =SECTION Editing\n\nTest.waitMessage(\"form-update\");\n$(\"#ace-editor\").focus();\neditor.insert(\"Some more text\");\n\n/* =>\nsend: form-update\n  clientId: \"me\",\n  element: \"#ace-editor\",\n  replace: {\n    basis: 1,\n    delta: {\n      del: 0,\n      start: 0,\n      text: \"Some more text\"\n    },\n    id: \"...\"\n  },\n  \"server-echo\": true,\n  tracker: \"AceEditor\"\n*/\n\nvar current = editor.getValue();\nwait(function() { return editor.getValue() !== current; });\n\nTest.incoming({\n  type: \"form-update\",\n  clientId: \"faker\",\n  element: \"#ace-editor\",\n  tracker: \"AceEditor\",\n  replace: {\n    basis: 2,\n    delta: {\n      del: 0,\n      start: 5,\n      text: \"Hey \"\n    },\n    id: \"faker.2\"\n  },\n  \"server-echo\": true\n});\n\n// =>\n\nprint(editor.getValue());\n\n/* =>\nSome Hey more textfunction square(x) {\n  return x * x;\n}\n*/\n\n// FIXME: need to test (and do) cursor adjustments.  Unless they work out automatically.\n"
  },
  {
    "path": "togetherjs/tests/func_codemirror.js",
    "content": "// =SECTION Setup\n\nvar cmSrc = \"./codemirror4.js\";\nvar script = $(\"<script>\").attr(\"onload\", Spy(\"cmLoad\", {wait: true})).attr(\"src\", cmSrc);\n$(document.head).append(script);\n\n// => <script />.cmLoad(0)\n\nprint(CodeMirror);\n\n// => function ...\n\nvar div = $('<div><pre id=\"cm-editor\" style=\"width: 200px; height: 200px; position: absolute; bottom: 10px; left: 10px;\"></pre></div>');\n$(\"#fixture\").append(div);\nwait();\n// =>\n\nprint($(\"#cm-editor\")[0]);\nvar editor = CodeMirror($(\"#cm-editor\")[0], {\n  mode: \"javascript\"\n});\neditor.setValue(\"function square(x) {\\n  return x * x;\\n}\\n\");\n\nTest.require(\"forms\", \"session\", \"ui\", \"templates-en-US\");\n/* =>\n<pre...\nLoaded modules: ...\n*/\n\nTest.normalStartup();\n// => ...\n\nprint(editor.getValue());\n\n// => function square...\n\n// =SECTION Setup peer\n\nTest.waitMessage(\"form-init\");\nTest.incoming({\n  type: \"hello\",\n  clientId: \"faker\",\n  url: location.href.replace(/\\#.*/, \"\"),\n  urlHash: \"\",\n  name: \"Faker\",\n  avatar: TogetherJS.baseUrl + \"/togetherjs/images/robot-avatar.png\",\n  color: \"#ff0000\",\n  title: document.title,\n  rtcSupported: false\n});\n\n/* =>\n\nsend: hello-back...\nsend: form-init\n  clientId: \"me\",\n  pageAge: ?,\n  updates: [\n    {\n      basis: 1,\n      element: \"#cm-editor:nth-child(1)\",\n      tracker: \"CodeMirrorEditor\",\n      value: \"function square(x) {\\n  return x * x;\\n}\\n\"\n    }\n  ]\n*/\n\n// =SECTION Editing\n\nTest.waitMessage(\"form-update\");\n$(\"#cm-editor\").focus();\neditor.replaceRange(\"Some more text\", {line: 0, ch: 0});\n\n/* =>\nsend: form-update\n  clientId: \"me\",\n  element: \"#cm-editor:nth-child(1)\",\n  replace: {\n    basis: 1,\n    delta: {\n      del: 0,\n      start: 0,\n      text: \"Some more text\"\n    },\n    id: \"...\"\n  },\n  \"server-echo\": true,\n  tracker: \"CodeMirrorEditor\"\n*/\n\nvar current = editor.getValue();\nwait(function() { return editor.getValue() !== current; });\n\nTest.incoming({\n  type: \"form-update\",\n  clientId: \"faker\",\n  element: \"#cm-editor:nth-child(1)\",\n  tracker: \"CodeMirrorEditor\",\n  replace: {\n    basis: 2,\n    delta: {\n      del: 0,\n      start: 5,\n      text: \"Hey \"\n    },\n    id: \"faker.2\"\n  },\n  \"server-echo\": true\n});\n\n// =>\n\nprint(editor.getValue());\n\n/* =>\nSome Hey more textfunction square(x) {\n  return x * x;\n}\n*/\n\n// FIXME: need to test (and do) cursor adjustments.  Unless they work out automatically.\n"
  },
  {
    "path": "togetherjs/tests/func_forms.js",
    "content": "/*global forms, session, ui, windowing, eventMaker */\n// =SECTION Setup\n\n$(\"#fixture\").append('<textarea id=\"textarea\" style=\"width: 10em; height: 3em;\"></textarea>');\n$(\"#fixture\").append('<br>');\n$(\"#fixture\").append('<div><label for=\"yes\"><input type=\"radio\" name=\"answer\" id=\"yes\"> Yes</label><label for=\"no\"><input type=\"radio\" name=\"answer\" id=\"no\"> No</label></div>');\n$(\"#fixture\").append('<input type=\"password\" id=\"password\" value=\"test\">');\n\nTest.require(\"forms\", \"session\", \"ui\", \"windowing\", \"eventMaker\", \"templates-en-US\");\n// => Loaded modules: ...\n\nTest.normalStartup();\n// =>...\n\nvar fireChange = eventMaker.fireChange;\nvar $yes = $(\"#yes\");\nvar $no = $(\"#no\");\nvar $textarea = $(\"#textarea\");\nvar $password = $(\"#password\");\n\nwindowing.hide(\"#togetherjs-share\");\n\n// =SECTION Changes\n\nTest.waitMessage(\"form-update\");\n$yes.prop(\"checked\", true);\nfireChange($yes);\n\n/* =>\nsend: form-update\n  clientId: \"me\",\n  element: \"#yes\",\n  value: true\n*/\n\nTest.waitMessage(\"form-update\");\n$no.prop(\"checked\", true);\nfireChange($no);\n\n/* =>\nsend: form-update\n  clientId: \"me\",\n  element: \"#no\",\n  value: true\n*/\n\n$password.val(\"New Password\");\nfireChange($password);\nwait(100);\n\n/* =>\n */\n\nfunction selection() {\n  var start = $textarea[0].selectionStart;\n  var end = $textarea[0].selectionEnd;\n  if (typeof start != \"number\") {\n    if (typeof end == \"number\") {\n      console.warn(\"Weird, end with no start\", end);\n    }\n    return 'no selection';\n  }\n  print('selected', start, '-', end);\n}\n\nfunction select(start, end) {\n  if (end === undefined) {\n    end = start;\n  }\n  $textarea[0].selectionStart = start;\n  $textarea[0].selectionEnd = end;\n}\n\nTest.waitMessage(\"form-update\");\n$textarea.val(\"hello\");\nfireChange($textarea);\n\n/* =>\nsend: form-update\n  clientId: \"me\",\n  element: \"#textarea\",\n  replace: {\n    basis: 1,\n    delta: {\n      del: 0,\n      start: 0,\n      text: \"hello\"\n    },\n    id: \"...\"\n  },\n  \"server-echo\": true\n*/\n\n$textarea.focus();\nselect(3, 4);\nselection();\n\nTest.waitMessage(\"form-update\");\n$textarea.val(\"hello there\");\nfireChange($textarea);\n\n/* =>\nsend: form-focus\n  clientId: \"me\",\n  element: \"#textarea\"\nselected 3 - 4\nsend: form-update\n  clientId: \"me\",\n  element: \"#textarea\",\n  replace: {\n    basis: 2,\n    delta: {\n      del: 0,\n      start: 5,\n      text: \" there\"\n    },\n    id: \"...\"\n  },\n  \"server-echo\": true\n*/\n\n// This doesn't seem to have a reliable result, but I don't know why...\n// but I don't think it matters, since the change is only the result of\n// $textarea.val()\nselection();\n\nTest.waitMessage(\"form-update\");\n$textarea.val(\"hi there\");\nfireChange($textarea);\n\n/* =>\nselected ? - ?\nsend: form-update\n  clientId: \"me\",\n  element: \"#textarea\",\n  replace: {\n    basis: 3,\n    delta: {\n      del: 4,\n      start: 1,\n      text: \"i\"\n    },\n    id: \"...\"\n  },\n  \"server-echo\": true\n*/\n\nselect(3, 4);\n\nTest.waitMessage(\"form-focus\");\nTest.incoming({\n  type: \"hello\",\n  clientId: \"faker\",\n  url: location.href.replace(/\\#.*/, \"\"),\n  urlHash: \"\",\n  name: \"Faker\",\n  avatar: TogetherJS.baseUrl + \"/togetherjs/images/robot-avatar.png\",\n  color: \"#ff0000\",\n  title: document.title,\n  rtcSupported: false\n});\nTest.incoming({\n  clientId: \"faker\",\n  type: 'form-update',\n  element: \"#textarea\",\n  replace: {\n    basis: 4,\n    delta: {\n      start: 1,\n      del: 1,\n      text: \"ey\"\n    }\n  }\n});\n\n/* =>\n\nsend: hello-back...\nsend: form-init\n  clientId: \"me\",\n  pageAge: ?,\n  updates: [\n    {\n      basis: 5,\n      element: \"#textarea\",\n      value: \"hey there\"\n    },\n    {\n      element: \"#yes\",\n      value: false\n    },\n    {\n      element: \"#no\",\n      value: true\n    }\n  ]\nsend: form-focus...\n*/\n\nprint($textarea.val());\nselection();\n\n/* =>\nhey there\nselected 4 - 5\n*/\n\nselect(0, 5);\nTest.incoming({\n  clientId: \"faker\",\n  type: 'form-update',\n  element: \"#textarea\",\n  replace: {\n    basis: 5,\n    delta: {\n      start: 1, del: 2, text: \"ELLO\"\n    }\n  }\n});\nwait(function() { return $textarea.val()==='hELLO there'; });\n\n// =>\n\nprint($textarea.val());\nselection();\n\n/* =>\nhELLO there\nselected 0 - 7\n*/\n\n// form-init should be ignored in some cases...\nprint(Date.now() - TogetherJS.pageLoaded > 10);\nTest.incoming({\n  clientId: \"faker\",\n  type: \"form-init\",\n  pageAge: 10,\n  updates: [\n    {element: \"#textarea\",\n     value: \"foo\"\n    }\n  ]\n});\nwait(100);\n\n// => true\n\nprint($textarea.val());\n\n// => hELLO there\n"
  },
  {
    "path": "togetherjs/tests/func_misc.js",
    "content": "// =SECTION Setup\n\n$(\"#other\").remove();\n\nTest.require(\"ui\", \"chat\", \"util\", \"session\", \"jquery\", \"storage\", \"peers\", \"cursor\", \"windowing\", \"templates-en-US\");\n// => Loaded modules: ...\n\nTest.normalStartup();\n\n/* =>\nSettings reset\nTogetherJS started\nsend: hello\n  avatar: \"...default-avatar.png\",\n  clientId: \"...\",\n  clientVersion: \"...\",\n  color: \"...\",\n  isClient: false,\n  name: \"...\",\n  rtcSupported: ?,\n  starting: true,\n  title: \"...\",\n  url: \"...\",\n  urlHash: \"...\"\nWalkthrough closed\n */\n\nprintResolved(storage.settings.get(\"seenIntroDialog\"));\n\n// => true\n\n// =SECTION Peer handling\n\nTest.viewSend.deactivate();\nTest.newPeer();\nwait(500);\n\n// =>\n\nTest.incoming({\n  type: \"cursor-update\",\n  clientId: \"faker\",\n  top: 100,\n  left: 100\n});\n\nwait(300);\n\n// =>\n\nvar fakeCursor = TogetherJSTestSpy.Cursor.getClient(\"faker\");\nprint(fakeCursor.element && fakeCursor.element.is(\":visible\"));\n\n// => true\n\nvar faker = peers.getPeer(\"faker\");\nprint(faker);\n\n// => Peer(\"faker\")\n\nprint(faker.status, faker.idle, faker.view.dockElement && faker.view.dockElement.is(\":visible\"));\n\n// => live active true\n\nTest.incoming({\n  type: \"chat\",\n  text: \"Test message\",\n  clientId: \"faker\",\n  messageId: \"message1\"\n});\nwait(100);\n\n// =>\n\nprint($(\"#togetherjs-chat-notifier\").is(\":visible\"));\n\n// => true\n\nprint($(\"#togetherjs-chat-notifier\")[0]);\n\n/* =>\n...\n<div class=\"togetherjs-person togetherjs-person-faker\"...>\n...\n<div class=\"togetherjs-person-name-abbrev togetherjs-person-name-abbrev-faker\">Faker</div>\n<div class=\"togetherjs-chat-content\">Test message</div>\n...\n*/\n\n$(\"#togetherjs-chat-button\").click();\n\n// We need a wait here for the animation to finish:\nwait(1000);\n\n// =>\n\nprint($(\"#togetherjs-chat-notifier\").is(\":visible\"), $(\"#togetherjs-chat\").is(\":visible\"));\n\n// => false true\n\nTest.viewSend.activate();\n$(\"#togetherjs-chat-input\").val(\"outgoing message\");\nTogetherJSTestSpy.submitChat();\n\n/* =>\nsend: chat\n  clientId: \"me\",\n  messageId: \"...\",\n  text: \"outgoing message\"\n*/\n\nprint($(\"#togetherjs-chat-input\").val() === \"\");\n// => true\n\nprint($(\"#togetherjs-chat\")[0]);\n/* =>\n...\n<div class=\"togetherjs-chat-content\">outgoing message</div>\n...\n*/\n\nwindowing.hide();\n$(\"#togetherjs-profile-button\").click();\nprint($(\"#togetherjs-menu\").is(\":visible\"), $(\"#togetherjs-menu .togetherjs-self-name\").is(\":visible\"));\n// => true false\n$(\"#togetherjs-menu-update-name\").click();\nprint($(\"#togetherjs-menu .togetherjs-self-name\").is(\":visible\"));\n// => true\n$(\"#togetherjs-menu .togetherjs-self-name\").val(\"Joe\");\n// First we do a keyup to trigger the change event:\n\n$(\"#togetherjs-menu .togetherjs-self-name\").trigger(\"keyup\");\n// Then we submit:\n$(\"#togetherjs-menu .togetherjs-self-name\").trigger($.Event(\"keyup\", {which: 13}));\nprint(peers.Self.name);\nprint($(\"#togetherjs-menu\").is(\":visible\"), $(\"#togetherjs-menu .togetherjs-self-name\").is(\":visible\"));\nprint($(\"#togetherjs-self-name-display\").text());\n/* =>\nsend: peer-update\n  clientId: \"me\",\n  name: \"Joe\"\nJoe\ntrue false\nJoe\n*/\n\n// =SECTION Scrolling and participant screen\n\nvar lastEl = $('<div id=\"last-element\" />');\n$(document.body).append(lastEl);\nvar dockEl = peers.getPeer(\"faker\").view.dockElement;\nvar partEl = peers.getPeer(\"faker\").view.detailElement;\nprint(\"Starts visible:\", partEl.is(\":visible\"));\nTest.incoming({\n  type: \"scroll-update\",\n  position: {\n    location: \"#last-element\",\n    offset: 0\n  },\n  clientId: \"faker\"\n});\nvar prevPos = $(window).scrollTop();\ndockEl.click();\nwait(400);\n// => Starts visible: false\nvar curPos = $(window).scrollTop();\nprint(\"Moved from:\", prevPos, \"to:\", curPos, \"same?\", prevPos == curPos);\nwindow.scrollTo(0, prevPos);\nprint(\"Ends visible:\", partEl.is(\":visible\"));\n/* =>\nMoved from: ? to: ? same? false\nEnds visible: true\n*/\n\n\n// =SECTION Attic\n\n/****************************************\n * Skipping these for now, because leaving the client in place is handy:\n */\n\n/*\nTest.incoming({\n  type: \"bye\",\n  clientId: \"faker\"\n});\n\nwait(100);\n\n// =>\n\nprint(faker.status, faker.idle, faker.dockElement && faker.dockElement.is(\":visible\"));\n\n// => bye active undefined\n\nprint(fakeCursor.element && fakeCursor.element.is(\":visible\"));\n\n// => false\n*/\n"
  },
  {
    "path": "togetherjs/tests/func_notifications.js",
    "content": "// =SECTION Setup\n\nfunction visible() {\n  Array.prototype.slice.call(arguments).forEach(function (s) {\n    var el = $(s);\n    var status;\n    if (! el.length) {\n      status = \"does not exist\";\n    } else if (el.is(\":visible\")) {\n      status = \"visible\";\n    } else {\n      status = \"hidden\";\n    }\n    print(s, \":\", status);\n  });\n}\n\nTest.require(\"ui\", \"chat\", \"util\", \"session\", \"jquery\", \"storage\", \"peers\", \"cursor\", \"windowing\", \"templates-en-US\");\n// => Loaded modules: ...\n\nTest.normalStartup();\n\n// => ...\n\nTest.newPeer();\n\n// => ...\n\nvisible(\"#togetherjs-chat-notifier\");\n\n// => #togetherjs-chat-notifier : visible\n\n$(\"#togetherjs-chat-notifier .togetherjs-dismiss\").click();\n\nTest.incoming({\n  type: \"chat\",\n  clientId: \"faker\",\n  text: \"Test\",\n  messageId: \"test-message\"\n});\n\n// => ...\n\nvisible(\"#togetherjs-chat-notifier\", \"#togetherjs-chat\");\n\n/* =>\n#togetherjs-chat-notifier : visible\n#togetherjs-chat : hidden\n*/\n\n$(\"#togetherjs-chat-button\").click();\n// The animation makes this take a while:\n// (We could check $(\"#togetherjs-chat-notifier\").queue().length though)\nwait(function () {return ! $(\"#togetherjs-chat-notifier\").is(\":visible\");});\n// =>\nvisible(\"#togetherjs-chat-notifier\", \"#togetherjs-chat\");\n\n/* =>\n#togetherjs-chat-notifier : hidden\n#togetherjs-chat : visible\n*/\n\n$(\"#togetherjs-chat .togetherjs-close\").click();\nvisible(\"#togetherjs-chat-notifier\", \"#togetherjs-chat\");\n\n/* =>\n#togetherjs-chat-notifier : hidden\n#togetherjs-chat : hidden\n*/\n\n$(\"#togetherjs-chat-button\").click();\n\nTest.incoming({\n  type: \"chat\",\n  clientId: \"faker\",\n  text: \"Test 2\",\n  messageId: \"test-message\"\n});\nvisible(\"#togetherjs-chat-notifier\", \"#togetherjs-chat\");\n\n/* =>\n#togetherjs-chat-notifier : hidden\n#togetherjs-chat : visible\n*/\n\n$(\"#togetherjs-chat .togetherjs-close\").click();\nTest.incoming({\n  type: \"bye\",\n  clientId: \"faker\"\n});\n\n// =>\n\nvisible(\"#togetherjs-chat-notifier\", \"#togetherjs-chat\");\n\n/* =>\n#togetherjs-chat-notifier : visible\n#togetherjs-chat : hidden\n*/\n\n// Now we'll bring back the user:\nTest.newPeer({url: \"http://example.com/foo\"});\n\n// => ...\n\nvisible(\".togetherjs-follow\");\n\n/* =>\n.togetherjs-follow : visible\n*/\n\n$(\".togetherjs-nudge\").click();\n\n/* =>\nsend: url-change-nudge\n  clientId: \"me\",\n  to: \"faker\",\n  url: \"...\"\n\n */\n\n// =SECTION Helpers\n\nTest.addControl('<div>Some perhaps helpful test buttons to trigger events (not all combos are valid):</div>');\n\nTest.addControl($(\"<button>Faker Rejoin</button>\").click(function () {\n  Test.newPeer();\n}));\n\nTest.addControl($(\"<button>Join Random New Faker</button>\").click(function () {\n  var id = Math.floor(Math.random() * 1000);\n  Test.newPeer({\n    name: \"Faker \" + id,\n    clientId: \"random-\" + id\n  });\n}));\n\nTest.addControl($('<input placeholder=\"Change Faker URL\">').keypress(function (ev) {\n  if (ev.which == 13) {\n    Test.newPeer({url: ev.target.value});\n    ev.target.value = \"\";\n  }\n}));\n\nTest.addControl($('<button>Faker Leave</button>').click(function () {\n  Test.incoming({\n    type: \"bye\",\n    clientId: \"faker\"\n  });\n}));\n\nTest.addControl($('<button>Faker decline</button>').click(function () {\n  Test.incoming({\n    type: \"bye\",\n    clientId: \"faker\",\n    reason: \"declined-join\"\n  });\n}));\n\nTest.addControl($('<button>Nudge Me</button>').click(function () {\n  Test.incoming({\n    type: \"url-change-nudge\",\n    clientId: \"faker\",\n    url: peers.getPeer(\"faker\").url,\n    to: peers.Self.id\n  });\n}));\n\nTest.addControl($('<button>Keyboard</button>').click(function () {\n  Test.incoming({\n    type: \"keydown\",\n    clientId: \"faker\"\n  });\n}));\n\nTest.addControl($('<button>Participant down page (cursor rotate)</button>').click(function () {\n  \n  $('.togetherjs-cursor svg').animate({borderSpacing: -150, opacity: 1}, {\n    step: function(now, fx) {\n      if (fx.prop == \"borderSpacing\") {\n        $(this).css('-webkit-transform', 'rotate('+now+'deg)')\n          .css('-moz-transform', 'rotate('+now+'deg)')\n          .css('-ms-transform', 'rotate('+now+'deg)')\n          .css('-o-transform', 'rotate('+now+'deg)')\n          .css('transform', 'rotate('+now+'deg)');\n      } else {\n        $(this).css(fx.prop, now);\n      }\n    },\n    duration: 500\n  }, 'linear').promise().then(function () {\n    this.css('-webkit-transform', '');\n    this.css('-moz-transform', '');\n    this.css('-ms-transform', '');\n    this.css('-o-transform', '');\n    this.css('transform', '');\n    this.css(\"opacity\", \"\");\n  });\n\n  // Test.incoming({\n  //   type: \"keydown\",\n  //   clientId: \"faker\"\n  // });\n}));\n"
  },
  {
    "path": "togetherjs/tests/func_peer_status.js",
    "content": "// =SECTION Setup\n\nTest.require(\"peers\", \"templates-en-US\");\n// => Loaded modules: ...\n\nTogetherJSTestSpy.setIdleTime(100);\n\nTest.normalStartup();\n\n// => ...\n\nTest.newPeer();\n\n// => ...\n\n// =SECTION Test\n\nvar peer = peers.getPeer(\"faker\");\nprint(peer.status, peer.idle);\n\n// => live active\n\nwait(200);\n// =>\n\nprint(peer.status, peer.idle);\n\n// => live inactive\n\n// =SECTION Manual test code\n\n// 3 second idle time:\nTogetherJSTestSpy.setIdleTime(3000);\n\nTest.addControl('<div>Trigger activity states:</div>');\n\nTest.addControl($('<input type=\"text\" placeholder=\"Idle time (milliseconds)\">').keyup(function (event) {\n  var el = $(event.target);\n  if (event.which == 13) {\n    var value = parseInt(el.val(), 10);\n    TogetherJSTestSpy.setIdleTime(value);\n    el.val(\"\");\n  }\n}));\n\nTest.addControl($('<button>Faker inactive</button>').click(function () {\n  Test.incoming({\n    type: \"idle-status\",\n    idle: \"inactive\",\n    clientId: \"faker\"\n  });\n}));\n\nTest.addControl($('<button>Faker active</button>').click(function () {\n  Test.incoming({\n    type: \"idle-status\",\n    idle: \"active\",\n    clientId: \"faker\"\n  });\n}));\n"
  },
  {
    "path": "togetherjs/tests/func_walkthrough.js",
    "content": "// =SECTION Setup\n\nTest.require(\"ui\", \"chat\", \"util\", \"session\", \"jquery\", \"storage\", \"peers\", \"cursor\", \"windowing\", \"templates-en-US\");\n// => Loaded modules: ...\n\nTogetherJS.config(\"siteName\", \"this site\");\n\nprintChained(\n  Test.resetSettings,\n  Test.startTogetherJS);\n\n// => ...\n"
  },
  {
    "path": "togetherjs/tests/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>TogetherJS tests</title>\n    <meta charset=\"UTF-8\">\n    <script src=\"./doctestjs/doctest.js\" charset=\"UTF-8\"></script>\n    <script>\n      // This keeps TogetherJS from auto-starting:\n      sessionStorage.removeItem(\"togetherjs-session.status\");\n      sessionStorage.removeItem(\"togetherjs-session.peerCache\");\n    </script>\n    <script src=\"../../togetherjs.js\"></script>\n    <script src=\"//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js\"></script>\n    <script src=\"testutils.js\"></script>\n    <link rel=\"stylesheet\" href=\"doctestjs/doctest.css\">\n    <style>\n      #contents {\n        width: 100%;\n      }\n      #contents td {\n        vertical-align: top;\n      }\n    </style>\n  </head>\n  <body class=\"autodoctest\">\n\n    <table id=\"contents\">\n      <tr>\n        <td id=\"doctest-output\" style=\"width: 30%\"></td>\n        <td id=\"controls\" style=\"width: 30%\"></td>\n        <td style=\"width: 20%\">\n          Functional tests:\n          <ol>\n            <li><a href=\"?name=func_misc.js\">misc</a></li>\n            <li><a href=\"?name=func_notifications.js\">notifications</a></li>\n            <li><a href=\"?name=func_walkthrough.js\">walkthrough</a></li>\n            <li><a href=\"?name=func_peer_status.js\">peer status</a></li>\n            <li><a href=\"?name=func_forms.js\">forms</a></li>\n            <li><a href=\"?name=func_ace.js\">ace</a></li>\n            <li><a href=\"?name=func_codemirror.js\">codemirror</a></li>\n          </ol>\n        </td>\n        <td style=\"width: 20%\">\n          Unit tests:\n          <ol>\n            <li><a href=\"?name=test_storage.js\">storage</a></li>\n            <li><a href=\"?name=test_resolves.js\">resolves</a></li>\n            <li><a href=\"?name=test_elementFinder.js\">elementFinder</a></li>\n            <!--<li><a href=\"?name=test_ot.js\">ot</a></li>-->\n            <li><a href=\"?name=test_ot_text.js\">ot text</a></li>\n            <li><a href=\"?name=test_linkify.js\">linkify</a></li>\n            <li><a href=\"?name=test_console.js\">console</a></li>\n            <li><a href=\"?name=test_misc.js\">misc (small)</a></li>\n          </ol>\n          <p>\n            <a href=\"?name=interactive.js\">Manual testing</a><br>\n            <!--<a href=\"../../example/\">Example site</a><br>-->\n            <a href=\"manual/\">Manual tests</a>\n          </p>\n        </td>\n      </tr>\n    </table>\n\n<pre class=\"test\" data-href-pattern=\"./{name|interactive.js}\">xxx\n</pre>\n\n<div id=\"fixture\">\n</div>\n\n</body></html>\n"
  },
  {
    "path": "togetherjs/tests/interactive.js",
    "content": "// =SECTION Setup\n\n// Local config overrides\nvar config = localStorage.getItem(\"interactiveOverrides\");\nif (config) {\n  config = JSON.parse(config);\n  window.TogetherJSConfig = config;\n  for (var a in config) {\n    TogetherJS.config(a, config[a]);\n  }\n}\n\nTest.require(\"ui\", \"chat\", \"util\", \"session\", \"jquery\", \"storage\", \"peers\", \"cursor\", \"windowing\", \"elementFinder\", \"templates-en-US\");\n// => Loaded ...\n\nprintChained(\n  Test.resetSettings(),\n  storage.settings.set(\"seenIntroDialog\", true),\n  storage.settings.set(\"seenWalkthrough\", true),\n  storage.settings.set(\"dontShowRtcInfo\", true),\n  Test.startTogetherJS());\n\n// => ...\n\nfunction addPeer(id) {\n  var name = \"Faker\";\n  if (id) {\n    name += \" \" + id;\n  }\n  id = id || 'faker';\n  var color = \"#\" + Math.floor(Math.random() * 0xffffff).toString(16);\n  Test.newPeer({\n    name: name,\n    color: color,\n    clientId: id\n  });\n  var len = peers.getAllPeers().length;\n  var pageHeight = $(document).height();\n  var left = (len * 40) % $(window).width();\n  var top = len % 2 ? (len * 10) : (pageHeight - 100 - len * 10);\n  Test.incoming({\n    type: \"cursor-update\",\n    top: top,\n    left: left,\n    clientId: id\n  });\n  Test.incoming({\n    type: \"scroll-update\",\n    clientId: id,\n    position: {\n      location: \"body\",\n      offset: 20,\n      absoluteTop: 20,\n      documentHeight: $(document).height()\n    }\n  });\n}\n\nfunction pick(seq) {\n  if (! seq) {\n    seq = peers.getAllPeers(true);\n  }\n  return seq[Math.floor(Math.random() * seq.length)];\n}\n\naddPeer();\n// => ...\n\n// =SECTION Controls\n\nTest.addControl(\n\n  $(\"<button>Animate in cursor/box</button>\").click(function () {\n    //$(\".togetherjs-cursor\").fadeOut();\n  }),\n\n  $(\"<button>Animate out cursor/box</button>\").click(function () {\n    //$(\".togetherjs-cursor\").fadeOut();\n  }),\n\n  $(\"<button>Faker Join</button>\").click(function () {\n    addPeer();\n  }),\n  $(\"<button>Join Random</button>\").click(function () {\n    addPeer(\"faker-\" + Math.floor(Math.random() * 1000));\n  }),\n  $('<button>Leave</button>').click(function () {\n    var peer = pick();\n    Test.incoming({\n      type: \"bye\",\n      clientId: peer.id\n    });\n\n  }),\n  $('<button>Decline</button>').click(function () {\n    var peer = pick();\n    Test.incoming({\n      type: \"bye\",\n      clientId: peer.id,\n      reason: \"declined-join\"\n    });\n  })\n);\n\nTest.addControl(\n  $('<input placeholder=\"Change Faker URL\">').keypress(function (ev) {\n    if (ev.which == 13) {\n      Test.newPeer({url: ev.target.value});\n      ev.target.value = \"\";\n    }\n  }),\n  $('<button>Other URL</button>').click(function () {\n    Test.newPeer({url: \"http://example.com/?\" + Date.now()});\n  }),\n  $('<button>Same URL</button>').click(function () {\n    var url = location.href.replace(/\\#.*/, \"\");\n    Test.newPeer({url: url});\n  })\n);\n\nTest.addControl($('<button>Nudge Me</button>').click(function () {\n  var peer = pick();\n  Test.incoming({\n    type: \"url-change-nudge\",\n    clientId: peer.id,\n    url: peer.url,\n    to: peers.Self.id\n  });\n}));\n\nvar focused = {};\nTest.addControl($('<button>Focus something</button>').click(function () {\n  var peer = pick();\n  if (focused[peer.id]) {\n    Test.incoming({\n      type: \"form-focus\",\n      element: null,\n      clientId: peer.id,\n      url: peer.url\n    });\n    focused[peer.id] = null;\n    return;\n  }\n  var els = $(\"#controls textarea:visible, #controls input:visible, #controls select:visible\");\n\n  var el = $(els[Math.floor(els.length * Math.random())]);\n  focused[peer.id] = el;\n  Test.incoming({\n    type: \"form-focus\",\n    element: elementFinder.elementLocation(el),\n    clientId: peer.id,\n    url: peer.url\n  });\n}));\n\nTest.addControl($('<input placeholder=\"Incoming chat\">').keypress(function (event) {\n  var el = $(event.target);\n  if (event.which == 13) {\n    var peer = pick();\n    Test.incoming({\n      type: \"chat\",\n      text: el.val(),\n      messageId: 'message-' + Date.now(),\n      clientId: peer.id\n    });\n    el.val(\"\");\n  }\n}));\n\nvar el = $('<div><label for=\"idle-check\">Quick idle <input type=\"checkbox\" id=\"idle-check\"></label>' +\n           '<label for=\"expire-check\">Quick expire <input type=\"checkbox\" id=\"expire-check\"></label>' +\n           '<label for=\"include-hash\">includeHashInUrl <input type=\"checkbox\" id=\"include-hash\"></label></div>');\nel.find(\"#idle-check\").change(function (event) {\n  if (event.target.checked) {\n    TogetherJSTestSpy.setIdleTime(100);\n  } else {\n    TogetherJSTestSpy.setIdleTime(3*60*1000);\n  }\n});\n\nel.find(\"#expire-check\").change(function (event) {\n  if (event.target.checked) {\n    TogetherJSTestSpy.setByeTime(10*1000);\n  } else {\n    TogetherJSTestSpy.setIdleTime(10*60*1000);\n  }\n});\n\nel.find(\"#include-hash\").change(function (event) {\n  var config = localStorage.getItem(\"interactiveOverrides\");\n  if (config) {\n    config = JSON.parse(config);\n  } else {\n    config = {};\n  }\n  config.includeHashInUrl = event.target.checked;\n  localStorage.setItem(\"interactiveOverrides\", JSON.stringify(config));\n  alert(\"Reload required\");\n});\nif (TogetherJS.config.get(\"includeHashInUrl\")) {\n  el.find(\"#include-hash\").prop(\"checked\", true);\n}\n\nTest.addControl(el);\n\nTest.addControl(\n  $('<button>Inactive</button>').click(function () {\n    Test.incoming({\n      type: \"idle-status\",\n      idle: \"inactive\",\n      clientId: \"faker\"\n    });\n  }),\n  $('<button>Active</button>').click(function () {\n    Test.incoming({\n      type: \"idle-status\",\n      idle: \"active\",\n      clientId: \"faker\"\n    });\n  }),\n  $('<button>Keyboard</button>').click(function () {\n    Test.incoming({\n      type: \"keydown\",\n      clientId: \"faker\"\n    });\n  })\n);\n\nTest.addControl($('<input placeholder=\"Tool name\">').keypress(function (event) {\n  var el = $(event.target);\n  if (event.which == 13) {\n    TogetherJS.config(\"toolName\", el.val() || null);\n    el.val(\"\");\n  }\n}));\n"
  },
  {
    "path": "togetherjs/tests/manual/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Manual tests</title>\n  </head>\n  <body>\n\n    <h1>Manual tests</h1>\n\n    <p>These are test cases that aren't automated, but do have instructions...</p>\n\n    <ol>\n      <li>\n        <a href=\"https://github.com/mozilla/togetherjs/issues/797\">#797</a> <a href=\"multi-textarea-focus.html\">multi textarea focus</a>\n      </li>\n      <li>\n        <a href=\"youtube-video.html\">YouTube videos</a>\n      </li>\n    </ol>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/manual/multi-textarea-focus.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=UTF-8>\n    <title>Multi-textarea focus</title>\n    <script>\n      TogetherJSConfig_autoStart = true;\n    </script>\n    <script src=\"../../../togetherjs.js\"></script>\n  </head>\n  <body>\n\n    <h1>Multi-textarea focus</h1>\n\n    <p>To run this test, start this session in another tab.  Focus\n    textarea #1 in the first tab, edit textarea #2 in another tab.\n    <a href=\"https://github.com/mozilla/togetherjs/issues/797\">#797</a>\n    identifies a problem where textarea #2 will become focused in\n    the first tab.</p>\n\n    <div>\n      Textarea #1:<br>\n      <textarea id=\"number-1\">Number 1</textarea>\n    </div>\n\n    <div>\n      Textarea #2:<br>\n      <textarea id=\"number-2\">Number 2</textarea>\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/manual/youtube-video.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>YouTube Video Test</title>\n  </head>\n  <body>\n    <iframe width=\"420\" height=\"315\" src=\"//www.youtube.com/embed/rP1zHJKpV2s\" frameborder=\"0\" allowfullscreen></iframe>\n    <iframe width=\"420\" height=\"315\" src=\"http://www.youtube.com/embed/rKyoq5L1YIY\" frameborder=\"0\" allowfullscreen></iframe>\n\n    <button onclick=\"TogetherJS(this); return false;\">Toggle TogetherJS</button>\n\n    <script>\n      var TogetherJSConfig_suppressInvite = true;\n      var TogetherJSConfig_autoStart = true;\n      var TogetherJSConfig_suppressJoinConfirmation = true;\n      var TogetherJSConfig_dontShowClicks = true;\n      var TogetherJSConfig_youtube = true;\n      var TogetherJSConfig_cacheBust = false;\n    </script>\n\n\n    <script type=\"text/javascript\" src=\"../../../togetherjs.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/mobiletest.html",
    "content": "<!DOCTYPE html>\n\n<html>\n<head>\n  <title>Mobile test</title>\n  <meta name=\"description\" content=\"\">\n  <meta name=\"viewport\" content=\"width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;\"/>\n  <meta name=\"author\" content=\"\">\n  <script src=\"../../togetherjs.js\"></script>  \n</head>\n<body>\n    \n  <button onclick=\"TogetherJS(this); return false;\">Start TogetherJS</button>\n  \n  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sollicitudin eu metus vel lobortis. Donec ac posuere diam, ut sollicitudin elit. Proin nulla ipsum, dignissim porttitor dui congue, euismod pellentesque quam. Nunc suscipit elit iaculis risus pharetra, vitae faucibus nulla molestie. In et ornare magna. Interdum et malesuada fames ac ante ipsum primis in faucibus. In ultricies, orci eu condimentum commodo, est urna porta metus, sed euismod ante lorem quis sapien. Maecenas semper dui sed est imperdiet blandit.</p>\n  \n  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sollicitudin eu metus vel lobortis. Donec ac posuere diam, ut sollicitudin elit. Proin nulla ipsum, dignissim porttitor dui congue, euismod pellentesque quam. Nunc suscipit elit iaculis risus pharetra, vitae faucibus nulla molestie. In et ornare magna. Interdum et malesuada fames ac ante ipsum primis in faucibus. In ultricies, orci eu condimentum commodo, est urna porta metus, sed euismod ante lorem quis sapien. Maecenas semper dui sed est imperdiet blandit.</p>\n  \n  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sollicitudin eu metus vel lobortis. Donec ac posuere diam, ut sollicitudin elit. Proin nulla ipsum, dignissim porttitor dui congue, euismod pellentesque quam. Nunc suscipit elit iaculis risus pharetra, vitae faucibus nulla molestie. In et ornare magna. Interdum et malesuada fames ac ante ipsum primis in faucibus. In ultricies, orci eu condimentum commodo, est urna porta metus, sed euismod ante lorem quis sapien. Maecenas semper dui sed est imperdiet blandit.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/test_console.js",
    "content": "/*global tjconsole */\nvar origConsole = window.console;\nTest.require({tjconsole: \"console\"});\n// => Loaded modules: console\n\ntjconsole.warn(\"hey\", {a: 1, b: 2});\ntjconsole.log(1, 2, 3, {repr: function () {return (null).foo;}});\ntjconsole.trace();\nprint(tjconsole.toString());\n\n/* =>\nTogetherJS base URL: ...\nUser Agent: ...\nPage loaded: 20...Z\nAge: ... minutes\nURL: ...\n------+------+----------------------------------------------\n  ...  warn   hey {\"a\":1,\"b\":2}\n  ...  log    1 2 3 {}\n  ...         ...\n\n */\n"
  },
  {
    "path": "togetherjs/tests/test_elementFinder.js",
    "content": "Test.require(\"elementFinder\");\n// => Loaded modules: ...\n\nvar els = $(document.body).find(\"*\");\nels.each(function (index, el) {\n  el = $(el);\n  var loc;\n  try {\n    loc = elementFinder.elementLocation(el);\n  } catch (e) {\n    console.trace();\n    print(\"Error: cannot get location for\", el, \":\", e);\n    return;\n  }\n  var result = elementFinder.findElement(loc);\n  if (result != el[0]) {\n    print(\"Bad element:\", loc, el);\n    print(\"Resolved to:\", result);\n  } else {\n    console.log(\"Resolved element\", loc, el);\n  }\n});\nprint(\"done.\");\n\n// => done.\n"
  },
  {
    "path": "togetherjs/tests/test_linkify.js",
    "content": "/*global linkify */\nTest.require(\"linkify\");\n// => Loaded modules: linkify\n\nprint(linkify($(\"<span>this is a test</span>\")));\n// => <span>this is a test</span>\nprint(linkify($(\"<span>http://foo.com test</span>\")));\n/* =>\n<span>\n  <a href=\"http://foo.com\" target=\"_blank\">http://foo.com</a>\ntest</span>\n*/\n\nprint(linkify($(\"<span>yahoo (http://yahoo.com)</span>\")));\n/* =>\n<span>yahoo (\n  <a href=\"http://yahoo.com\" target=\"_blank\">http://yahoo.com</a>\n)</span>\n*/\n"
  },
  {
    "path": "togetherjs/tests/test_misc.js",
    "content": "/*global util */\nTest.require(\"util\");\n// => Loaded modules: util\n\nutil.assertValidUrl(\"http://foo.com\");\n// =>\nutil.assertValidUrl(\"//foobar\");\n// =>\nutil.assertValidUrl(\"data:image/png,asdf\");\n// =>\nutil.assertValidUrl(\"javascript:alert()\");\n// => Error: AssertionError: ...\nutil.assertValidUrl(\"foobar.com\");\n// => Error: AssertionError: ...\nutil.assertValidUrl(\"http://test.com); something: foo\");\n// => Error: AssertionError: ...\nutil.assertValidUrl(\"HTTPS://test.com\");\n// =>\n"
  },
  {
    "path": "togetherjs/tests/test_ot.js",
    "content": "// =SECTION Setup expand-on-failure\n\nTest.require(\"ot\", \"util\", \"randomutil\");\n// => Loaded...\n\nvar generator = randomutil(1);\n\nvar Client = util.Class({\n\n  constructor: function (clientId, hub, text) {\n    this.clientId = clientId;\n    this.hub = hub;\n    this.text = text || \"\";\n    this.history = ot.History(clientId, this.text);\n    this.queuedChanges = [];\n    this.hub.addClient(this);\n  },\n\n  makeChange: function () {\n    var delta = ot.TextReplace.random(this.text, generator);\n    var orig = this.text;\n    this.text = delta.apply(this.text);\n    var change = this.history.addDelta(delta);\n    this.text = this.history.getState();\n    this.queuedChanges.push(change);\n    console.log(\"internal:\", change+\"\", this.clientId);\n    console.log(\"    from:\", orig);\n    console.log(\"      to:\", this.text);\n  },\n\n  incoming: function (change) {\n    console.log(\"incoming change\", change);\n    var delta = this.history.add(change);\n    console.log(\"resulting delta\", delta+\"\");\n    var orig = this.text;\n    console.log(\"applying\", JSON.stringify(this.text), delta+\"\");\n    this.text = delta.apply(this.text);\n    this.text = this.history.getState();\n    console.log(\"  change:\", change+\"\", this.clientId);\n    console.log(\"    from:\", orig);\n    console.log(\"      to:\", this.text);\n    if (this.text != this.history.getState()) {\n      console.log(\"INVALID FORWARD DELTA\");\n      console.log(\"Delta applied:\", delta+\"\");\n      console.log(\"Produces\", JSON.stringify(this.text), \"instead of\", JSON.stringify(this.history.getState()), \"from\", JSON.stringify(orig));\n    }\n  },\n\n  flush: function () {\n    this.queuedChanges.forEach(function (c) {\n      this.hub.send(c, this);\n    }, this);\n    this.queuedChanges = [];\n  }\n});\n\nvar hub = {\n\n  clients: [],\n\n  addClient: function (client) {\n    this.clients.push(client);\n  },\n\n  send: function (change, client) {\n    util.assert(client);\n    for (var i=0; i<this.clients.length; i++) {\n      var c = this.clients[i];\n      if (c !== client) {\n        console.log(\"send change:\", change+\"\", \"from:\", client.clientId, \"to:\", c.clientId);\n        c.incoming(change.clone());\n      }\n    }\n  },\n\n  flushAll: function () {\n    this.clients.forEach(function (c) {\n      c.flush();\n      c.history.logHistory();\n    }, this);\n  },\n\n  clear: function () {\n    this.clients = [];\n  }\n};\n\n// =>\n\n// =SECTION Test fixture expand-on-failure\n\nvar error;\n\nfunction check() {\n  hub.flushAll();\n  var text;\n  var textId;\n  var history;\n  hub.clients.forEach(function (c) {\n    console.log(\"----------------------------------------\");\n    c.history.logHistory();\n  });\n  for (var i=0; i<hub.clients.length; i++) {\n    var client = hub.clients[i];\n    if (text === undefined) {\n      text = client.text;\n      textId = client.clientId;\n      history = client.history;\n    } else {\n      if (text != client.text) {\n        print(\"Error: mismatch in client\", client.clientId, \"in run\", run, first, second);\n        print(\"Basis text:\", JSON.stringify(text), textId);\n        print(\"Found text:\", JSON.stringify(client.text), client.clientId);\n        throw 'Error';\n      }\n    }\n  }\n}\n\nfunction runExample(first, second) {\n  generator = randomutil((run+1) * (first+1) * (second+1));\n  generator.defaultChars = \"XYZ/_ \";\n  var text = \"abcdef\";\n  console.log(\"Text:\", JSON.stringify(text));\n  hub.clear();\n  var clients = [Client(\"a\", hub, text), Client(\"b\", hub, text)];\n  for (var i=0; i<first; i++) {\n    hub.clients[0].makeChange();\n  }\n  generator.defaultChars = \"SRT+:-\";\n  for (i=0; i<second; i++) {\n    hub.clients[1].makeChange();\n  }\n  console.log(\"--Starting state--------------------------------------------\");\n  hub.clients[0].history.logHistory();\n  hub.clients[1].history.logHistory();\n  console.log(\"------------------------------------------------------------\");\n}\n\n// =SECTION Test\n\nvar start = doctest.params.startRun;\nstart = start ? parseInt(start, 10) : 0;\nfor (var run=start; run<100; run++) {\n  for (var first=0; first<4; first++) {\n    for (var second=0; second<4; second++) {\n      if (! (first || second)) {\n        // Boring case\n        continue;\n      }\n      console.log(\"Run:\", run, \"First:\", first, \"Second:\", second);\n      runExample(first, second);\n      check();\n      console.clear();\n    }\n  }\n}\nprint(\"done.\");\n\n\n// => done.\n"
  },
  {
    "path": "togetherjs/tests/test_ot_text.js",
    "content": "// =SECTION Setup expand-on-failure\n\nTest.require(\"ot\", \"util\", \"randomutil\");\n// => Loaded...\n\nvar generator = randomutil(1);\ngenerator.defaultChars = \"XYZ/_ \";\n\nfunction run() {\n  var base = \"abcdefg\";\n  console.log(\"Start:\", JSON.stringify(base) + \"/\" + base.length);\n  var delta1 = ot.TextReplace.random(base, generator);\n  var delta2 = ot.TextReplace.random(base, generator);\n  console.log(\"Delta1:\", delta1+\"\");\n  console.log(\"Delta2:\", delta2+\"\");\n  var sub1 = delta1.transpose(delta2);\n  console.log(\"Translated\", delta1, \"to\", sub1[0]);\n  var text1a = sub1[0].apply(delta2.apply(base));\n  console.log(\"     trans\", delta2, \"to\", sub1[1]);\n  var text1b = sub1[1].apply(delta1.apply(base));\n  console.log(\"first text:\", JSON.stringify(text1a), JSON.stringify(text1b));\n  if (text1a != text1b) {\n    print(\"Not equal\");\n    throw new Error(\"Error; not equal\");\n  }\n  var sub2 = delta2.transpose(delta1);\n  console.log(\" Translate\", delta2, \"to\", sub2[0]);\n  var text2a = sub2[0].apply(delta1.apply(base));\n  console.log(\"     trans\", delta1, \"to\", sub2[1]);\n  var text2b = sub2[1].apply(delta2.apply(base));\n  console.log(\"second text:\", JSON.stringify(text2a), JSON.stringify(text2b));\n  if (text2a != text2b) {\n    print(\"Not equal\");\n    throw new Error(\"Error; not equal\");\n  }\n  console.clear();\n}\n\n// =>\n\n// =SECTION Simple Test Setup expand-on-failure\n\nfunction r(start, length, text) {\n  return ot.TextReplace(start, length, text);\n}\n\nfunction trans(text, d1, d2) {\n  var sub = d1.transpose(d2);\n  console.log(JSON.stringify(text), \"+\", d1+\"\", \"->\", JSON.stringify(d1.apply(text)));\n  console.log(JSON.stringify(text), \"+\", d2+\"\", \"->\", JSON.stringify(d2.apply(text)));\n  var d1prime = sub[0];\n  var d2prime = sub[1];\n  if (d1.equals(d1prime)) {\n    print(d1, \"stays same\");\n  } else {\n    print(d1, \"becomes\", d1prime);\n  }\n  if (d2.equals(d2prime)) {\n    print(d2, \"stays same\");\n  } else {\n    print(d2, \"becomes\", d2prime);\n  }\n  var text1 = d1prime.apply(d2.apply(text));\n  var text2 = d2prime.apply(d1.apply(text));\n  print(d2, \"+\", d1prime, \"->\", text1);\n  print(d1, \"+\", d2prime, \"->\", text2);\n  if (text1 != text2) {\n    print(\"Error: text mismatch\");\n  }\n}\n\n// =SECTION Two insertions\n\nvar text = \"abcdef\";\nvar ins1 = r(0, 0, \"X\");\nvar ins2 = r(1, 0, \"Y\");\n\ntrans(text, ins1, ins2);\n/* =>\n[insert \"X\" @0] stays same\n[insert \"Y\" @1] becomes [insert \"Y\" @2]\n[insert \"Y\" @1] + [insert \"X\" @0] -> XaYbcdef\n[insert \"X\" @0] + [insert \"Y\" @2] -> XaYbcdef\n */\n\ntrans(text, ins2, ins1);\n/* =>\n[insert \"Y\" @1] becomes [insert \"Y\" @2]\n[insert \"X\" @0] stays same\n[insert \"X\" @0] + [insert \"Y\" @2] -> XaYbcdef\n[insert \"Y\" @1] + [insert \"X\" @0] -> XaYbcdef\n */\n\nins1 = r(0, 0, \"X\");\nins2 = r(0, 0, \"Y\");\n\ntrans(text, ins1, ins2);\n/* =>\n[insert \"X\" @0] becomes [insert \"X\" @1]\n[insert \"Y\" @0] stays same\n[insert \"Y\" @0] + [insert \"X\" @1] -> YXabcdef\n[insert \"X\" @0] + [insert \"Y\" @0] -> YXabcdef\n */\n\n// As we see in this example, precedence matters (YX vs XY):\ntrans(text, ins2, ins1);\n/* =>\n[insert \"Y\" @0] becomes [insert \"Y\" @1]\n[insert \"X\" @0] stays same\n[insert \"X\" @0] + [insert \"Y\" @1] -> XYabcdef\n[insert \"Y\" @0] + [insert \"X\" @0] -> XYabcdef\n */\n\n\n// =SECTION Two Deletions\n\ntext = \"abcdef\";\nvar del1 = r(0, 1, \"\");\nvar del2 = r(1, 1, \"\");\n\ntrans(text, del1, del2);\n/* =>\n[delete 1 chars @0] stays same\n[delete 1 chars @1] becomes [delete 1 chars @0]\n[delete 1 chars @1] + [delete 1 chars @0] -> cdef\n[delete 1 chars @0] + [delete 1 chars @0] -> cdef\n */\n\ntrans(text, del2, del1);\n/* =>\n[delete 1 chars @1] becomes [delete 1 chars @0]\n[delete 1 chars @0] stays same\n[delete 1 chars @0] + [delete 1 chars @0] -> cdef\n[delete 1 chars @1] + [delete 1 chars @0] -> cdef\n */\n\ntrans(text, r(0, 2, \"\"), r(0, 1, \"\"));\n/* =>\n[delete 2 chars @0] becomes [delete 1 chars @0]\n[delete 1 chars @0] becomes [no-op]\n[delete 1 chars @0] + [delete 1 chars @0] -> cdef\n[delete 2 chars @0] + [no-op] -> cdef\n */\n\ntrans(text, r(0, 1, \"\"), r(1, 1, \"\"));\n/* =>\n[delete 1 chars @0] stays same\n[delete 1 chars @1] becomes [delete 1 chars @0]\n[delete 1 chars @1] + [delete 1 chars @0] -> cdef\n[delete 1 chars @0] + [delete 1 chars @0] -> cdef\n */\n\ntrans(text, r(0, 4, \"\"), r(1, 1, \"\"));\n/* =>\n[delete 4 chars @0] becomes [delete 3 chars @0]\n[delete 1 chars @1] becomes [no-op]\n[delete 1 chars @1] + [delete 3 chars @0] -> ef\n[delete 4 chars @0] + [no-op] -> ef\n */\n\ntrans(text, r(1, 1, \"\"), r(0, 4, \"\"));\n/* =>\n[delete 1 chars @1] becomes [no-op]\n[delete 4 chars @0] becomes [delete 3 chars @0]\n[delete 4 chars @0] + [no-op] -> ef\n[delete 1 chars @1] + [delete 3 chars @0] -> ef\n */\n\ntrans(text, r(0, 3, \"\"), r(2, 4, \"\"));\n/* =>\n[delete 3 chars @0] becomes [delete 2 chars @0]\n[delete 4 chars @2] becomes [delete 3 chars @0]\n[delete 4 chars @2] + [delete 2 chars @0] ->\n[delete 3 chars @0] + [delete 3 chars @0] ->\n */\n\ntrans(text, r(2, 4, \"\"), r(0, 3, \"\"));\n/* =>\n[delete 4 chars @2] becomes [delete 3 chars @0]\n[delete 3 chars @0] becomes [delete 2 chars @0]\n[delete 3 chars @0] + [delete 3 chars @0] ->\n[delete 4 chars @2] + [delete 2 chars @0] ->\n */\n\n\n// =SECTION Insertion and replacement\n\ntrans(text, r(0, 0, \"X\"), r(2, 2, \"Y\"));\n/* =>\n[insert \"X\" @0] stays same\n[replace 2 chars with \"Y\" @2] becomes [replace 2 chars with \"Y\" @3]\n[replace 2 chars with \"Y\" @2] + [insert \"X\" @0] -> XabYef\n[insert \"X\" @0] + [replace 2 chars with \"Y\" @3] -> XabYef\n*/\n\ntrans(text, r(2, 2, \"Y\"), r(0, 0, \"X\"));\n/* =>\n[replace 2 chars with \"Y\" @2] becomes [replace 2 chars with \"Y\" @3]\n[insert \"X\" @0] stays same\n[insert \"X\" @0] + [replace 2 chars with \"Y\" @3] -> XabYef\n[replace 2 chars with \"Y\" @2] + [insert \"X\" @0] -> XabYef\n*/\n\ntrans(text, r(2, 0, \"X\"), r(2, 2, \"Y\"));\n/* =>\n[insert \"X\" @2] stays same\n[replace 2 chars with \"Y\" @2] becomes [replace 2 chars with \"Y\" @3]\n[replace 2 chars with \"Y\" @2] + [insert \"X\" @2] -> abXYef\n[insert \"X\" @2] + [replace 2 chars with \"Y\" @3] -> abXYef\n*/\n\ntrans(text, r(2, 2, \"Y\"), r(2, 0, \"X\"));\n/* =>\n[replace 2 chars with \"Y\" @2] becomes [replace 2 chars with \"Y\" @3]\n[insert \"X\" @2] stays same\n[insert \"X\" @2] + [replace 2 chars with \"Y\" @3] -> abXYef\n[replace 2 chars with \"Y\" @2] + [insert \"X\" @2] -> abXYef\n*/\n\ntrans(text, r(1, 0, \"X\"), r(0, 3, \"Y\"));\n/* =>\n[insert \"X\" @1] stays same\n[replace 3 chars with \"Y\" @0] becomes [replace 4 chars with \"YX\" @0]\n[replace 3 chars with \"Y\" @0] + [insert \"X\" @1] -> YXdef\n[insert \"X\" @1] + [replace 4 chars with \"YX\" @0] -> YXdef\n*/\n\ntrans(text, r(0, 3, \"Y\"), r(1, 0, \"X\"));\n/* =>\n[replace 3 chars with \"Y\" @0] becomes [replace 4 chars with \"XY\" @0]\n[insert \"X\" @1] becomes [insert \"X\" @0]\n[insert \"X\" @1] + [replace 4 chars with \"XY\" @0] -> XYdef\n[replace 3 chars with \"Y\" @0] + [insert \"X\" @0] -> XYdef\n*/\n\ntrans(text, r(4, 0, \"X\"), r(2, 2, \"Y\"));\n/* =>\n[insert \"X\" @4] becomes [insert \"X\" @3]\n[replace 2 chars with \"Y\" @2] stays same\n[replace 2 chars with \"Y\" @2] + [insert \"X\" @3] -> abYXef\n[insert \"X\" @4] + [replace 2 chars with \"Y\" @2] -> abYXef\n*/\n\ntrans(text, r(2, 2, \"Y\"), r(4, 0, \"X\"));\n/* =>\n[replace 2 chars with \"Y\" @2] stays same\n[insert \"X\" @4] becomes [insert \"X\" @3]\n[insert \"X\" @4] + [replace 2 chars with \"Y\" @2] -> abYXef\n[replace 2 chars with \"Y\" @2] + [insert \"X\" @3] -> abYXef\n*/\n\ntrans(text, r(0, 0, \"X\"), r(2, 2, \"Y\"));\n/* =>\n[insert \"X\" @0] stays same\n[replace 2 chars with \"Y\" @2] becomes [replace 2 chars with \"Y\" @3]\n[replace 2 chars with \"Y\" @2] + [insert \"X\" @0] -> XabYef\n[insert \"X\" @0] + [replace 2 chars with \"Y\" @3] -> XabYef\n*/\n\n// =SECTION Test (TP1)\n\nfor (var i=0; i<1000; i++) {\n  console.log(\"Run\", i);\n  run();\n}\nprint(\"done.\");\n\n// => done.\n\n// =SECTION Test (TP2 attempt)\n\n\nfunction runTp2() {\n  var base = \"abcdefg\";\n  console.log(\"Start:\", JSON.stringify(base) + \"/\" + base.length);\n  var deltaFirst = ot.TextReplace.random(base, generator);\n  var delta1 = ot.TextReplace.random(base, generator);\n  var delta2 = ot.TextReplace.random(base, generator);\n  console.log(\"Delta First:\", deltaFirst+\"\");\n  console.log(\"Delta1:\", delta1+\"\");\n  console.log(\"Delta2:\", delta2+\"\");\n  // Now we'll try two orderings:\n  // first + 1 + 2\n  // first + 2 + 1\n  var delta1Trans = delta1.transpose(deltaFirst)[0];\n  console.log(\"Translate:\", deltaFirst, \"+ (\", delta1, \"becomes\", delta1Trans, \")\");\n  var delta2Trans = delta2.transpose(deltaFirst)[0];\n  console.log(\"Translate:\", deltaFirst, \"+ (\", delta2, \"becomes\", delta2Trans, \")\");\n  var delta1Trans_a = delta1Trans.transpose(delta2Trans)[0];\n  console.log(\"Translate:\", delta2Trans, \"+ (\", delta1Trans, \"becomes\", delta1Trans_a, \")\");\n  var delta2Trans_a = delta1Trans.transpose(delta2Trans)[1];\n  console.log(\"Translate:\", delta1Trans, \"+ (\", delta2Trans, \"becomes\", delta2Trans_a, \")\");\n  var text1 = delta1Trans_a.apply(delta2Trans.apply(deltaFirst.apply(base)));\n  console.log(\"text1:\", JSON.stringify(base), \"->\", JSON.stringify(text1));\n  console.log(\" \", deltaFirst, deltaFirst.apply(base));\n  console.log(\" \", delta2Trans, delta2Trans.apply(deltaFirst.apply(base)));\n  console.log(\" \", delta1Trans_a, text1);\n  var text2 = delta2Trans_a.apply(delta1Trans.apply(deltaFirst.apply(base)));\n  console.log(\"text2:\", JSON.stringify(base), \"->\", JSON.stringify(text2));\n  console.log(\" \", deltaFirst, deltaFirst.apply(base));\n  console.log(\" \", delta1Trans, delta1Trans.apply(deltaFirst.apply(base)));\n  console.log(\" \", delta2Trans_a, text2);\n  if (text1 != text2) {\n    print(\"Not equal\");\n    throw new Error(\"Error; not equal\");\n  }\n}\n\nfor (var i=0; i<1000; i++) {\n  console.clear();\n  console.log(\"Run\", i);\n  runTp2();\n}\nprint(\"done.\");\n\n// => done.\n"
  },
  {
    "path": "togetherjs/tests/test_resolves.js",
    "content": "Test.require(\"util\");\n// => Loaded modules: util\n\nvar def = util.Deferred();\n\nsetTimeout(util.resolver(def, function () {\n  return 'ok';\n}));\n\nprintResolved('item', def);\n\n// => item ok\n\ndef = util.Deferred();\nvar chained = util.Deferred();\nsetTimeout(util.resolver(def, function () {\n  return chained;\n}));\nsetTimeout(function () {\n  chained.resolve(\"second\");\n});\n\nprintResolved('item2', def);\n\n// => item2 second\n\nvar defs = [util.Deferred(), util.Deferred(), util.Deferred()];\nvar result = util.resolveMany(defs);\nsetTimeout(function () {\n  defs[0].resolve('first');\n  defs[1].resolve('second');\n  defs[2].resolve('last');\n});\n\nprintResolved(result);\n// => [\"first\", \"second\", \"last\"]\n"
  },
  {
    "path": "togetherjs/tests/test_storage.js",
    "content": "/*global storage */\nTest.require(\"storage\", \"util\");\n// => Loaded modules: storage util\n\nprint(storage);\n// => [storage for localStorage]\n\nprintResolved(storage.clear(), storage.tab.clear());\n// => (resolved) (resolved)\n\nprintResolved(storage.keys(), storage.tab.keys());\n// => [] []\n\nprintResolved(storage.tab.set(\"foo\", \"bar\"));\n// => (resolved)\n\nprintResolved(storage.tab.keys());\n// => [\"foo\"]\n"
  },
  {
    "path": "togetherjs/tests/testutils.js",
    "content": "TogetherJSTestSpy = {};\n\nvar Test = {};\n\n/* Loads the modules that are listed as individual arguments, and adds\n   them to the global scope.  Blocks on the loading.  Use like:\n\n       Test.require(\"foo\", \"bar\");\n       // => ...\n       foo.someFunction()...\n\n   If you want to alias something, do:\n\n       Test.require({myConsole: \"console\"})\n       // => ...\n       myConsole.log()\n*/\nTest.require = function () {\n  var done = false;\n  var args = Array.prototype.slice.call(arguments);\n  var modules = [];\n  var aliases = {};\n  args.forEach(function (m) {\n    if (typeof m == \"object\") {\n      for (var alias in m) {\n        if (m.hasOwnProperty(alias)) {\n          modules.push(m[alias]);\n          aliases[m[alias]] = alias;\n        }\n      }\n    } else {\n      modules.push(m);\n    }\n  });\n\n  function loadModules() {\n    if (! modules.length) {\n      print(\"Require loaded\");\n      done = true;\n      return;\n    }\n    TogetherJS.require(modules, function () {\n      for (var i=0; i<modules.length; i++) {\n        var localName = aliases[modules[i]] || modules[i];\n        window[localName] = arguments[i];\n      }\n      var msg = [\"Loaded modules:\"].concat(modules);\n      print.apply(null, msg);\n      TogetherJS._loaded = true;\n      done = true;\n    });\n  }\n\n  if (TogetherJS.require) {\n    console.log(\"TogetherJS already initialized\");\n    loadModules();\n  } else if (typeof require == \"function\") {\n    console.log(\"require.js already loaded; configuring\");\n    loadModules();\n  } else {\n    window.require = TogetherJS._extend(TogetherJS.requireConfig);\n    window.require.callback = function () {\n      TogetherJS.require = require.config({context: \"togetherjs\"});\n      loadModules();\n    };\n    var url = \"../libs/require.js\";\n    var script = document.createElement(\"script\");\n    script.src = url;\n    console.log(\"Loading require.js from\", url);\n    document.head.appendChild(script);\n  }\n  wait(function () {return done;});\n};\n\nTest.IGNORE_MESSAGES = [\"cursor-update\", \"scroll-update\", \"keypress\"];\n\nTest.viewSend = function () {\n  // Prints out all send() messages\n  var session = TogetherJS.require(\"session\");\n  if (! TogetherJS.running) {\n    session.once(\"start\", Test.viewSend);\n    return;\n  }\n  var channel = TogetherJSTestSpy.getChannel();\n  var oldSend = channel.send;\n  channel.send = function (msg) {\n    oldSend.apply(channel, arguments);\n    Test.viewSend.emit(msg.type, msg);\n    if (Test.viewSend.running && Test.IGNORE_MESSAGES.indexOf(msg.type) == -1) {\n      if (typeof print == \"function\") {\n        print(\"send:\", msg.type);\n        var shortMsg = TogetherJS._extend(msg);\n        delete shortMsg.type;\n        var r = repr(shortMsg, undefined, 10);\n        r = \"  \" + r.replace(/^\\{\\s+/, \"\");\n        r = r.replace(/\\s+\\}$/, \"\");\n        print(r);\n      } else {\n        console.log(\"send[out-of-test](\", msg, \")\");\n      }\n    }\n  };\n};\n\nTogetherJS._mixinEvents(Test.viewSend);\nTest.viewSend.running = true;\nTest.viewSend.activate = function () {\n  Test.viewSend.running = true;\n};\nTest.viewSend.deactivate = function () {\n  Test.viewSend.running = false;\n};\n\n\nTest.newPeer = function (options) {\n  options = options || {};\n  var msg = {\n    type: \"hello\",\n    isClient: false,\n    clientId: options.clientId || \"faker\",\n    name: options.name || \"Faker\",\n    avatar: options.avatar || TogetherJS.baseUrl + \"/togetherjs/images/robot-avatar.png\",\n    color: options.color || \"#ff0000\",\n    url: options.url || location.href.replace(/#.*/, \"\"),\n    urlHash: options.urlHash || \"\",\n    title: document.title,\n    rtcSupported: false\n  };\n  Test.incoming(msg);\n};\n\nTest.waitEvent = function (context, event, options) {\n  var ops = TogetherJS._extend({wait: true, ignoreThis: true}, options);\n  context.once(event, Spy(event, ops));\n};\n\nTest.waitMessage = function (messageType) {\n  Test.waitEvent(Test.viewSend, messageType, {writes: false});\n};\n\nTest.resetSettings = function () {\n  var util = TogetherJS.require(\"util\");\n  var storage = TogetherJS.require(\"storage\");\n  return $.Deferred(function (def) {\n    util.resolveMany(\n      storage.settings.set(\"name\", \"\"),\n      storage.settings.set(\"defaultName\", \"Jane Doe\"),\n      storage.settings.set(\"avatar\", undefined),\n      storage.settings.set(\"stickyShare\", null),\n      storage.settings.set(\"color\", \"#00ff00\"),\n      storage.settings.set(\"seenIntroDialog\", undefined),\n      storage.settings.set(\"seenWalkthrough\", undefined),\n      storage.settings.set(\"dontShowRtcInfo\", undefined),\n      storage.tab.set(\"chatlog\", undefined)\n    ).then(function () {\n      def.resolve(\"Settings reset\");\n    });\n  });\n};\n\nTest.startTogetherJS = function () {\n  return $.Deferred(function (def) {\n    var session = TogetherJS.require(\"session\");\n    Test.viewSend();\n    session.once(\"ui-ready\", function () {\n      session.clientId = \"me\";\n      def.resolve(\"TogetherJS started\");\n    });\n    TogetherJS.startup._launch = true;\n    TogetherJS();\n  });\n};\n\nTest.closeWalkthrough = function () {\n  return $.Deferred(function (def) {\n    var buttonSelector = \"#togetherjs-walkthrough .togetherjs-dismiss:visible\";\n    var seenButton = false;\n    var id = setInterval(function () {\n      var button = $(buttonSelector);\n      if (seenButton && ! button.length) {\n        // The walkthrough popped up, and then disappeared\n        clearTimeout(id);\n        def.resolve(\"Walkthrough closed\");\n      }\n      if ((! seenButton) && button.length) {\n        seenButton = true;\n        button.click();\n      }\n    }, 100);\n  });\n};\n\nTest.normalStartup = function () {\n  printChained(\n    Test.resetSettings,\n    Test.startTogetherJS,\n    Test.closeWalkthrough);\n};\n\nfunction printChained() {\n  var args = Array.prototype.slice.call(arguments);\n  var index = 0;\n  var done = false;\n  function run() {\n    if (index >= args.length) {\n      done = true;\n      return;\n    }\n    var f = args[index];\n    if (!f.then) { f = f(); }\n    f.then(function () {\n      if (! arguments.length) {\n        print(\"(done)\");\n      } else {\n        print.apply(null, arguments);\n      }\n      check(1);\n    }, function () {\n      if (! arguments.length) {\n        print(\"(error)\");\n      } else {\n        print.apply(null, [\"Error:\"].concat(arguments));\n      }\n      check(1);\n    });\n    function check(increment) {\n      index += increment;\n      setTimeout(run);\n    }\n  }\n  wait(function () {return done;});\n  run();\n}\n\nTest.incoming = function (msg) {\n  TogetherJSTestSpy.getChannel().onmessage(msg);\n};\n\nTest.addControl = function () {\n  var div = $(\"<div />\");\n  var el;\n  for (var i=0; i<arguments.length; i++) {\n    el = $(arguments[i]);\n    div.append(el);\n  }\n  $(\"#controls\").append(div);\n  return el;\n};\n"
  },
  {
    "path": "togetherjs/tests/togetherjs-animations/css/styles.css",
    "content": "  #canvas {\n    background:#efefef;\n    width:800;\n    height:400px;\n  }\n  \n  .ellipse {\n    position:absolute;\n    opacity:0;\n  }\n\n  #windowpopout {\n    width:150px;\n    height:170px;\n    border-radius:4px;\n    background:#fff;\n    position:absolute;\n    right:80px;\n    top:140px;\n    box-shadow: 0px 2px 4px rgba(0,0,0,0.2);\n    opacity:0;\n  }\n\n  #notification {\n    width:300px;\n    height:100px;\n    background:#ccc;\n    position:absolute;\n    right:20px;\n    top:160px;\n    opacity:0;\n    border-radius:4px;\n  }\n\n  #notification2 {\n    width:300px;\n    height:100px;\n    background:#ccc;\n    position:absolute;\n    right:20px;\n    top:160px;\n    opacity:0;\n    border-radius:4px;\n  }\n  \n  #notification3 {\n    width:300px;\n    height:100px;\n    background:#ccc;\n    position:absolute;\n    right:20px;\n    top:160px;\n    opacity:0;\n    border-radius:4px;\n  }\n\n  #dock {\n    position:absolute;\n    right:20px;\n    top:160px;\n    width:60px;\n    height:300px;\n    z-index:9999;\n    background:#999;\n    border-radius:4px;\n  }\n\n  #participant-avatar {\n    width:20px;\n    height:20px;\n    margin:20px;\n    background:#fff;\n    position:absolute;\n    bottom:0px;\n    opacity:0;\n    border-radius:4px;\n  }\n\n  #participant-cursor {\n    position:absolute;\n    left:-10px;\n    bottom:19px;\n    transform:rotate(-30deg);\n    -ms-transform:rotate(-30deg); /* IE 9 */\n    -webkit-transform:rotate(-30deg); /* Safari and Chrome */\n  }\n\n  #participant-box {\n    width:50px;\n    height:20px;\n    border-radius:4px;\n    background:#ccc;\n    position:absolute;\n    left:300px;\n    top:200px;\n    opacity:0;\n    font-size:12px;\n  }\n  \n  #notification-transform {\n    width:300px;\n    height:200px;\n    background-color: red;\n/*    -moz-transform: perspective( 100px ) rotateX( 45deg );\n    -webkit-transform: perspective( 100px ) rotateX( 45deg );*/\n            transform: perspective( 100px ) rotateX( 45deg );\n  }\n  \n  html {\n      -webkit-transform-style: preserve-3d;\n      -webkit-font-smoothing: antialiased !important;\n    }\n"
  },
  {
    "path": "togetherjs/tests/togetherjs-animations/index.html",
    "content": "<!DOCTYPE html>\n\n<html>\n<head>\n  <title>TogetherJS interactions</title>\n  <meta name=\"description\" content=\"\">\n  <meta name=\"author\" content=\"Aaron Druck\">\n  <link rel=\"stylesheet\" href=\"css/styles.css\">\n  \n  <script src=\"js/jquery-1.11.1.min.js\"></script>\n  <script src=\"js/jquery.transit.min.js\"></script>\n  <script src=\"js/animations.js\"></script>\n  <script src=\"http://code.jquery.com/ui/1.10.3/jquery-ui.js\"></script>\n  \n  \n\n</head>\n<body>\n  \n  <!-- Notifications -->\n  <ul>\n    <li><button onclick=\"participantEnter()\">Participant enters notification</button>\n    <li><button onclick=\"participantLeave()\">Participant leaves notification</button>\n    <li><button onclick=\"participantCursorRotateDown()\">Participant cursor is down the page</button>\n    <li><button onclick=\"participantCursorRotateUp()\">Participant cursor is in same area of the page</button>\n    <li><button onclick=\"participantTyping()\">Participant is typing</button>\n    <li><button onclick=\"windowPopOut()\">Popout window</button>\n    <li><button onclick=\"chatnotification()\">Chat notification / no auto-dismiss</button> \n    <li><button onclick=\"transformPers()\">Perspective</button>    \n  </ul>\n  \n  <div id=\"canvas\">\n\n    <!-- participant box -->\n    <div id=\"participant-box\"> \n      <div id=\"participant-cursor\">\n        &#8593;\n      </div>     \n      Participant name box and cursor\n      <div id=\"participant-typing\"></div>\n    </div>\n\n    <!-- notification entered -->\n    <div id=\"notification\">\n      Participant entered\n    </div>\n    \n    <!-- notification left -->\n    <div id=\"notification2\">\n      Participant left\n    </div>\n    \n    <!-- chat notification -->\n    <div id=\"notification3\" onclick=\"closeNotification3();\">\n       Click to close chat\n     </div>\n  \n    <div id=\"windowpopout\"></div>\n    \n    <div id=\"dock\">\n      <div id=\"participant-avatar\"></div>\n    </div>\n    \n    <div id=\"notification-transform\">\n      \n    </div>\n  \n  </div>\n  \n  \n\n</body>\n</html>\n"
  },
  {
    "path": "togetherjs/tests/togetherjs-animations/js/animations.js",
    "content": "   // Methods\n  \n    function participantScaleUp() {\n      $('#participant-avatar').transition({ opacity: 1, scale: 2 });\n    }\n  \n    function participantScaleDown() {\n      $('#participant-avatar').transition({ opacity: 0, scale: 0 });\n    }\n\n  \tfunction notificationSlideIn() {\n  \t  $('#notification').css({\n        left: \"+=84px\",\n        opacity: 0,\n        \"zIndex\": 8888\n      });\n      $('#notification').animate({\n        \"left\": \"-=164px\",\n         opacity: 1,\n         \"zIndex\": 9999\n        }, \"fast\");\n    };\n  \n    function notificationSlideInParticipantLeave() {\n  \t  $('#notification2').css({\n        left: \"+=84px\",\n        opacity: 0,\n        \"zIndex\": 8888\n      });\n      $('#notification2').animate({\n        \"left\": \"-=164px\",\n         opacity: 1,\n         \"zIndex\": 9999\n        }, \"fast\");\n    };\n    \n    function notificationChat() {\n  \t  $('#notification3').css({\n        left: \"+=84px\",\n        opacity: 0,\n        \"zIndex\": 8888\n      });\n      $('#notification3').animate({\n        \"left\": \"-=164px\",\n         opacity: 1,\n         \"zIndex\": 9999\n        }, \"fast\");\n    };\n  \n    function closeNotification() {\n  \t  $('#notification').transition({\n        perspective: '300px',\n        rotateX: '-90deg',\n        delay: 3000,\n        opacity: 0\n      });\n    };\n  \n    function closeNotification2() {\n  \t  $('#notification2').transition({\n        perspective: '300px',\n        rotateX: '-90deg',\n        delay: 3000,\n        opacity: 0\n      });\n    };\n    \n    function closeNotification3() {\n  \t  $('#notification3').transition({\n        perspective: '300px',\n        rotateX: '-90deg',\n        opacity: 0\n      });\n    };\n  \n    function cursorPopIn() {\n      scaleUp($(\"#participant-box\"), 10);\n    }\n  \n    function cursorPopOut() {\n      $(\"#participant-box\")\n        .transition({ opacity: 0, scale: 0 })\n    }\n  \n    function scaleUp(el, size) {\n      var height = el.height();\n      var width = el.width();\n      var buffer = size / 2;\n      el.animate({\n        opacity: 1,\n        width: (width + size) + \"px\",\n        height: (height + size) + \"px\",\n        marginLeft: -buffer + \"px\",\n        paddingLeft: buffer + \"px\"\n      }).animate({\n        width: width + \"px\",\n        height: height + \"px\",\n        marginLeft: 0,\n        paddingLeft: 0\n      });\n    }\n  \t \n    // Objects\t  \n    \n    //chat notification\n    function chatnotification() {\n  \t  notificationChat();\n  \t  closeNotification();\n    };\n  \n    // when the participant enters the session\n    function participantEnter() {\n  \t  notificationSlideIn();\n  \t  participantScaleUp();\n  \t  closeNotification();\n  \t  cursorPopIn();\n    };\n  \n    // when the participant leaves the session\n    function participantLeave() {\n      notificationSlideInParticipantLeave();\n      participantScaleDown();\n      closeNotification2();\n      cursorPopOut();\n    }\n  \n    // when the participant is down the page or up the page\n    function participantCursorRotateDown() {\n      $('#participant-cursor').transition({\n        rotate: '-180deg'\n      });\n    }\n  \n    // when the user is at the same location as the participant\n    function participantCursorRotateUp() {\n      $('#participant-cursor').transition({\n        rotate: '-30deg'\n      });\n    }\n  \n    // NEEDS WORK when user presses a button in the dock to popout a window\n    function windowPopOut() {\n      $(\"#windowpopout\")\n        //.css({ transformOrigin: '100px 50px' })\n        .transition({ x: '-110', y: '100', opacity: 1, scale: 2.2 }, 100, 'ease')\n        .transition({ scale: 2 }, 100, 'ease')\n    }\n  \n    // when the participant is typing\n    function participantTyping() {\n      var count = 0;\n      \n      setInterval(function(){\n        count++;\n        document.getElementById('participant-typing').innerHTML = new Array(count % 5).join('.');\n      }, 150);\n      \n    }\n    \n    function transformPers() {\n      alert(\"transform\");\n      \n    }\n"
  },
  {
    "path": "togetherjs/togetherjs.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/*jshint scripturl:true */\n(function () {\n\n  var defaultConfiguration = {\n    // Disables clicks for a certain element.\n    // (e.g., 'canvas' would not show clicks on canvas elements.)\n    // Setting this to true will disable clicks globally.\n    dontShowClicks: false,\n    // Experimental feature to echo clicks to certain elements across clients:\n    cloneClicks: false,\n    // Enable Mozilla or Google analytics on the page when TogetherJS is activated:\n    // FIXME: these don't seem to be working, and probably should be removed in favor\n    // of the hub analytics\n    enableAnalytics: false,\n    // The code to enable (this is defaulting to a Mozilla code):\n    analyticsCode: \"UA-35433268-28\",\n    // The base URL of the hub (gets filled in below):\n    hubBase: null,\n    // A function that will return the name of the user:\n    getUserName: null,\n    // A function that will return the color of the user:\n    getUserColor: null,\n    // A function that will return the avatar of the user:\n    getUserAvatar: null,\n    // The siteName is used in the walkthrough (defaults to document.title):\n    siteName: null,\n    // Whether to use the minimized version of the code (overriding the built setting)\n    useMinimizedCode: undefined,\n    // Append cache-busting queries (useful for development!)\n    cacheBust: true,\n    // Any events to bind to\n    on: {},\n    // Hub events to bind to\n    hub_on: {},\n    // Enables the alt-T alt-T TogetherJS shortcut; however, this setting\n    // must be enabled early as TogetherJSConfig_enableShortcut = true;\n    enableShortcut: false,\n    // The name of this tool as provided to users.  The UI is updated to use this.\n    // Because of how it is used in text it should be a proper noun, e.g.,\n    // \"MySite's Collaboration Tool\"\n    toolName: null,\n    // Used to auto-start TogetherJS with a {prefix: pageName, max: participants}\n    // Also with findRoom: \"roomName\" it will connect to the given room name\n    findRoom: null,\n    // If true, starts TogetherJS automatically (of course!)\n    autoStart: false,\n    // If true, then the \"Join TogetherJS Session?\" confirmation dialog\n    // won't come up\n    suppressJoinConfirmation: false,\n    // If true, then the \"Invite a friend\" window won't automatically come up\n    suppressInvite: false,\n    // A room in which to find people to invite to this session,\n    inviteFromRoom: null,\n    // This is used to keep sessions from crossing over on the same\n    // domain, if for some reason you want sessions that are limited\n    // to only a portion of the domain:\n    storagePrefix: \"togetherjs\",\n    // When true, we treat the entire URL, including the hash, as the identifier\n    // of the page; i.e., if you one person is on `http://example.com/#view1`\n    // and another person is at `http://example.com/#view2` then these two people\n    // are considered to be at completely different URLs\n    includeHashInUrl: false,\n    // When true, the WebRTC-based mic/chat will be disabled\n    disableWebRTC: false,\n    // When true, youTube videos will synchronize\n    youtube: true,\n    // Ignores the following console messages, disables all messages if set to true\n    ignoreMessages: [\"cursor-update\", \"keydown\", \"scroll-update\"],\n    // Ignores the following forms (will ignore all forms if set to true):\n    ignoreForms: [\":password\"],\n    // When undefined, attempts to use the browser's language\n    lang: undefined,\n    fallbackLang: \"en-US\"\n  };\n\n  var styleSheet = \"/togetherjs/togetherjs.css\";\n\n  var baseUrl = \"__baseUrl__\";\n  if (baseUrl == \"__\" + \"baseUrl__\") {\n    // Reset the variable if it doesn't get substituted\n    baseUrl = \"\";\n  }\n  // Allow override of baseUrl (this is done separately because it needs\n  // to be done very early)\n  if (window.TogetherJSConfig && window.TogetherJSConfig.baseUrl) {\n    baseUrl = window.TogetherJSConfig.baseUrl;\n  }\n  if (window.TogetherJSConfig_baseUrl) {\n    baseUrl = window.TogetherJSConfig_baseUrl;\n  }\n  defaultConfiguration.baseUrl = baseUrl;\n\n  // True if this file should use minimized sub-resources:\n  var min = \"__min__\" == \"__\" + \"min__\" ? false : \"__min__\" == \"yes\";\n\n  var baseUrlOverride = localStorage.getItem(\"togetherjs.baseUrlOverride\");\n  if (baseUrlOverride) {\n    try {\n      baseUrlOverride = JSON.parse(baseUrlOverride);\n    } catch (e) {\n      baseUrlOverride = null;\n    }\n    if ((! baseUrlOverride) || baseUrlOverride.expiresAt < Date.now()) {\n      // Ignore because it has expired\n      localStorage.removeItem(\"togetherjs.baseUrlOverride\");\n    } else {\n      baseUrl = baseUrlOverride.baseUrl;\n      var logger = console.warn || console.log;\n      logger.call(console, \"Using TogetherJS baseUrlOverride:\", baseUrl);\n      logger.call(console, \"To undo run: localStorage.removeItem('togetherjs.baseUrlOverride')\");\n    }\n  }\n\n  var configOverride = localStorage.getItem(\"togetherjs.configOverride\");\n  if (configOverride) {\n    try {\n      configOverride = JSON.parse(configOverride);\n    } catch (e) {\n      configOverride = null;\n    }\n    if ((! configOverride) || configOverride.expiresAt < Date.now()) {\n      localStorage.removeItem(\"togetherjs.configOverride\");\n    } else {\n      var shownAny = false;\n      for (var attr in configOverride) {\n        if (! configOverride.hasOwnProperty(attr)) {\n          continue;\n        }\n        if (attr == \"expiresAt\" || ! configOverride.hasOwnProperty(attr)) {\n          continue;\n        }\n        if (! shownAny) {\n          console.warn(\"Using TogetherJS configOverride\");\n          console.warn(\"To undo run: localStorage.removeItem('togetherjs.configOverride')\");\n        }\n        window[\"TogetherJSConfig_\" + attr] = configOverride[attr];\n        console.log(\"Config override:\", attr, \"=\", configOverride[attr]);\n      }\n    }\n  }\n\n  var version = \"unknown\";\n  // FIXME: we could/should use a version from the checkout, at least\n  // for production\n  var cacheBust = \"__gitCommit__\";\n  if ((! cacheBust) || cacheBust == \"__gitCommit__\") {\n    cacheBust = Date.now() + \"\";\n  } else {\n    version = cacheBust;\n  }\n\n  // Make sure we have all of the console.* methods:\n  if (typeof console == \"undefined\") {\n    console = {};\n  }\n  if (! console.log) {\n    console.log = function () {};\n  }\n  [\"debug\", \"info\", \"warn\", \"error\"].forEach(function (method) {\n    if (! console[method]) {\n      console[method] = console.log;\n    }\n  });\n\n  if (! baseUrl) {\n    var scripts = document.getElementsByTagName(\"script\");\n    for (var i=0; i<scripts.length; i++) {\n      var src = scripts[i].src;\n      if (src && src.search(/togetherjs(-min)?.js(\\?.*)?$/) !== -1) {\n        baseUrl = src.replace(/\\/*togetherjs(-min)?.js(\\?.*)?$/, \"\");\n        console.warn(\"Detected baseUrl as\", baseUrl);\n        break;\n      } else if (src && src.search(/togetherjs-min.js(\\?.*)?$/) !== -1) {\n        baseUrl = src.replace(/\\/*togetherjs-min.js(\\?.*)?$/, \"\");\n        console.warn(\"Detected baseUrl as\", baseUrl);\n        break;\n      }\n    }\n  }\n  if (! baseUrl) {\n    console.warn(\"Could not determine TogetherJS's baseUrl (looked for a <script> with togetherjs.js and togetherjs-min.js)\");\n  }\n\n  function addStyle() {\n    var existing = document.getElementById(\"togetherjs-stylesheet\");\n    if (! existing) {\n      var link = document.createElement(\"link\");\n      link.id = \"togetherjs-stylesheet\";\n      link.setAttribute(\"rel\", \"stylesheet\");\n      link.href = baseUrl + styleSheet +\n\t(cacheBust ? (\"?bust=\" + cacheBust) : '');\n      document.head.appendChild(link);\n    }\n  }\n\n  function addScript(url) {\n    var script = document.createElement(\"script\");\n    script.src = baseUrl + url +\n      (cacheBust ? (\"?bust=\" + cacheBust) : '');\n    document.head.appendChild(script);\n  }\n\n  var TogetherJS = window.TogetherJS = function TogetherJS(event) {\n    var session;\n    if (TogetherJS.running) {\n      session = TogetherJS.require(\"session\");\n      session.close();\n      return;\n    }\n    TogetherJS.startup.button = null;\n    try {\n      if (event && typeof event == \"object\") {\n        if (event.target && typeof event) {\n          TogetherJS.startup.button = event.target;\n        } else if (event.nodeType == 1) {\n          TogetherJS.startup.button = event;\n        } else if (event[0] && event[0].nodeType == 1) {\n          // Probably a jQuery element\n          TogetherJS.startup.button = event[0];\n        }\n      }\n    } catch (e) {\n      console.warn(\"Error determining starting button:\", e);\n    }\n    if (window.TowTruckConfig) {\n      console.warn(\"TowTruckConfig is deprecated; please use TogetherJSConfig\");\n      if (window.TogetherJSConfig) {\n        console.warn(\"Ignoring TowTruckConfig in favor of TogetherJSConfig\");\n      } else {\n        window.TogetherJSConfig = TowTruckConfig;\n      }\n    }\n    if (window.TogetherJSConfig && (! window.TogetherJSConfig.loaded)) {\n      TogetherJS.config(window.TogetherJSConfig);\n      window.TogetherJSConfig.loaded = true;\n    }\n\n    // This handles loading configuration from global variables.  This\n    // includes TogetherJSConfig_on_*, which are attributes folded into\n    // the \"on\" configuration value.\n    var attr;\n    var attrName;\n    var globalOns = {};\n    for (attr in window) {\n      if (attr.indexOf(\"TogetherJSConfig_on_\") === 0) {\n        attrName = attr.substr((\"TogetherJSConfig_on_\").length);\n        globalOns[attrName] = window[attr];\n      } else if (attr.indexOf(\"TogetherJSConfig_\") === 0) {\n        attrName = attr.substr((\"TogetherJSConfig_\").length);\n        TogetherJS.config(attrName, window[attr]);\n      } else if (attr.indexOf(\"TowTruckConfig_on_\") === 0) {\n        attrName = attr.substr((\"TowTruckConfig_on_\").length);\n        console.warn(\"TowTruckConfig_* is deprecated, please rename\", attr, \"to TogetherJSConfig_on_\" + attrName);\n        globalOns[attrName] = window[attr];\n      } else if (attr.indexOf(\"TowTruckConfig_\") === 0) {\n        attrName = attr.substr((\"TowTruckConfig_\").length);\n        console.warn(\"TowTruckConfig_* is deprecated, please rename\", attr, \"to TogetherJSConfig_\" + attrName);\n        TogetherJS.config(attrName, window[attr]);\n      }\n\n\n    }\n    // FIXME: copy existing config?\n    // FIXME: do this directly in TogetherJS.config() ?\n    // FIXME: close these configs?\n    var ons = TogetherJS.config.get(\"on\");\n    for (attr in globalOns) {\n      if (globalOns.hasOwnProperty(attr)) {\n        // FIXME: should we avoid overwriting?  Maybe use arrays?\n        ons[attr] = globalOns[attr];\n      }\n    }\n    TogetherJS.config(\"on\", ons);\n    for (attr in ons) {\n      TogetherJS.on(attr, ons[attr]);\n    }\n    var hubOns = TogetherJS.config.get(\"hub_on\");\n    if (hubOns) {\n      for (attr in hubOns) {\n        if (hubOns.hasOwnProperty(attr)) {\n          TogetherJS.hub.on(attr, hubOns[attr]);\n        }\n      }\n    }\n    if (!TogetherJS.config.close('cacheBust')) {\n      cacheBust = '';\n      delete TogetherJS.requireConfig.urlArgs;\n    }\n\n    if (! TogetherJS.startup.reason) {\n      // Then a call to TogetherJS() from a button must be started TogetherJS\n      TogetherJS.startup.reason = \"started\";\n    }\n\n    // FIXME: maybe I should just test for TogetherJS.require:\n    if (TogetherJS._loaded) {\n      session = TogetherJS.require(\"session\");\n      addStyle();\n      session.start();\n      return;\n    }\n    // A sort of signal to session.js to tell it to actually\n    // start itself (i.e., put up a UI and try to activate)\n    TogetherJS.startup._launch = true;\n\n    addStyle();\n    var minSetting = TogetherJS.config.get(\"useMinimizedCode\");\n    TogetherJS.config.close(\"useMinimizedCode\");\n    if (minSetting !== undefined) {\n      min = !! minSetting;\n    }\n    var requireConfig = TogetherJS._extend(TogetherJS.requireConfig);\n    var deps = [\"session\", \"jquery\"];\n    var lang = TogetherJS.getConfig(\"lang\");\n    // [igoryen]: We should generate this value in Gruntfile.js, based on the available translations\n    var availableTranslations = {\n      \"en-US\": true,\n      \"en\": \"en-US\",\n      \"es\": \"es-BO\",\n      \"es-BO\": true,\n      \"ru\": true,\n      \"ru-RU\": \"ru\",\n      \"pl\": \"pl-PL\",\n      \"pl-PL\": true,\n      \"de-DE\": true,\n      \"de\": \"de-DE\"\n    };\n\n    if(lang === undefined) {\n      // BCP 47 mandates hyphens, not underscores, to separate lang parts\n      lang = navigator.language.replace(/_/g, \"-\");\n    }\n    if (/-/.test(lang) && !availableTranslations[lang]) {\n      lang = lang.replace(/-.*$/, '');\n    }\n    if (!availableTranslations[lang]) {\n      lang = TogetherJS.config.get(\"fallbackLang\");\n    } else if (availableTranslations[lang] !== true) {\n      lang = availableTranslations[lang];\n    }\n    TogetherJS.config(\"lang\", lang);\n\n    var localeTemplates = \"templates-\" + lang;\n    deps.splice(0, 0, localeTemplates);\n    function callback(session, jquery) {\n      TogetherJS._loaded = true;\n      if (! min) {\n        TogetherJS.require = require.config({context: \"togetherjs\"});\n        TogetherJS._requireObject = require;\n      }\n    }\n    if (! min) {\n      if (typeof require == \"function\") {\n        if (! require.config) {\n          console.warn(\"The global require (\", require, \") is not requirejs; please use togetherjs-min.js\");\n          throw new Error(\"Conflict with window.require\");\n        }\n        TogetherJS.require = require.config(requireConfig);\n      }\n    }\n    if (typeof TogetherJS.require == \"function\") {\n      // This is an already-configured version of require\n      TogetherJS.require(deps, callback);\n    } else {\n      requireConfig.deps = deps;\n      requireConfig.callback = callback;\n      if (! min) {\n        window.require = requireConfig;\n      }\n    }\n    if (min) {\n      addScript(\"/togetherjs/togetherjsPackage.js\");\n    } else {\n      addScript(\"/togetherjs/libs/require.js\");\n    }\n  };\n\n  TogetherJS.pageLoaded = Date.now();\n\n  TogetherJS._extend = function (base, extensions) {\n    if (! extensions) {\n      extensions = base;\n      base = {};\n    }\n    for (var a in extensions) {\n      if (extensions.hasOwnProperty(a)) {\n        base[a] = extensions[a];\n      }\n    }\n    return base;\n  };\n\n  TogetherJS._startupInit = {\n    // What element, if any, was used to start the session:\n    button: null,\n    // The startReason is the reason TogetherJS was started.  One of:\n    //   null: not started\n    //   started: hit the start button (first page view)\n    //   joined: joined the session (first page view)\n    reason: null,\n    // Also, the session may have started on \"this\" page, or maybe is continued\n    // from a past page.  TogetherJS.continued indicates the difference (false the\n    // first time TogetherJS is started or joined, true on later page loads).\n    continued: false,\n    // This is set to tell the session what shareId to use, if the boot\n    // code knows (mostly because the URL indicates the id).\n    _joinShareId: null,\n    // This tells session to start up immediately (otherwise it would wait\n    // for session.start() to be run)\n    _launch: false\n  };\n  TogetherJS.startup = TogetherJS._extend(TogetherJS._startupInit);\n  TogetherJS.running = false;\n\n  TogetherJS.requireConfig = {\n    context: \"togetherjs\",\n    baseUrl: baseUrl + \"/togetherjs\",\n    urlArgs: \"bust=\" + cacheBust,\n    paths: {\n      jquery: \"libs/jquery-1.11.1.min\",\n      walkabout: \"libs/walkabout/walkabout\",\n      esprima: \"libs/walkabout/lib/esprima\",\n      falafel: \"libs/walkabout/lib/falafel\",\n      tinycolor: \"libs/tinycolor\",\n      whrandom: \"libs/whrandom/random\"\n    }\n  };\n\n  TogetherJS._mixinEvents = function (proto) {\n    proto.on = function on(name, callback) {\n      if (typeof callback != \"function\") {\n        console.warn(\"Bad callback for\", this, \".once(\", name, \", \", callback, \")\");\n        throw \"Error: .once() called with non-callback\";\n      }\n      if (name.search(\" \") != -1) {\n        var names = name.split(/ +/g);\n        names.forEach(function (n) {\n          this.on(n, callback);\n        }, this);\n        return;\n      }\n      if (this._knownEvents && this._knownEvents.indexOf(name) == -1) {\n        var thisString = \"\" + this;\n        if (thisString.length > 20) {\n          thisString = thisString.substr(0, 20) + \"...\";\n        }\n        console.warn(thisString + \".on('\" + name + \"', ...): unknown event\");\n        if (console.trace) {\n          console.trace();\n        }\n      }\n      if (! this._listeners) {\n        this._listeners = {};\n      }\n      if (! this._listeners[name]) {\n        this._listeners[name] = [];\n      }\n      if (this._listeners[name].indexOf(callback) == -1) {\n        this._listeners[name].push(callback);\n      }\n    };\n    proto.once = function once(name, callback) {\n      if (typeof callback != \"function\") {\n        console.warn(\"Bad callback for\", this, \".once(\", name, \", \", callback, \")\");\n        throw \"Error: .once() called with non-callback\";\n      }\n      var attr = \"onceCallback_\" + name;\n      // FIXME: maybe I should add the event name to the .once attribute:\n      if (! callback[attr]) {\n        callback[attr] = function onceCallback() {\n          callback.apply(this, arguments);\n          this.off(name, onceCallback);\n          delete callback[attr];\n        };\n      }\n      this.on(name, callback[attr]);\n    };\n    proto.off = proto.removeListener = function off(name, callback) {\n      if (this._listenerOffs) {\n        // Defer the .off() call until the .emit() is done.\n        this._listenerOffs.push([name, callback]);\n        return;\n      }\n      if (name.search(\" \") != -1) {\n        var names = name.split(/ +/g);\n        names.forEach(function (n) {\n          this.off(n, callback);\n        }, this);\n        return;\n      }\n      if ((! this._listeners) || ! this._listeners[name]) {\n        return;\n      }\n      var l = this._listeners[name], _len = l.length;\n      for (var i=0; i<_len; i++) {\n        if (l[i] == callback) {\n          l.splice(i, 1);\n          break;\n        }\n      }\n    };\n    proto.emit = function emit(name) {\n      var offs = this._listenerOffs = [];\n      if ((! this._listeners) || ! this._listeners[name]) {\n        return;\n      }\n      var args = Array.prototype.slice.call(arguments, 1);\n      var l = this._listeners[name];\n      l.forEach(function (callback) {\n\n        callback.apply(this, args);\n      }, this);\n      delete this._listenerOffs;\n      if (offs.length) {\n        offs.forEach(function (item) {\n          this.off(item[0], item[1]);\n        }, this);\n      }\n\n    };\n    return proto;\n  };\n\n  /* This finalizes the unloading of TogetherJS, including unloading modules */\n  TogetherJS._teardown = function () {\n    var requireObject = TogetherJS._requireObject || window.require;\n    // FIXME: this doesn't clear the context for min-case\n    if (requireObject.s && requireObject.s.contexts) {\n      delete requireObject.s.contexts.togetherjs;\n    }\n    TogetherJS._loaded = false;\n    TogetherJS.startup = TogetherJS._extend(TogetherJS._startupInit);\n    TogetherJS.running = false;\n  };\n\n  TogetherJS._mixinEvents(TogetherJS);\n  TogetherJS._knownEvents = [\"ready\", \"close\"];\n  TogetherJS.toString = function () {\n    return \"TogetherJS\";\n  };\n\n  var defaultHubBase = \"__hubUrl__\";\n  if (defaultHubBase == \"__\" + \"hubUrl\"+ \"__\") {\n    // Substitution wasn't made\n    defaultHubBase = \"https://hub.togetherjs.mozillalabs.com\";\n  }\n  defaultConfiguration.hubBase = defaultHubBase;\n\n  TogetherJS._configuration = {};\n  TogetherJS._defaultConfiguration = {\n    // Disables clicks for a certain element.\n    // (e.g., 'canvas' would not show clicks on canvas elements.)\n    // Setting this to true will disable clicks globally.\n    dontShowClicks: false,\n    // Experimental feature to echo clicks to certain elements across clients:\n    cloneClicks: false,\n    // Enable Mozilla or Google analytics on the page when TogetherJS is activated:\n    // FIXME: these don't seem to be working, and probably should be removed in favor\n    // of the hub analytics\n    enableAnalytics: false,\n    // The code to enable (this is defaulting to a Mozilla code):\n    analyticsCode: \"UA-35433268-28\",\n    // The base URL of the hub\n    hubBase: defaultHubBase,\n    // A function that will return the name of the user:\n    getUserName: null,\n    // A function that will return the color of the user:\n    getUserColor: null,\n    // A function that will return the avatar of the user:\n    getUserAvatar: null,\n    // The siteName is used in the walkthrough (defaults to document.title):\n    siteName: null,\n    // Whether to use the minimized version of the code (overriding the built setting)\n    useMinimizedCode: undefined,\n    // Any events to bind to\n    on: {},\n    // Hub events to bind to\n    hub_on: {},\n    // Enables the alt-T alt-T TogetherJS shortcut; however, this setting\n    // must be enabled early as TogetherJSConfig_enableShortcut = true;\n    enableShortcut: false,\n    // The name of this tool as provided to users.  The UI is updated to use this.\n    // Because of how it is used in text it should be a proper noun, e.g.,\n    // \"MySite's Collaboration Tool\"\n    toolName: null,\n    // Used to auto-start TogetherJS with a {prefix: pageName, max: participants}\n    // Also with findRoom: \"roomName\" it will connect to the given room name\n    findRoom: null,\n    // If true, starts TogetherJS automatically (of course!)\n    autoStart: false,\n    // If true, then the \"Join TogetherJS Session?\" confirmation dialog\n    // won't come up\n    suppressJoinConfirmation: false,\n    // If true, then the \"Invite a friend\" window won't automatically come up\n    suppressInvite: false,\n    // A room in which to find people to invite to this session,\n    inviteFromRoom: null,\n    // This is used to keep sessions from crossing over on the same\n    // domain, if for some reason you want sessions that are limited\n    // to only a portion of the domain:\n    storagePrefix: \"togetherjs\",\n    // When true, we treat the entire URL, including the hash, as the identifier\n    // of the page; i.e., if you one person is on `http://example.com/#view1`\n    // and another person is at `http://example.com/#view2` then these two people\n    // are considered to be at completely different URLs\n    includeHashInUrl: false,\n    // The language to present the tool in, such as \"en-US\" or \"ru-RU\"\n    // Note this must be set as TogetherJSConfig_lang, as it effects the loader\n    // and must be set as soon as this file is included\n    lang: null\n  };\n  // FIXME: there's a point at which configuration can't be updated\n  // (e.g., hubBase after the TogetherJS has loaded).  We should keep\n  // track of these and signal an error if someone attempts to\n  // reconfigure too late\n\n  TogetherJS.getConfig = function (name) { // rename into TogetherJS.config.get()?\n    var value = TogetherJS._configuration[name];\n    if (value === undefined) {\n      if (! TogetherJS._defaultConfiguration.hasOwnProperty(name)) {\n        console.error(\"Tried to load unknown configuration value:\", name);\n      }\n      value = TogetherJS._defaultConfiguration[name];\n    }\n    return value;\n  };\n  TogetherJS._defaultConfiguration = defaultConfiguration;\n  TogetherJS._configTrackers = {};\n  TogetherJS._configClosed = {};\n\n  /* TogetherJS.config(configurationObject)\n     or: TogetherJS.config(configName, value)\n\n     Adds configuration to TogetherJS.  You may also set the global variable TogetherJSConfig\n     and when TogetherJS is started that configuration will be loaded.\n\n     Unknown configuration values will lead to console error messages.\n     */\n  TogetherJS.config = function (name, maybeValue) {\n    var settings;\n    if (arguments.length == 1) {\n      if (typeof name != \"object\") {\n        throw new Error('TogetherJS.config(value) must have an object value (not: ' + name + ')');\n      }\n      settings = name;\n    } else {\n      settings = {};\n      settings[name] = maybeValue;\n    }\n    var i;\n    var tracker;\n    var attr;\n    for (attr in settings) {\n      if (settings.hasOwnProperty(attr)) {\n        if (TogetherJS._configClosed[attr] && TogetherJS.running) {\n          throw new Error(\"The configuration \" + attr + \" is finalized and cannot be changed\");\n        }\n      }\n    }\n    for (attr in settings) {\n      if (! settings.hasOwnProperty(attr)) {\n        continue;\n      }\n      if (attr == \"loaded\" || attr == \"callToStart\") {\n        continue;\n      }\n      if (! TogetherJS._defaultConfiguration.hasOwnProperty(attr)) {\n        console.warn(\"Unknown configuration value passed to TogetherJS.config():\", attr);\n      }\n      var previous = TogetherJS._configuration[attr];\n      var value = settings[attr];\n      TogetherJS._configuration[attr] = value;\n      var trackers = TogetherJS._configTrackers[name] || [];\n      var failed = false;\n      for (i=0; i<trackers.length; i++) {\n        try {\n          tracker = trackers[i];\n          tracker(value, previous);\n        } catch (e) {\n          console.warn(\"Error setting configuration\", name, \"to\", value,\n                       \":\", e, \"; reverting to\", previous);\n          failed = true;\n          break;\n        }\n      }\n      if (failed) {\n        TogetherJS._configuration[attr] = previous;\n        for (i=0; i<trackers.length; i++) {\n          try {\n            tracker = trackers[i];\n            tracker(value);\n          } catch (e) {\n            console.warn(\"Error REsetting configuration\", name, \"to\", previous,\n                         \":\", e, \"(ignoring)\");\n          }\n        }\n      }\n    }\n  };\n\n  TogetherJS.config.get = function (name) {\n    var value = TogetherJS._configuration[name];\n    if (value === undefined) {\n      if (! TogetherJS._defaultConfiguration.hasOwnProperty(name)) {\n        console.error(\"Tried to load unknown configuration value:\", name);\n      }\n      value = TogetherJS._defaultConfiguration[name];\n    }\n    return value;\n  };\n\n  TogetherJS.config.track = function (name, callback) {\n    if (! TogetherJS._defaultConfiguration.hasOwnProperty(name)) {\n      throw new Error(\"Configuration is unknown: \" + name);\n    }\n    callback(TogetherJS.config.get(name));\n    if (! TogetherJS._configTrackers[name]) {\n      TogetherJS._configTrackers[name] = [];\n    }\n    TogetherJS._configTrackers[name].push(callback);\n    return callback;\n  };\n\n  TogetherJS.config.close = function (name) {\n    if (! TogetherJS._defaultConfiguration.hasOwnProperty(name)) {\n      throw new Error(\"Configuration is unknown: \" + name);\n    }\n    TogetherJS._configClosed[name] = true;\n    return this.get(name);\n  };\n\n  TogetherJS.reinitialize = function () {\n    if (TogetherJS.running && typeof TogetherJS.require == \"function\") {\n      TogetherJS.require([\"session\"], function (session) {\n        session.emit(\"reinitialize\");\n      });\n    }\n    // If it's not set, TogetherJS has not been loaded, and reinitialization is not needed\n  };\n\n  TogetherJS.refreshUserData = function () {\n    if (TogetherJS.running && typeof TogetherJS.require ==  \"function\") {\n      TogetherJS.require([\"session\"], function (session) {\n        session.emit(\"refresh-user-data\");\n      });\n    }\n  };\n\n  // This should contain the output of \"git describe --always --dirty\"\n  // FIXME: substitute this on the server (and update make-static-client)\n  TogetherJS.version = version;\n  TogetherJS.baseUrl = baseUrl;\n\n  TogetherJS.hub = TogetherJS._mixinEvents({});\n\n  TogetherJS._onmessage = function (msg) {\n    var type = msg.type;\n    if (type.search(/^app\\./) === 0) {\n      type = type.substr(\"app.\".length);\n    } else {\n      type = \"togetherjs.\" + type;\n    }\n    msg.type = type;\n    TogetherJS.hub.emit(msg.type, msg);\n  };\n\n  TogetherJS.send = function (msg) {\n    if (! TogetherJS.require) {\n      throw \"You cannot use TogetherJS.send() when TogetherJS is not running\";\n    }\n    var session = TogetherJS.require(\"session\");\n    session.appSend(msg);\n  };\n\n  TogetherJS.shareUrl = function () {\n    if (! TogetherJS.require) {\n      return null;\n    }\n    var session = TogetherJS.require(\"session\");\n    return session.shareUrl();\n  };\n\n  var listener = null;\n\n  TogetherJS.listenForShortcut = function () {\n    console.warn(\"Listening for alt-T alt-T to start TogetherJS\");\n    TogetherJS.removeShortcut();\n    listener = function listener(event) {\n      if (event.which == 84 && event.altKey) {\n        if (listener.pressed) {\n          // Second hit\n          TogetherJS();\n        } else {\n          listener.pressed = true;\n        }\n      } else {\n        listener.pressed = false;\n      }\n    };\n    TogetherJS.once(\"ready\", TogetherJS.removeShortcut);\n    document.addEventListener(\"keyup\", listener, false);\n  };\n\n  TogetherJS.removeShortcut = function () {\n    if (listener) {\n      document.addEventListener(\"keyup\", listener, false);\n      listener = null;\n    }\n  };\n\n  TogetherJS.config.track(\"enableShortcut\", function (enable, previous) {\n    if (enable) {\n      TogetherJS.listenForShortcut();\n    } else if (previous) {\n      TogetherJS.removeShortcut();\n    }\n  });\n\n  TogetherJS.checkForUsersOnChannel = function (address, callback) {\n    if (address.search(/^https?:/i) === 0) {\n      address = address.replace(/^http/i, 'ws');\n    }\n    var socket = new WebSocket(address);\n    var gotAnswer = false;\n    socket.onmessage = function (event) {\n      var msg = JSON.parse(event.data);\n      if (msg.type != \"init-connection\") {\n        console.warn(\"Got unexpected first message (should be init-connection):\", msg);\n        return;\n      }\n      if (gotAnswer) {\n        console.warn(\"Somehow received two responses from channel; ignoring second\");\n        socket.close();\n        return;\n      }\n      gotAnswer = true;\n      socket.close();\n      callback(msg.peerCount);\n    };\n    socket.onclose = socket.onerror = function () {\n      if (! gotAnswer) {\n        console.warn(\"Socket was closed without receiving answer\");\n        gotAnswer = true;\n        callback(undefined);\n      }\n    };\n  };\n\n  // It's nice to replace this early, before the load event fires, so we conflict\n  // as little as possible with the app we are embedded in:\n  var hash = location.hash.replace(/^#/, \"\");\n  var m = /&?togetherjs=([^&]*)/.exec(hash);\n  if (m) {\n    TogetherJS.startup._joinShareId = m[1];\n    TogetherJS.startup.reason = \"joined\";\n    var newHash = hash.substr(0, m.index) + hash.substr(m.index + m[0].length);\n    location.hash = newHash;\n  }\n  if (window._TogetherJSShareId) {\n    // A weird hack for something the addon does, to force a shareId.\n    // FIXME: probably should remove, it's a wonky feature.\n    TogetherJS.startup._joinShareId = window._TogetherJSShareId;\n    delete window._TogetherJSShareId;\n  }\n\n  function conditionalActivate() {\n    if (window.TogetherJSConfig_noAutoStart) {\n      return;\n    }\n    // A page can define this function to defer TogetherJS from starting\n    var callToStart = window.TogetherJSConfig_callToStart;\n    if (! callToStart && window.TowTruckConfig_callToStart) {\n      callToStart = window.TowTruckConfig_callToStart;\n      console.warn(\"Please rename TowTruckConfig_callToStart to TogetherJSConfig_callToStart\");\n    }\n    if (window.TogetherJSConfig && window.TogetherJSConfig.callToStart) {\n      callToStart = window.TogetherJSConfig.callToStart;\n    }\n    if (callToStart) {\n      // FIXME: need to document this:\n      callToStart(onload);\n    } else {\n      onload();\n    }\n  }\n\n  // FIXME: can we push this up before the load event?\n  // Do we need to wait at all?\n  function onload() {\n    if (TogetherJS.startup._joinShareId) {\n      TogetherJS();\n    } else if (window._TogetherJSBookmarklet) {\n      delete window._TogetherJSBookmarklet;\n      TogetherJS();\n    } else {\n      // FIXME: this doesn't respect storagePrefix:\n      var key = \"togetherjs-session.status\";\n      var value = sessionStorage.getItem(key);\n      if (value) {\n        value = JSON.parse(value);\n        if (value && value.running) {\n          TogetherJS.startup.continued = true;\n          TogetherJS.startup.reason = value.startupReason;\n          TogetherJS();\n        }\n      } else if (window.TogetherJSConfig_autoStart ||\n                 (window.TogetherJSConfig && window.TogetherJSConfig.autoStart)) {\n        TogetherJS.startup.reason = \"joined\";\n        TogetherJS();\n      }\n    }\n  }\n\n  conditionalActivate();\n\n  // FIXME: wait until load event to double check if this gets set?\n  if (window.TogetherJSConfig_enableShortcut) {\n    TogetherJS.listenForShortcut();\n  }\n\n  // For compatibility:\n  window.TowTruck = TogetherJS;\n\n})();\n"
  },
  {
    "path": "togetherjs/togetherjs.less",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n* License, v. 2.0. If a copy of the MPL was not distributed with this file,\n* You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/*Fonts*/\n@font-face {\n  font-family: openSansRegular;\n  src: url('fonts/OpenSans-Regular.ttf');\n}\n\n@font-face {\n  font-family: openSansLight;\n  src: url('fonts/OpenSans-Light.ttf');\n}\n\n@font-face {\n  font-family: openSansBold;\n  src: url('fonts/OpenSans-Bold.ttf');\n}\n\n@default-font: openSansLight, Helvetica, 'Helvetica Neue', Arial, sans-serif;\n\n// Size of the buttons (they're square):\n@button-size: 40px;\n@avatar-size: 32px;\n// Note: this is also in ui.js, BUTTON_HEIGHT\n// Height of the draggable anchor at the top:\n@anchor-height: @button-size / 2;\n// Extra padding on the edge of the screen:\n@side-padding: 0;\n// Background color of most elements:\n@background-color: #0095DD;\n@window-background-color: #ffffff;\n@window-color: #000;\n@text-color: #000;\n\n// This is the base z-index of the buttons; items you want below or above\n// this can be @z-index+1, etc.\n@z-index: 10000;\n\n@import \"reset.less\";\n@import \"functions.less\";\n\n.togetherjs {\n\n  /* General styles */\n  font-family: openSansLight, Helvetica, 'Helvetica Neue', Arial;\n  font-size: 14px;\n  line-height: 20px;\n  color: rgb(51, 51, 51);\n  font-weight: normal;\n\n  a {\n    color: #0095DD;\n    text-decoration: none;\n  }\n\n  a:hover {\n    color: #0095DD;\n    text-decoration: underline;\n  }\n\n  p {\n    margin: 7px 0 7px 0;\n  }\n\n  button, img {\n    vertical-align: middle;\n  }\n\n  input:focus {\n    outline: none;\n  }\n\n  button::-moz-focus-inner, input::-moz-focus-inner { // Inner padding and border oddities in FF3/4\n    padding: 0;\n    border: 0;\n  }\n\n  .togetherjs-right {\n    float:right;\n  }\n\n}\n\n\n.button-style () {\n  display: inline-block;\n  border-radius: 4px;\n  text-align: center;\n  // FIXME: for some reason this effects the total space of a <a\n  // class=\"togetherjs-primary/etc\"> but not a <button\n  // class=\"togetherjs-primary/etc\"> :\n  //padding: 3px 10px 3px;\n  height: 40px;\n  /*line-height not consistent across browsers*/\n  line-height: 37px;\n  text-decoration: none;\n  min-width: 100px;\n  border: none;\n  font-family: @default-font;\n  /*transition: all 0.25s linear 0s;*/\n  text-shadow: none;\n  margin:3px;\n  font-size:14px;\n}\n\nbutton:disabled {\n  opacity:0.2;\n}\n\nbutton[disabled]:hover {\n  background:#0194DB;\n}\n\n.togetherjs-default {\n  .button-style;\n  background:#9A9A9A;\n  color: #fff;\n  &.togetherjs-follow {\n    cursor: pointer;\n  }\n\n  &:hover {\n    background:#ADADAD;\n  }\n}\n\n.togetherjs-primary {\n  .button-style;\n  background:#0194DB;\n  color: #fff;\n  &.togetherjs-follow {\n    cursor: pointer;\n  }\n\n  &:hover {\n    background:#00ACFF;\n  }\n}\n\na.togetherjs-primary, a.togetherjs-default, a.togetherjs-secondary {\n  &, &:link, &:active, &:visited, &:hover {\n    color: #fff;\n    text-decoration: none;\n    vertical-align: middle;\n  }\n}\n\n#togetherjs-avatar-edit .togetherjs-person-avatar-swatch {\n  margin-left: 22px;\n}\n\n#togetherjs-avatar-edit .togetherjs-person {\n  float: left;\n  height: 36px;\n  width: 36px;\n  margin: 35px;\n  background-repeat: no-repeat;\n  background-size: 40px 40px;\n  background-position: -2px -1px;\n  border: 2px solid;\n  border-radius: 2px;\n  background-clip: border-box;\n}\n\n#togetherjs-avatar-edit #togetherjs-avatar-buttons {\n  float:right;\n  width:172px;\n  padding:45px 0px;\n}\n\ninput.togetherjs-upload-avatar {\n  line-height: 0px;\n  width: 174px;\n  margin-left:-20px;\n}\n\n#togetherjs-upload-avatar {\n  float:left;\n}\n\n#togetherjs-camera-avatar {\n  clear:both;\n}\n\n#togetherjs-avatar-edit .togetherjs-buttons {\n  clear:both;\n}\n\n\n.togetherjs-destructive {\n  .button-style;\n  background:#AC2924;\n  color: #ffffff;\n\n  &:hover {\n    background: rgba(212,6,6,1);\n  }\n\n}\n\n.togetherjs-secondary {\n  .button-style;\n  .gradient(#999999, #888888);\n  color: #fff;\n}\n\n.togetherjs-cancel {\n  display: inline-block;\n  background-color: @background-color;\n  border: none;\n  padding:3px 0px;\n  margin:0px 0px 0px;\n  min-width: 0;\n  font-size:14px;\n  color:#333333;\n  font-family: openSansLight, Helvetica;\n  vertical-align:-2px !important;\n  &:hover {\n    cursor: pointer;\n    border-bottom:1px solid #BCBCBC;\n    margin:0px 0px -1px;\n  }\n\n}\n\n.togetherjs-alt-text {\n  vertical-align:-2px;\n}\n\n\n.window() {\n  // top/left is set in code\n  position: fixed;\n  background-color: @window-background-color;\n  color: @window-color;\n  padding: 0 7px 0 7px;\n  z-index: @z-index + 1;\n\n\n  section {\n    margin: 15px 7px;\n  }\n\n  & > header {\n    font-weight: bold;\n    font-variant: normal;\n    text-align: center;\n    font-family: openSansRegular, Helvetica;\n    color: #fff;\n    margin: 0 -7px 0 -7px;\n    padding: 10px 4px 5px 30px;\n    height: (@button-size + 8)/2;\n    background: #0095DD;\n    border-radius: 4px 4px 0 0;\n    position: relative;\n    border-bottom:1px solid #0071A7;\n  }\n\n  .togetherjs-share-link {\n    width: 256px;\n    font-size: 12px;\n    padding: 6px 6px 4px;\n    border-radius: 4px;\n    border: 1px solid #cccccc;\n    box-shadow: inset 0 2px 2px rgba(0,0,0,0.1);\n    font-family: Monaco, sans-serif;\n    margin: 7px 0px;\n    &:focus {\n      border:1px solid #0095DD;\n    }\n  }\n\n  header button.togetherjs-close {\n    .button-reset;\n    border-left:1px solid #0071A7;\n    float: right;\n    font-weight: bold;\n    cursor: pointer;\n    background-color: @background-color;\n    background-image: url('./images/icon-close@2x.png');\n    background-position:center center;\n    background-repeat: no-repeat;\n    background-size:13px 13px;\n    width:39px;\n    height:39px;\n    margin-top:-10px;\n    margin-right:-4px;\n    border-top-right-radius:4px;\n    &:hover {\n      background-image:url('./images/icon-close-active.png');\n      background-color:rgba(0,0,0,0.1);\n    }\n  }\n\n  #togetherjs-chat-messages {\n    overflow-y: auto;\n    /*FIXME: I'm just pulling numbers out of thin air here:*/\n    height: 260px;\n  }\n\n} // End of .window()\n\n/*FIX ME something weird is going on here. the avatar has no paddingTop only on Safari*/\n/*button#togetherjs-profile-button.togetherjs-button {\n  padding:10px 0px !important;\n}*/\n\n/* General dock rules: */\n\n.togetherjs {\n\n  // The dock buttons\n  #togetherjs-buttons .togetherjs-button {\n    .button-reset;\n    position: relative;\n    width: @button-size+20;\n    height: @button-size+20;\n    background-color: @background-color;\n    background-size: @button-size @button-size;\n    background-repeat: no-repeat;\n    background-position: center;\n    border-top:1px solid rgba(0,0,0,0.2);\n    &:hover {\n      background-color: #0F81BF;\n    }\n  }\n\n  #togetherjs-buttons hr {\n    padding: 0;\n    margin: 0;\n  }\n\n  #togetherjs-dock-participants button.togetherjs-active {\n    background-color: #0F81BF !important;\n  }\n\n  #togetherjs-buttons #togetherjs-share-button {\n    background-image: url('./images/button-share.png');\n    &:hover {\n      background-image: url('./images/button-share-active.png');\n    }\n  }\n\n  #togetherjs-buttons #togetherjs-share-button.togetherjs-active {\n    background-image: url('./images/button-share-active.png') !important;\n    background-color: #0F81BF;\n  }\n\n  #togetherjs-buttons #togetherjs-audio-button{\n    background-image: url('./images/button-mic.png');\n    &:hover {\n      background-image: url('./images/button-mic-active.png');\n      /*background-color:#0095dd;*/\n      /*cursor: default;*/\n    }\n  }\n\n  #togetherjs-buttons #togetherjs-audio-button.togetherjs-active {\n    background-image: url('./images/button-mic-active.png') !important;\n    background-color: #0F81BF;\n  }\n\n  #togetherjs-buttons #togetherjs-chat-button{\n    background-image: url('./images/button-chat.png');\n    &:hover {\n      background-image: url('./images/button-chat-active.png');\n    }\n  }\n\n  #togetherjs-buttons #togetherjs-chat-button.togetherjs-active {\n    background-image: url('./images/button-chat-active.png') !important;\n    background-color: #0F81BF;\n  }\n\n  #togetherjs-dock-anchor {\n    height: @anchor-height;\n    text-align: center;\n    /* FIXME: disabling dock movement for now, cursor would be misleading: */\n    //cursor: move;\n    .user-select(none);\n    width: 100%;\n    position: relative;\n    left: 0px;\n    border-top-left-radius: 4px;\n    border-top-right-radius: 4px;\n  }\n\n  .togetherjs-subtitle {\n    background:#0195DD;\n    width:280px;\n    height:17px;\n    border-bottom:1px solid #0071A7;\n    color: rgba(255,255,255,0.5);\n    font-size:12px;\n    padding:7px 10px;\n    left:-14px;\n    top:-15px;\n    position:relative;\n  }\n\n  .togetherjs-subtitle #togetherjs-chat-participants {\n    font-size:12px;\n    color:rgba(255,255,255,0.5);\n  }\n\n  .togetherjs-subtitle #togetherjs-chat-no-participants {\n    font-size:12px;\n    color:rgba(255,255,255,0.5);\n  }\n\n  .togetherjs-subtitle #togetherjs-chat-participant-list {\n    font-size:12px;\n    color:rgba(255,255,255,0.5);\n  }\n\n\n  #togetherjs-chat-input {\n    width: 264px;\n    height: 20px;\n    overflow-x: hidden;\n    overflow-y: hidden;\n    resize: none;\n    font-size: 14px;\n    padding: 4px 6px 5px;\n    border-radius: 4px;\n    border: 1px solid #cccccc;\n    /*box-shadow: inset 0 2px 2px rgba(0,0,0,0.1);*/\n    font-family: openSansLight, Helvetica, sans-serif;\n    &:focus {\n      border:1px solid #0095DD;\n    }\n  }\n\n  #togetherjs-chat-input-box {\n    margin: 0;\n    padding: 10px 10px 11px;\n    border-top: 1px solid rgba(0,0,0,0.1);\n    background:#F2F2F2;\n    position: relative;\n    /*box-shadow: 0 -1px 2px rgba(0,0,0,0.1);*/\n    height: 31px;\n    width: 280px;\n    margin-left:-7px;\n    border-bottom-right-radius:4px;\n    border-bottom-left-radius:4px;\n  }\n\n  .togetherjs-window #togetherjs-chat-messages {\n    width: 300px;\n    position: relative;\n    left: -14px;\n    background: #fff;\n    top:-30px;\n    margin-bottom:-30px !important;\n  }\n\n  .togetherjs-chat-item {\n    padding: 0 0 20px 0;\n    font-family: @default-font;\n    font-size: 14px;\n    padding: 10px 0px;\n    margin: 0;\n    border-bottom: 1px solid rgba(0,0,0,0.1);\n    color:rgba(51,51,51,1);\n    min-height: 60px;\n  }\n\n  #togetherjs-chat-messages .togetherjs-chat-item a.togetherjs-person-url {\n    width: 105px;\n    white-space: nowrap;\n    vertical-align: top;\n    display: inline-block;\n    overflow: hidden;\n    text-overflow: ellipsis;\n  }\n\n  #togetherjs-chat-messages .togetherjs-person-self {\n    float:left;\n    margin-bottom:20px;\n    margin-top:7px;\n  }\n\n  #togetherjs-chat-messages .togetherjs-person {\n    float:left;\n    margin-bottom:20px;\n  }\n\n  .togetherjs-person-name-abbrev {\n    color:rgba(51,51,51,1);\n    font-family:openSansRegular, Helvetica, sans-serif;\n    padding-top: 2px;\n  }\n\n  .togetherjs-timestamp {\n    float: right;\n    color:rgba(51,51,51,0.5);\n    font-size: 9px !important;\n    padding: 0 15px;\n  }\n\n  .togetherjs-chat-content {\n    white-space: pre-wrap;\n    line-height: 20px;\n    font-family: @default-font;\n    margin: 3px 15px 3px 60px;\n  }\n\n  #togetherjs-window-pointer-right, #togetherjs-window-pointer-left {\n    position: fixed;\n    width: 10px;\n    height: 10px;\n    margin-right: -5px;\n    margin-top: -5px;\n    background: #fff;\n    border-right: 1px solid rgba(0,0,0,0.2);\n    border-bottom: 1px solid rgba(0,0,0,0.2);\n    z-index: @z-index + 2;\n    box-shadow: 1px 1px 1px rgba(0,0,0,0.1);\n  }\n  #togetherjs-window-pointer-right {\n    -moz-transform: rotate(-45deg);\n    -webkit-transform: rotate(-45deg);\n  }\n  #togetherjs-window-pointer-left {\n    -moz-transform: rotate(135deg);\n    -webkit-transform: rotate(135deg);\n  }\n\n  .togetherjs-window {\n    .window;\n    width: 286px;\n    border-radius: 4px;\n    box-shadow: 0 2px 4px rgba(0,0,0,0.5);\n  }\n\n  // FIXME: why the override?\n\n  #togetherjs-feedback-form > header {\n    font-weight: bold;\n    font-variant: normal;\n    text-align: center;\n    font-family: openSansRegular, Helvetica, sans-serif;\n    color: #fff;\n    margin: 0 -1px 0 -1px;\n    padding: 10px 4px 5px 30px;\n    height: 24px;\n    background: #0095DD;\n    border-radius: 4px 4px 0 0;\n    position: relative;\n    border-bottom: 1px solid #0071A7;\n  }\n\n  #togetherjs-feedback-form.togetherjs-modal {\n    background-color: #fff;\n    color: #000000;\n    padding: 0 0 5px 0;\n    border-radius: 2px;\n    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n    border-left: 1px solid #c9c9c9;\n    border-right: 1px solid #c9c9c9;\n    border-bottom: 1px solid #c9c9c9;\n    position: fixed;\n    top: 46%;\n    left: 47%;\n    margin-left: -150px;\n    margin-top: -10em;\n    height: 24em;\n    width:399px;\n  }\n\n  #togetherjs-alpha-intro .togetherjs-small-feedback-txt {\n    font-size: 10px;\n  }\n\n  #togetherjs-alpha-intro .togetherjs-modal-close:hover {\n    background: #61921b;\n  }\n\n  #togetherjs-alpha-intro {\n    height: 24em;\n  }\n\n  #togetherjs-intro .togetherjs-modal-dont-join {\n/*    background-repeat: repeat-x;\n    border: 0;\n    color: rgb(255, 255, 255);\n    cursor: pointer;\n    display: inline-block;\n    text-transform: none;\n    vertical-align: middle;\n    padding: 10px 0 10px 0;*/\n  }\n\n  .togetherjs-notification {\n    .window;\n    width: 300px;\n    border-radius: 4px;\n    background: rgba(242,242,242,0.9);\n    border: 1px solid #BCBCBC;\n    -moz-box-shadow:    0px 5px 15px 0px rgba(0,0,0,0.40), inset 0px 3px 1px 0px #FFFFFF;\n    -webkit-box-shadow: 0px 5px 15px 0px rgba(0,0,0,0.40), inset 0px 3px 1px 0px #FFFFFF;\n    box-shadow:         0px 5px 15px 0px rgba(0,0,0,0.40), inset 0px 3px 1px 0px #FFFFFF;\n    &:hover {\n      background: rgba(242,242,242,1);\n      cursor:pointer;\n    }\n  }\n\n  .togetherjs-notification .togetherjs-chat-item {\n    border-bottom:0px;\n    word-wrap: break-word;\n  }\n\n  .togetherjs-notification section#togetherjs-chat-notifier-message {\n    margin:0px !important;\n  }\n\n  .togetherjs-notification .togetherjs-chat-content {\n    font-size:12px;\n  }\n\n  .togetherjs-notification section {\n    font-size:12px;\n  }\n\n  .togetherjs-notification .togetherjs-person-name {\n    font-family: openSansRegular, Helvetica Bold, 'Helvetica Neue', Arial;\n    font-size:14px;\n  }\n\n  .togetherjs-notification button {\n    min-width:47% !important;\n  }\n\n  .togetherjs-notification .togetherjs-person {\n    display:none;\n  }\n\n  .togetherjs-notification .togetherjs-timestamp {\n    display:none;\n  }\n\n  .togetherjs-notification {\n    border-bottom:0px;\n  }\n\n  .togetherjs-notification img.togetherjs-notification-logo {\n    float: left;\n    margin: 22px 14px 14px 10px;\n    width: 34px;\n    height: 25px;\n  }\n\n  .togetherjs-notification img.togetherjs-notification-closebtn{\n    float:right;\n    padding: 14px 7px;\n\n    &:hover{\n      opacity:0.5;\n    }\n  }\n\n  .togetherjs-notification section.togetherjs-buttons {\n    border-top:1px solid #E1E1E1;\n  }\n\n  .togetherjs-person {\n    height: @avatar-size + 4;\n    width: @avatar-size + 4;\n    margin:(@button-size/5) + 2;\n    background-repeat: no-repeat;\n    background-size: 40px 40px;\n    background-position: -2px -2px;\n    border: 2px solid;\n    border-radius: 2px;\n    background-clip: border-box;\n    &.togetherjs-person-small {\n      display: inline-block;\n      @height: (@button-size + 8px) / 2 - 9px;\n      height: @height + 5;\n      width: @height + 5;\n      margin: -1px -18px;\n      background-size: (@height + 7) (@height + 7);\n      background-position: -1px -1px;\n    }\n  }\n\n  .togetherjs-person-small .togetherjs-person-avatar-swatch {\n    border-width: 3px;\n    margin-left: 14px;\n    margin-top: 0px;\n  }\n\n  .togetherjs-person-avatar-swatch {\n    /* This is the element that lives inside all .togetherjs-person elements\n       and is used for the triangle. */\n    @size: 7px;\n    width: 0;\n    height: 0;\n    margin-left: @avatar-size - @size - 2px;\n    padding: 0;\n    border-top: @size solid transparent;\n    border-left: @size solid transparent;\n    border-right: @size solid transparent;\n    border-bottom: @size solid transparent;\n    margin-top: 0px;\n  }\n\n  .togetherjs-person-inactive {\n    opacity: 0.5;\n  }\n\n  // causes a problem on FF\n  .togetherjs-button .togetherjs-person {\n    // A hack of sorts, because we don't want any top or bottom margin when the avatar\n    // is inside a dock button (but we do want the left margin);\n    margin: 0 0 0 10px;\n  }\n\n  @-moz-document url-prefix() {\n      /* firefox only styles */\n      .togetherjs-button .togetherjs-person {\n        margin: 10px 0 0 10px;\n      }\n  }\n\n  // Only applies to the participant-detail screen, really?\n  header .togetherjs-person {\n    float: left;\n  }\n\n  .togetherjs-dock-person > .togetherjs-dock-person-tooltip {\n    display: none;\n  }\n  .togetherjs-dock-person:hover > .togetherjs-dock-person-tooltip {\n    display: block;\n  }\n  .togetherjs-dock-person.togetherjs-active:hover > .togetherjs-dock-person-tooltip {\n    display: none;\n  }\n\n  .togetherjs-dock-person-tooltip {\n    font-family: openSansLight, Helvetica, 'Helvetica Neue', Arial;\n    position: absolute;\n    right: 70px;\n    top: 0px;\n    padding: 8px;\n    font-size:12px;\n    text-align:left;\n    min-width:30px;\n  }\n\n  .togetherjs-tooltip {\n    background-color: rgba(42,42,42,.9);\n    color: #fff;\n    border-radius: 4px;\n    line-height:20px !important;\n  }\n\n  .togetherjs-dock-person-tooltip .togetherjs-person-name {\n    font-size:12px;\n  }\n\n  .togetherjs-person-tooltip-arrow-r {\n    position:absolute;\n    left:46px;\n  \twidth: 0;\n  \theight: 0;\n  \tborder-top: 4px solid transparent;\n  \tborder-bottom: 4px solid transparent;\n  \tborder-left: 4px solid rgba(0,0,0,0.9);\n  \tline-height:20px;\n  \topacity:0.9;\n  \ttop:20px;\n  }\n\n}\n\n.togetherjs-triangle-up  {\n\tposition: absolute;\n  top: -15px;\n  width: 13px;\n  left: 50px;\n}\n\n.togetherjs-triangle-up img {\n  width:12px;\n  height:13px;\n}\n\n.togetherjs-rtc-dialog-btn {\n  text-align:right;\n}\n\n\n#togetherjs-rtc-info section.togetherjs-buttons {\n  text-align:right !important;\n}\n\n#togetherjs-rtc-info label {\n  font-size: 12px !important;\n  float: left !important;\n  padding-top: 13px;\n  padding-left: 30px;\n}\n\n#togetherjs-rtc-info input {\n  margin-top:0px !important;\n}\n\n\n.togetherjs-chat-url-change {\n  background: #f2f2f2;\n  margin-top:0px !important;\n}\n\n.togetherjs-chat-join-item {\n  background: #f2f2f2;\n  margin-top:0px !important;\n}\n\n.togetherjs-chat-left-item {\n  background: #f2f2f2;\n  margin-top:0px !important;\n}\n\n.togetherjs-inline-text {\n  margin-top:10px !important;\n}\n\n.togetherjs-chat-join-item .togetherjs-person{\n  float: left;\n  margin-bottom:0px !important;\n  margin-top:0px;\n}\n\n.togetherjs-chat-left-item .togetherjs-person{\n  float: left;\n  margin-bottom:0px !important;\n  margin-top:0px;\n}\n\n.togetherjs-chat-url-change .togetherjs-person{\n  float: left;\n  margin-bottom:0px !important;\n  margin-top:0px;\n}\n\n.togetherjs-chat-join-item span.togetherjs-person-name{\n  font-family:openSansRegular, Helvetica;\n}\n\n.togetherjs-chat-left-item span.togetherjs-person-name{\n  font-family:openSansRegular, Helvetica;\n}\n\n.togetherjs-chat-url-change span.togetherjs-person-name{\n  font-family:openSansRegular, Helvetica;\n}\n\n.togetherjs-clear {\n  clear:both;\n}\n\n\n/* Menu */\n#togetherjs-menu {\n  @icon-size: 12px;\n  width:216px;\n  position: fixed;\n  font-size: 14px;\n  background-color: #fff;\n  z-index: @z-index + 3;\n  border: 1px solid #979797;\n  border-radius: 4px;\n  hr {\n    margin:0px;\n    border-top: 0px solid #E1E1E1;\n  }\n  .togetherjs-menu-hr-avatar{\n    margin-top:20px;\n    height: 0px;\n    border-bottom: 1px solid #E1E1E1;\n    font-size: 1px;\n  }\n  .togetherjs-hr {\n    height: 0px;\n    margin: 0px;\n    border-bottom: 1px solid #E1E1E1;\n    font-size: 1px;\n  }\n  .togetherjs-menu-item {\n    margin:-1px 0px -1px;\n    padding: 12px;\n    line-height:9px;\n    height:10px;\n    clear:both;\n    cursor: pointer;\n    &.togetherjs-menu-disabled {\n      cursor: default;\n      &:hover {\n        background-color: inherit;\n        border-radius:4px;\n        border-top:1px solid #979797;\n        padding-top:11px !important;\n      }\n    }\n    img {\n      float:left;\n      height: (@icon-size)+8;\n      width: (@icon-size)+8;\n      margin-right: 10px;\n      margin-top:-5px;\n    }\n    &:hover {\n      background-color: rgba(216,216,216,0.5);\n    }\n    & .togetherjs-avatar {\n      height: (@icon-size)+8;\n      width: (@icon-size)+8;\n      padding: 0;\n      margin: 0 10px 0 0;\n    }\n    & .togetherjs-person-bgcolor-self {\n      display: inline-block;\n      width: @icon-size;\n      height: @icon-size;\n      border: 1px solid #999;\n      border-radius: 2px;\n      margin-right: 12px;\n      float:left;\n      margin-top:-2px;\n      margin-left:4px;\n    }\n  }\n\n  #togetherjs-menu-help {\n    padding-left:15px;\n  }\n\n  #togetherjs-menu-feedback {\n    padding-left:15px;\n  }\n\n  img#togetherjs-menu-avatar {\n    float:left;\n    padding-top:8px;\n  }\n\n  .togetherjs-person-name-self {\n    padding-top:8px;\n    line-height:32px;\n    font-weight:bold;\n  }\n\n  .togetherjs-self-name {\n    width:146px !important;\n    float:right;\n    margin-top:-23px;\n    font-size: 12px;\n    padding: 7px 7px;\n    border-radius: 4px;\n    border: 1px solid #cccccc;\n    box-shadow: inset 0 2px 2px rgba(0,0,0,0.1);\n    margin: -2px 0px;\n    &:focus {\n      border:1px solid #0095DD;\n    }\n  }\n\n  .togetherjs-self-name:focus {\n    border-bottom: 1px solid #0095DD;\n  }\n\n}\n\n/*Participant windows*/\n\n// multiple participants\n\n#togetherjs-participantlist.togetherjs-window {\n  padding: -1px;\n}\n\n#togetherjs-participantlist.togetherjs-window section {\n  overflow: scroll;\n  height: 200px;\n  margin: 0px -7px;\n}\n\n#togetherjs-participantlist section.togetherjs-buttons {\n  height: auto;\n  background: none;\n  text-align: left;\n  margin: auto;\n  padding-top: 0px;\n}\n\n#togetherjs-participantlist .togetherjs-person.togetherjs-person-small {\n  margin: 0px;\n  width: 30px;\n  height: 30px;\n}\n\n#togetherjs-participantlist.togetherjs-window section ul li {\n  padding: 10px;\n  border-bottom: 1px solid rgba(0,0,0,0.2);\n}\n\n#togetherjs-participantlist.togetherjs-window img {\n\n}\n\n#togetherjs-participantlist.togetherjs-window .tj-name {\n  padding-left: 5px;\n}\n\n#togetherjs-participantlist.togetherjs-window .tj-status {\n  float: right;\n  margin-top: 6px;\n  margin-right: 10px;\n  font-size: 24px;\n  color: green;\n}\n\n#togetherjs-participantlist.togetherjs-window .tj-urllocation {\n  font-size: 12px;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n\n#togetherjs-participantlist .togetherjs-follow-question {\n  margin-left: 0px;\n}\n\n#togetherjs-participantlist.togetherjs-window .tj-follow {\n  font-size: 12px;\n}\n\n#togetherjs-participantlist.togetherjs-window .tj-btn-sm {\n  height: 30px;\n  line-height: 30px;\n  font-size: 12px;\n  margin: 0px 3px 0px 0px;\n}\n\n\n//\n\nsection.togetherjs-participant-window-main {\n  margin:0px -7px -7px !important;\n}\n\n.togetherjs-participant-window-row a.togetherjs-person-url {\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  width: 179px;\n  display: inline-block;\n}\n\n.togetherjs p.togetherjs-participant-window-row {\n  border-bottom:1px solid #E1E1E1 !important;\n  padding:7px 14px 14px !important\n}\n\n.togetherjs-participant-window-row strong {\n  font-weight:800;\n}\n\n.togetherjs-follow-question {\n  margin-left: 10px;\n}\n\n.togetherjs-float-left {\n  float: left;\n}\n\n.togetherjs-window {\n\tinput[type=\"radio\"], input[type=\"checkbox\"] {\n  \t\tmargin: 0 0 0 !important;\n\t}\n}\n\n.togetherjs-clear {\n  clear: both;\n  margin: 10px;\n}\n\nsection.togetherjs-buttons {\n  background: #F3F2F2;\n  margin: 0px -7px !important;\n  padding: 7px;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 4px;\n  text-align: right;\n}\n\nsection.togetherjs-buttons.togetherjs-buttons-notification-diff-url {\n  margin: 7px -7px 0px !important;\n  padding: 7px 3px 0px;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 4px;\n  width: 300px;\n  text-align: right;\n}\n\n.togetherjs-notification-diff-url {\n  width: 288px !important;\n  margin: 0px 7px !important;\n}\n\n\n.togetherjs-different-url button {\n  min-width:47% !important;\n}\n\n/*.togetherjs-different-url {\n  text-align:right;\n}*/\n\n.togetherjs-same-url {\n  padding-left: 7px !important;\n  opacity:.5 !important;\n  padding-top: 7px !important;\n  padding-bottom: 7px !important;\n}\n\nsection.togetherjs-buttons .togetherjs-same-url {\n  text-align: left;\n}\n\n\n\n/* Button set */\n#togetherjs-dock {\n  position: fixed;\n  z-index: @z-index;\n  background-color: @background-color;\n  box-shadow: 0 2px 4px rgba(0,0,0,0.5);\n  @border-radius: 4px;\n  @long-side: (@button-size + 9px) * 4 + 64px; // actual button-size * number of buttons + expand thingy\n  @short-side: @button-size + 20px;\n  /*border:1px solid #000;*/\n\n  &.togetherjs-dock-right {\n    padding: 0;\n    bottom: 150px;\n    right: 5px;\n    border-radius: @border-radius;\n    height: @long-side;\n    width: @short-side;\n    #togetherjs-dock-anchor-vertical {\n      display: none;\n    }\n    #togetherjs-dock-anchor-horizontal {\n      display: inline;\n    }\n\n    #togetherjs-dock-anchor-horizontal img {\n      width:31px;\n      height:7px;\n      padding:0px 2px 2px 2px;\n      pointer-events: none;\n    }\n  }\n\n  &.togetherjs-dock-left {\n    padding: 0;\n    bottom: 60px;\n    left: 5px;\n    border-radius: 0 @border-radius @border-radius 0;\n    height: @long-side - 46px;\n    width: @short-side;\n    #togetherjs-dock-anchor-vertical {\n      display: none;\n    }\n    #togetherjs-dock-anchor-horizontal {\n      display: inline;\n    }\n\n    #togetherjs-dock-anchor-horizontal img {\n      width: 6px;\n      height: 6px;\n      padding: 7px 2px 2px 2px\n    }\n  }\n\n  &.togetherjs-dock-top {\n    padding: 0;\n    top: 40px;\n    left: 50%;\n    margin-left: -(@long-side / 2);\n    border-radius: @border-radius @border-radius 0 0;\n    height: @short-side;\n    width: @long-side;\n    #togetherjs-buttons, #togetherjs-dock-anchor {\n      display: inline;\n    }\n    #togetherjs-dock-anchor-vertical {\n      display: inline;\n    }\n    #togetherjs-dock-anchor-horizontal {\n      display: none;\n    }\n    #togetherjs-dock-anchor-vertical img {\n      width: 6px;\n      height: 6px;\n      padding: 2px;\n    }\n  }\n}\n\n/* Arrows for pointing */\n\n.togetherjs-arrow {\n  position: absolute;\n  border: 2px solid #f00;\n  z-index: @z-index + 10;\n  padding: 0;\n  margin: 0;\n  .transform-origin(top left);\n}\n\n.togetherjs-chat-message.togetherjs-arrow-message {\n  border: 2px solid #f00;\n}\n\n/* Shared cursors */\n\n.togetherjs-cursor svg {\n  -webkit-filter: drop-shadow(1px 3px 2px rgba(0,0,0,0.3));\n  -webkit-transform: rotate(-10deg);\n}\n\n.togetherjs-cursor-img {\n  position: relative;\n  top: 0;\n}\n\n.togetherjs-cursor img {\n  width: 20px;\n  -webkit-filter: drop-shadow( 0px 2px 1px rgba(0,0,0,0.2) );\n  /*FIX ME, moz filter not working...*/\n  -moz-filter: drop-shadow( 0px 2px 1px rgba(0,0,0,0.2) );\n          filter: drop-shadow( 0px 2px 1px rgba(0,0,0,0.2) );\n}\n\n.togetherjs-cursor {\n  position: absolute;\n  z-index: @z-index - 1;\n  font-size: 28px;\n  font-weight: bolder;\n  /* This magic CSS rule makes this element basically invisible to clicks/etc:\n  (good on all but IE: http://caniuse.com/pointer-events */\n  pointer-events: none;\n  &:hover{\n    cursor:pointer;\n  }\n\n  /*FIXME: maybe these should use position: fixed so the cursor\n  stays stuck to the top of the screen until the appropriate time\n  (when .togetherjs-scrolled-above/below is removed)?*/\n  &.togetherjs-scrolled-above {\n    position: fixed;\n    svg {\n      -webkit-transition-duration: 0.8s;\n      -webkit-transition-property: -webkit-transform;\n      -webkit-transform: rotate(20deg);\n      transition-duration: 0.8s;\n      transition-property: transform;\n      transform: rotate(20deg);\n    }\n    .togetherjs-cursor-down {\n      display: none;\n    }\n  }\n\n  &.togetherjs-scrolled-below {\n    position: fixed;\n    svg {\n      -webkit-transition-duration: 0.8s;\n      -webkit-transition-property: -webkit-transform;\n      -webkit-transform: rotate(-150deg);\n      transition-duration: 0.8s;\n      transition-property: transform;\n      transform: rotate(-150deg);\n    }\n    .togetherjs-cursor-up {\n      display: none;\n    }\n  }\n\n  &.togetherjs-scrolled-normal {\n    svg {\n      -webkit-transition-duration: 0.8s;\n      -webkit-transition-property: -webkit-transform;\n      -webkit-transform: rotate(-10deg);\n      transition-duration: 0.8s;\n      transition-property: transform;\n      transform: rotate(-10deg);\n    }\n    .togetherjs-cursor-up, .togetherjs-cursor-down {\n      display: none;\n    }\n  }\n\n  .togetherjs-cursor-container {\n    opacity:0.9;\n    white-space: nowrap;\n    font-family: @default-font;\n    font-size: 40%;\n    position: relative;\n    top: 5px;\n    left: 15px;\n    padding: 8px;\n    border-radius: 4px;\n    box-shadow: 0 1px 1px rgba(0,0,0,0.2);\n    border: 1px solid rgba(0,0,0,0.2);\n    -moz-box-shadow:    0px 2px 4px 0px rgba(0,0,0,0.50);\n    -webkit-box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.50);\n    box-shadow:         0px 2px 4px 0px rgba(0,0,0,0.50);\n  }\n}\n\n@start-click: 10px;\n@end-click: 40px;\n\n.togetherjs-click {\n  position: absolute;\n  z-index: @z-index - 2;\n  pointer-events: none;\n  width: @start-click;\n  height: @start-click;\n  margin: (-@start-click/2) 0 0 (-@start-click/2);\n  border-radius: @start-click/2;\n  border: 3px solid rgba(288, 58, 41, 1);\n  .transition(~\"width 2s, height 2s, margin 2s, border 2s\");\n\n  // This class is immediately applied for the purpose of transitioning:\n  &.togetherjs-clicking {\n    width: @end-click;\n    height: @end-click;\n    margin: (-@end-click/2) 0 0 (-@end-click/2);\n    border-radius: @end-click/2;\n    border: 3px solid rgba(0, 0, 0, 0);\n  }\n}\n\n#togetherjs-starter .togetherjs-running {\n  background-color: #f00;\n  color: #fff;\n  border-radius: 4px;\n  border: 3px outset #d00;\n  /*FIXME: add gradient*/\n}\n\n/* Modals */\n\n#togetherjs-modal-background {\n  position: fixed;\n  background-color: #000;\n  opacity: 0.5;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  left: 0;\n  z-index: @z-index + 2;\n}\n\n.togetherjs {\n\n  .togetherjs-modal {\n    .togetherjs.togetherjs-window;\n    @height: 20em;\n    @width: 300px;\n    border-radius:5px !important;\n    position: fixed;\n    z-index: @z-index+3;\n    top: 50%;\n    left: 50%;\n    margin-left: -(@width/2);\n    width: @width;\n    margin-top: -(@height/2);\n    &.togetherjs-modal-wide {\n      width: 550px;\n      margin-left: -284px;\n      height: 530px;\n      // FIXME: Why isn't -35% the right number?\n      // I can't for the life of me figure out why 20% is right\n      margin-top: -(550px / 2);\n    }\n  }\n\n  .togetherjs-modal {\n    section.togetherjs-buttons {\n      /*position: absolute;*/\n      bottom: 0;\n      background: #F2F2F2;\n      width: 294px;\n      padding: 10px;\n      text-align: right;\n      border-bottom-right-radius: 4px;\n      border-bottom-left-radius: 4px;\n      margin-left: -7px;\n      margin-bottom: 0px;\n      border-top:1px solid #E1E1E1;\n    }\n  }\n  .togetherjs-modal-wide section.togetherjs-buttons {\n    width: 544px;\n    text-align: center !important;\n    position: absolute;\n  }\n\n  .togetherjs-walkthrough-slide {\n    padding: 0 30px 0 30px;\n    text-align:center;\n  }\n\n  .togetherjs-walkthrough-slide p {\n    margin:18px auto;\n    width:400px;\n  }\n\n  .togetherjs-walkthrough-slide iframe {\n    border-radius:4px;\n  }\n\n  section.togetherjs-walkthrough-slide .togetherjs-walkthrough-main-image .togetherjs-walkthrough-avatar-section {\n    margin-top:115px;\n  }\n\n  .togetherjs-avatar-preview {\n    float:left;\n    margin-left:82px;\n  }\n\n  .togetherjs-avatar-upload-input {\n    float:right;\n    margin-right:82px;\n    margin-top:19px;\n  }\n\n  .togetherjs-save-settings {\n    margin-top:239px;\n  }\n\n  section.togetherjs-walkthrough-slide .togetherjs-walkthrough-avatar {\n    width: 80px;\n    height: 80px;\n    position: absolute;\n    left: 44%;\n    top: 30%;\n    border-radius: 4px 4px 4px 4px;\n    border: 2px solid rgb(204, 204, 204);\n    background: none repeat scroll 0% 0% rgb(0, 0, 0);\n    &:hover {\n      cursor:pointer;\n      border: 2px solid rgb(204, 204, 204, 0.2);\n    }\n  }\n\n  section.togetherjs-walkthrough-slide input.togetherjs-self-name {\n    position: absolute;\n    top: 50%;\n    left: 29%;\n    font-size: 14px;\n    padding: 6px 6px 6px;\n    border-radius: 4px 4px 4px 4px;\n    border: 1px solid rgb(204, 204, 204);\n    box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.1) inset;\n    font-family: openSansRegular, Helvetica, sans-serif;\n    margin: -20px 0px;\n  }\n\n  section.togetherjs-walkthrough-slide .togetherjs-swatch {\n    width: 32px;\n    height: 32px;\n    background: none repeat scroll 0% 0% rgb(0, 0, 0);\n    position: absolute;\n    top: 46.2%;\n    right: 29%;\n    border-radius: 4px 4px 4px 4px;\n    border: 1px solid rgb(204, 204, 204);\n    &:hover {\n      cursor:pointer;\n      border: 1px solid rgba(204, 204, 204,0.2);\n    }\n  }\n\n  section.togetherjs-walkthrough-slide span.togetherjs-walkthrough-sendlink {\n    top: 44%;\n    position: relative;\n  }\n\n  section.togetherjs-walkthrough-slide input.togetherjs-share-link {\n    top: 44%;\n    position: relative;\n  }\n\n  .togetherjs-walkthrough-main-image {\n    width:400px;\n    height:300px;\n    background:rgba(216,216,216,0.1);\n    border-radius:4px;\n    border:1px solid rgba(151,151,151,0.1);\n    margin:0 auto;\n  }\n\n  .togetherjs-walkthrough-main-image img {\n    width:400px;\n    height:300px;\n  }\n\n  .togetherjs-walkthrough-arrow() {\n    cursor: pointer;\n    width:19px;\n    height:36px;\n    background-repeat:no-repeat;\n    background-size:60% 60%;\n    margin-right:28px;\n    margin-top:28%;\n    &.togetherjs-disabled {\n      cursor: default;\n      opacity: 0.2;\n    }\n  }\n\n  .togetherjs-walkthrough-arrow-l() {\n    cursor: pointer;\n    width:19px;\n    height:36px;\n    background-repeat:no-repeat;\n    background-size:60% 60%;\n    margin-left:36px;\n    margin-top:28%;\n    &.togetherjs-disabled {\n      cursor: default;\n      opacity: 0.2;\n    }\n  }\n\n  #togetherjs-walkthrough input, textarea, .uneditable-input {\n    width: 177px;\n  }\n\n  #togetherjs-walkthrough select, input[type=\"file\"] {\n    height: 30px;\n    line-height: 0px;\n  }\n\n  #togetherjs-walkthrough-previous {\n    .togetherjs-walkthrough-arrow-l;\n    background-image: url('./images/icn-walkthrough-arrow-l.png');\n    float:left;\n    &:hover {\n      background-image: url('./images/icn-walkthrough-arrow-l-hover.png');\n    }\n  }\n\n  #togetherjs-walkthrough-next {\n    .togetherjs-walkthrough-arrow;\n    background-image: url('./images/icn-walkthrough-arrow-r.png');\n    float:right;\n    &:hover {\n      background-image: url('./images/icn-walkthrough-arrow-r-hover.png');\n    }\n  }\n\n  #togetherjs-walkthrough-progress {\n    width: 537px;\n    position: absolute;\n    bottom: 66px;\n    text-align:center;\n  }\n\n  .togetherjs-walkthrough-slide-progress {\n    cursor: pointer;\n    padding: 0 5px 0 5px;\n    color: #D8D8D8;\n    font-size:20px;\n    &.togetherjs-active {\n      color: #9C9C9C;\n    }\n    &:hover {\n      color: #9C9C9C;\n    }\n  }\n\n}\n\n/* Animations */\n\n/* Inspired by https://github.com/daneden/animate.css */\n\n@-webkit-keyframes togetherjs-pulse {\n  0% { -webkit-transform: scale(1); }\n  50% { -webkit-transform: scale(1.1); }\n  100% { -webkit-transform: scale(1); }\n}\n@-moz-keyframes togetherjs-pulse {\n  0% { -moz-transform: scale(1); }\n  50% { -moz-transform: scale(1.1); }\n  100% { -moz-transform: scale(1); }\n}\n@-o-keyframes togetherjs-pulse {\n  0% { -o-transform: scale(1); }\n  50% { -o-transform: scale(1.1); }\n  100% { -o-transform: scale(1); }\n}\n@keyframes togetherjs-pulse {\n  0% { transform: scale(1); }\n  50% { transform: scale(1.1); }\n  100% { transform: scale(1); }\n}\n.togetherjs-pulse {\n  -webkit-animation-name: togetherjs-pulse;\n  -moz-animation-name: togetherjs-pulse;\n  -o-animation-name: togetherjs-pulse;\n  animation-name: togetherjs-pulse;\n}\n// Note: the 1s is also present in ui.js (ANIMATION_DURATION)\n.togetherjs-animated {\n  -webkit-animation-duration: 1s;\n  -moz-animation-duration: 1s;\n  -o-animation-duration: 1s;\n  animation-duration: 1s;\n  -webkit-animation-fill-mode: both;\n  -moz-animation-fill-mode: both;\n  -o-animation-fill-mode: both;\n  animation-fill-mode: both;\n}\n\n@-webkit-keyframes togetherjs-color-pulse {\n  0% {box-shadow: none;}\n  50% {box-shadow: inset 0 0 2px #0095dd;}\n  100% {box-shadow: none;}\n}\n@-moz-keyframes togetherjs-color-pulse {\n  0% {box-shadow: none;}\n  50% {box-shadow: inset 0 0 2px #0095dd;}\n  100% {box-shadow: none;}\n}\n@-o-keyframes togetherjs-color-pulse {\n  0% {box-shadow: none;}\n  50% {box-shadow: inset 0 0 2px #0095dd;}\n  100% {box-shadow: none;}\n}\n@keyframes togetherjs-color-pulse {\n  0% {box-shadow: none;}\n  50% {box-shadow: inset 0 0 2px #0095dd;}\n  100% {box-shadow: none;}\n}\n.togetherjs-color-pulse {\n  -webkit-animation-name: togetherjs-color-pulse;\n  -moz-animation-name: togetherjs-color-pulse;\n  -o-animation-name: togetherjs-color-pulse;\n  animation-name: togetherjs-color-pulse;\n}\n\n@-webkit-keyframes togetherjs-color-alert {\n  0% {box-shadow: none;}\n  50% {box-shadow: 0 0 5px #0095dd;}\n  100% {box-shadow: none;}\n}\n@-moz-keyframes togetherjs-color-alert {\n  0% {box-shadow: none;}\n  50% {box-shadow: 0 0 5px #0095dd;}\n  100% {box-shadow: none;}\n}\n@-o-keyframes togetherjs-color-alert {\n  0% {box-shadow: none;}\n  50% {box-shadow: 0 0 5px #0095dd;}\n  100% {box-shadow: none;}\n}\n@keyframes togetherjs-color-alert {\n  0% {box-shadow: none;}\n  50% {box-shadow: 0 0 5px #0095dd;}\n  100% {box-shadow: none;}\n}\n.togetherjs-color-alert {\n  -webkit-animation-name: togetherjs-color-alert;\n  -moz-animation-name: togetherjs-color-alert;\n  -o-animation-name: togetherjs-color-alert;\n  animation-name: togetherjs-color-alert;\n  animation-iteration-count: infinite;\n  -webkit-animation-iteration-count: infinite;\n  -moz-animation-iteration-count: infinite;\n  -o-animation-iteration-count: infinite;\n}\n\n#togetherjs-profile-arrow {\n  position: absolute;\n  width: 12px;\n  height: 12px;\n  left: 42px;\n  top: 46px;\n  background: url('./images/icn-gear.png');\n  background-size: 12px 12px;\n  background-repeat: no-repeat;\n}\n\n#togetherjs-pick-color {\n  width: 100px;\n  height: 76px;\n  margin-left: -35px;\n  position: absolute;\n  margin-top:25px;\n  background-color: #fff;\n  z-index: @z-index + 4;\n  // FIXME: shouldn't be one-off like this:\n  border: 1px solid #979797;\n  border-radius: 4px;\n  padding: 5px;\n  .togetherjs-swatch {\n    cursor: pointer;\n    display: inline-block;\n    height: 12px;\n    width: 12px;\n    border: 1px solid;\n    border-radius: 1px;\n    margin: 4px;\n    // Border and background color gets set dynamically\n    &.togetherjs-swatch-active {\n      border: 3px solid;\n      border-radius: 3px;\n    }\n    &:hover {\n      border: 2px solid rgba(0,0,0,0.5);\n      // Adjusting down the size, so that the total size (height or\n      // width + border) is the same as the non-hover swatch:\n      height: 10px;\n      width: 10px;\n      border-radius: 3px;\n    }\n  }\n}\n\n.togetherjs-focus {\n  position: absolute;\n  pointer-events: none;\n  z-index: @z-index - 1;\n  opacity: 0.4;\n  border: 3px solid;\n  margin: -3px; // border should be outside the specified box\n}\n\n.togetherjs-only-mobile {\n  display: none;\n}\n\n@media screen and (max-device-width: 480px) {\n  @import \"mobile.less\";\n}\n\n/* We set this class on the <body> element when that last media query won't work\n   but we detect in Javascript that the client should be treated as mobile */\n.togetherjs-mobile-browser {\n  @import \"mobile.less\";\n}\n"
  },
  {
    "path": "togetherjs/ui.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"require\", \"jquery\", \"util\", \"session\", \"templates\", \"templating\", \"linkify\", \"peers\", \"windowing\", \"tinycolor\", \"elementFinder\", \"visibilityApi\"], function (require, $, util, session, templates, templating, linkify, peers, windowing, tinycolor, elementFinder, visibilityApi) {\n  var ui = util.Module('ui');\n  var assert = util.assert;\n  var AssertionError = util.AssertionError;\n  var chat;\n  var $window = $(window);\n  // This is also in togetherjs.less, as @button-height:\n  var BUTTON_HEIGHT = 60 + 1; // 60 is button height, 1 is border\n  // chat TextArea\n  var TEXTAREA_LINE_HEIGHT = 20; // in pixels\n  var TEXTAREA_MAX_LINES = 5;\n  // This is also in togetherjs.less, under .togetherjs-animated\n  var ANIMATION_DURATION = 1000;\n  // Time the new user window sticks around until it fades away:\n  var NEW_USER_FADE_TIMEOUT = 5000;\n  // This is set when an animation will keep the UI from being ready\n  // (until this time):\n  var finishedAt = null;\n  // Time in milliseconds for the dock to animate out:\n  var DOCK_ANIMATION_TIME = 300;\n  // If two chat messages come from the same person in this time\n  // (milliseconds) then they are collapsed into one message:\n  var COLLAPSE_MESSAGE_LIMIT = 5000;\n\n  var COLORS = [\n    \"#8A2BE2\", \"#7FFF00\", \"#DC143C\", \"#00FFFF\", \"#8FBC8F\", \"#FF8C00\", \"#FF00FF\",\n    \"#FFD700\", \"#F08080\", \"#90EE90\", \"#FF6347\"];\n\n  // This would be a circular import, but we just need the chat module sometime\n  // after everything is loaded, and this is sure to complete by that time:\n  require([\"chat\"], function (c) {\n    chat = c;\n  });\n\n  /* Displays some toggleable element; toggleable elements have a\n     data-toggles attribute that indicates what other elements should\n     be hidden when this element is shown. */\n  ui.displayToggle = function (el) {\n    el = $(el);\n    assert(el.length, \"No element\", arguments[0]);\n    var other = $(el.attr(\"data-toggles\"));\n    assert(other.length, \"Cannot toggle\", el[0], \"selector\", other.selector);\n    other.hide();\n    el.show();\n  };\n\n  function panelPosition() {\n    var iface = $(\"#togetherjs-dock\");\n    if (iface.hasClass(\"togetherjs-dock-right\")) {\n      return \"right\";\n    } else if (iface.hasClass(\"togetherjs-dock-left\")) {\n      return \"left\";\n    } else if (iface.hasClass(\"togetherjs-dock-bottom\")) {\n      return \"bottom\";\n    } else {\n      throw new AssertionError(\"#togetherjs-dock doesn't have positioning class\");\n    }\n  }\n\n  ui.container = null;\n\n  // This is used for some signalling when ui.prepareUI and/or\n  // ui.activateUI is called before the DOM is fully loaded:\n  var deferringPrepareUI = null;\n\n  function deferForContainer(func) {\n    /* Defers any calls to func() until after ui.container is set\n       Function cannot have a return value (as sometimes the call will\n       become async).  Use like:\n\n       method: deferForContainer(function (args) {...})\n       */\n    return function () {\n      if (ui.container) {\n        func.apply(this, arguments);\n      }\n      var self = this;\n      var args = Array.prototype.slice.call(arguments);\n      session.once(\"ui-ready\", function () {\n        func.apply(self, args);\n      });\n    };\n  }\n\n  // This is called before activateUI; it doesn't bind anything, but does display\n  // the dock\n  // FIXME: because this module has lots of requirements we can't do\n  // this before those requirements are loaded.  Maybe worth splitting\n  // this out?  OTOH, in production we should have all the files\n  // combined so there's not much problem loading those modules.\n  ui.prepareUI = function () {\n    if (! (document.readyState == \"complete\" || document.readyState == \"interactive\")) {\n      // Too soon!  Wait a sec...\n      deferringPrepareUI = \"deferring\";\n      document.addEventListener(\"DOMContentLoaded\", function () {\n        var d = deferringPrepareUI;\n        deferringPrepareUI = null;\n        ui.prepareUI();\n        // This happens when ui.activateUI is called before the document has been\n        // loaded:\n        if (d == \"activate\") {\n          ui.activateUI();\n        }\n      });\n      return;\n    }\n    var container = ui.container = $(templates(\"interface\"));\n    assert(container.length);\n    $(\"body\").append(container);\n    fixupAvatars(container);\n    if (session.firstRun && TogetherJS.startTarget) {\n      // Time at which the UI will be fully ready:\n      // (We have to do this because the offset won't be quite right\n      // until the animation finishes - attempts to calculate the\n      // offset without taking into account CSS transforms have so far\n      // failed.)\n      var timeoutSeconds = DOCK_ANIMATION_TIME / 1000;\n      finishedAt = Date.now() + DOCK_ANIMATION_TIME + 50;\n      setTimeout(function () {\n        finishedAt = Date.now() + DOCK_ANIMATION_TIME + 40;\n        var iface = container.find(\"#togetherjs-dock\");\n        var start = iface.offset();\n        var pos = $(TogetherJS.startTarget).offset();\n        pos.top = Math.floor(pos.top - start.top);\n        pos.left = Math.floor(pos.left - start.left);\n        var translate = \"translate(\" + pos.left + \"px, \" + pos.top + \"px)\";\n        iface.css({\n          MozTransform: translate,\n          WebkitTransform: translate,\n          transform: translate,\n          opacity: \"0.0\"\n        });\n        setTimeout(function () {\n          // We keep recalculating because the setTimeout times aren't always so accurate:\n          finishedAt = Date.now() + DOCK_ANIMATION_TIME + 20;\n          var transition = \"transform \" + timeoutSeconds + \"s ease-out, \";\n          transition += \"opacity \" + timeoutSeconds + \"s ease-out\";\n          iface.css({\n            opacity: \"1.0\",\n            MozTransition: \"-moz-\" + transition,\n            MozTransform: \"translate(0, 0)\",\n            WebkitTransition: \"-webkit-\" + transition,\n            WebkitTransform: \"translate(0, 0)\",\n            transition: transition,\n            transform: \"translate(0, 0)\"\n          });\n          setTimeout(function () {\n            finishedAt = null;\n            iface.attr(\"style\", \"\");\n          }, 510);\n        }, 5);\n      }, 5);\n    }\n    if (TogetherJS.startTarget) {\n      var el = $(TogetherJS.startTarget);\n      var text = el.text().toLowerCase().replace(/\\s+/g, \" \");\n      text = text.replace(/^\\s*/, \"\").replace(/\\s*$/, \"\");\n      if (text == \"start togetherjs\") {\n        el.attr(\"data-end-togetherjs-html\", \"End TogetherJS\");\n      }\n      if (el.attr(\"data-end-togetherjs-html\")) {\n        el.attr(\"data-start-togetherjs-html\", el.html());\n        el.html(el.attr(\"data-end-togetherjs-html\"));\n      }\n      el.addClass(\"togetherjs-started\");\n    }\n    ui.container.find(\".togetherjs-window > header, .togetherjs-modal > header\").each(function () {\n      $(this).append($('<button class=\"togetherjs-close\"></button>'));\n    });\n\n    TogetherJS.config.track(\"disableWebRTC\", function (hide, previous) {\n      if (hide && ! previous) {\n        ui.container.find(\"#togetherjs-audio-button\").hide();\n        adjustDockSize(-1);\n      } else if ((! hide) && previous) {\n        ui.container.find(\"#togetherjs-audio-button\").show();\n        adjustDockSize(1);\n      }\n    });\n\n  };\n\n  // After prepareUI, this actually makes the interface live.  We have\n  // to do this later because we call prepareUI when many components\n  // aren't initialized, so we don't even want the user to be able to\n  // interact with the interface.  But activateUI is called once\n  // everything is loaded and ready for interaction.\n  ui.activateUI = function () {\n    if (deferringPrepareUI) {\n      console.warn(\"ui.activateUI called before document is ready; waiting...\");\n      deferringPrepareUI = \"activate\";\n      return;\n    }\n    if (! ui.container) {\n      ui.prepareUI();\n    }\n    var container = ui.container;\n\n    //create the overlay\n    if($.browser.mobile) {\n      // $(\"body\").append( \"\\x3cdiv class='overlay' style='position: absolute; top: 0; left: 0; background-color: rgba(0,0,0,0); width: 120%; height: 100%; z-index: 1000; margin: -10px'>\\x3c/div>\" );\n    }\n\n    // The share link:\n    ui.prepareShareLink(container);\n    container.find(\"input.togetherjs-share-link\").on(\"keydown\", function (event) {\n      if (event.which == 27) {\n        windowing.hide(\"#togetherjs-share\");\n        return false;\n      }\n      return undefined;\n    });\n    session.on(\"shareId\", updateShareLink);\n\n    // The chat input element:\n    var input = container.find(\"#togetherjs-chat-input\");\n    input.bind(\"keydown\", function (event) {\n      if (event.which == 13 && !event.shiftKey) { // Enter without Shift pressed\n        submitChat();\n        return false;\n      }\n      if (event.which == 27) { // Escape\n        windowing.hide(\"#togetherjs-chat\");\n        return false;\n      }\n    });\n\n    function submitChat() {\n      var val = input.val();\n      if ($.trim(val)) {\n        input.val(\"\");\n        // triggering the event manually to avoid the addition of newline character to the textarea:\n        input.trigger(\"input\").trigger(\"propertychange\");\n        chat.submit(val);\n      }\n    }\n    // auto-resize textarea:\n    input.on(\"input propertychange\", function () {\n      var $this = $(this);\n      var actualHeight = $this.height();\n      // reset the height of textarea to remove trailing empty space (used for shrinking):\n      $this.height(TEXTAREA_LINE_HEIGHT);\n      this.scrollTop = 0;\n      // scroll to bottom:\n      this.scrollTop = 9999;\n      var newHeight = this.scrollTop + $this.height();\n      var maxHeight = TEXTAREA_MAX_LINES * TEXTAREA_LINE_HEIGHT;\n      if (newHeight > maxHeight) {\n        newHeight = maxHeight;\n        this.style.overflowY = \"scroll\";\n      } else {\n        this.style.overflowY = \"hidden\";\n      }\n      this.style.height = newHeight + \"px\";\n      var diff = newHeight - actualHeight;\n      $(\"#togetherjs-chat-input-box\").height($(\"#togetherjs-chat-input-box\").height() + diff);\n      $(\"#togetherjs-chat-messages\").height($(\"#togetherjs-chat-messages\").height() - diff);\n      return false;\n    });\n\n    util.testExpose({submitChat: submitChat});\n\n    // Moving the window:\n    // FIXME: this should probably be stickier, and not just move the window around\n    // so abruptly\n    var anchor = container.find(\"#togetherjs-dock-anchor\");\n    assert(anchor.length);\n    // FIXME: This is in place to temporarily disable dock dragging:\n    anchor = container.find(\"#togetherjs-dock-anchor-disabled\");\n    anchor.mousedown(function (event) {\n      var iface = $(\"#togetherjs-dock\");\n      // FIXME: switch to .offset() and pageX/Y\n      var startPos = panelPosition();\n      function selectoff() {\n        return false;\n      }\n      function mousemove(event2) {\n        var fromRight = $window.width() + window.pageXOffset - event2.pageX;\n        var fromLeft = event2.pageX - window.pageXOffset;\n        var fromBottom = $window.height() + window.pageYOffset - event2.pageY;\n        // FIXME: this is to temporarily disable the bottom view:\n        fromBottom = 10000;\n\n        var pos;\n        if (fromLeft < fromRight && fromLeft < fromBottom) {\n          pos = \"left\";\n        } else if (fromRight < fromLeft && fromRight < fromBottom) {\n          pos = \"right\";\n        } else {\n          pos = \"bottom\";\n        }\n        iface.removeClass(\"togetherjs-dock-left\");\n        iface.removeClass(\"togetherjs-dock-right\");\n        iface.removeClass(\"togetherjs-dock-bottom\");\n        iface.addClass(\"togetherjs-dock-\" + pos);\n        if (startPos && pos != startPos) {\n          windowing.hide();\n          startPos = null;\n        }\n      }\n      $(document).bind(\"mousemove\", mousemove);\n      // If you don't turn selection off it will still select text, and show a\n      // text selection cursor:\n      $(document).bind(\"selectstart\", selectoff);\n      // FIXME: it seems like sometimes we lose the mouseup event, and it's as though\n      // the mouse is stuck down:\n      $(document).one(\"mouseup\", function () {\n        $(document).unbind(\"mousemove\", mousemove);\n        $(document).unbind(\"selectstart\", selectoff);\n      });\n      return false;\n    });\n\n    function openDock() {\n      $('.togetherjs-window').animate({\n        opacity: 1\n      });\n      $('#togetherjs-dock-participants').animate({\n        opacity: 1\n      });\n      $('#togetherjs-dock #togetherjs-buttons').animate({\n        opacity: 1\n      });\n\n      //for iphone\n      if($(window).width() < 480) {\n        $('.togetherjs-dock-right').animate({\n          width: \"204px\"\n        }, {\n          duration:60, easing:\"linear\"\n        });\n      }\n\n      //for ipad\n      else {\n        $('.togetherjs-dock-right').animate({\n          width: \"27%\"\n        }, {\n          duration:60, easing:\"linear\"\n        });\n      }\n\n\n      // add bg overlay\n      // $(\"body\").append( \"\\x3cdiv class='overlay' style='position: absolute; top: 0; left: -2px; background-color: rgba(0,0,0,0.5); width: 200%; height: 400%; z-index: 1000; margin: 0px;'>\\x3c/div>\" );\n\n      //disable vertical scrolling\n      // $(\"body\").css({\n      //   \"position\": \"fixed\",\n      //   top: 0,\n      //   left: 0\n      // });\n\n      //replace the anchor icon\n      var src = \"/togetherjs/images/togetherjs-logo-close.png\";\n      $(\"#togetherjs-dock-anchor #togetherjs-dock-anchor-horizontal img\").attr(\"src\", src);\n    }\n\n    function closeDock() {\n      //enable vertical scrolling\n      $(\"body\").css({\n        \"position\": \"\",\n        top: \"\",\n        left: \"\"\n      });\n\n      //replace the anchor icon\n      var src = \"/togetherjs/images/togetherjs-logo-open.png\";\n      $(\"#togetherjs-dock-anchor #togetherjs-dock-anchor-horizontal img\").attr(\"src\", src);\n\n      $('.togetherjs-window').animate({\n        opacity: 0\n      });\n      $('#togetherjs-dock-participants').animate({\n        opacity: 0\n      });\n      $('#togetherjs-dock #togetherjs-buttons').animate({\n        opacity: 0\n      });\n      $('.togetherjs-dock-right').animate({\n        width: \"40px\"\n      }, {\n        duration:60, easing:\"linear\"\n      });\n\n      // remove bg overlay\n      //$(\".overlay\").remove();\n    }\n\n    // Setting the anchor button + dock mobile actions\n    if($.browser.mobile) {\n\n      // toggle the audio button\n      $(\"#togetherjs-audio-button\").click(function () {\n        windowing.toggle(\"#togetherjs-rtc-not-supported\");\n      });\n\n      // toggle the profile button\n      $(\"#togetherjs-profile-button\").click(function () {\n        windowing.toggle(\"#togetherjs-menu-window\");\n      });\n\n      // $(\"body\").append( \"\\x3cdiv class='overlay' style='position: absolute; top: 0; left: -2px; background-color: rgba(0,0,0,0.5); width: 200%; height: 400%; z-index: 1000; margin: 0px'>\\x3c/div>\" );\n\n      //disable vertical scrolling\n      // $(\"body\").css({\n      //   \"position\": \"fixed\",\n      //   top: 0,\n      //   left: 0\n      // });\n\n      //replace the anchor icon\n      var src = \"/togetherjs/images/togetherjs-logo-close.png\";\n      $(\"#togetherjs-dock-anchor #togetherjs-dock-anchor-horizontal img\").attr(\"src\", src);\n\n      $(\"#togetherjs-dock-anchor\").toggle(function() {\n          closeDock();\n        },function(){\n          openDock();\n      });\n    }\n\n    $(\"#togetherjs-share-button\").click(function () {\n      windowing.toggle(\"#togetherjs-share\");\n    });\n\n    $(\"#togetherjs-profile-button\").click(function (event) {\n      if ($.browser.mobile) {\n        windowing.show(\"#togetherjs-menu-window\");\n        return false;\n      }\n      toggleMenu();\n      event.stopPropagation();\n      return false;\n    });\n\n    $(\"#togetherjs-menu-feedback, #togetherjs-menu-feedback-button\").click(function(){\n      windowing.hide();\n      hideMenu();\n      windowing.show(\"#togetherjs-feedback-form\");\n    });\n\n    $(\"#togetherjs-menu-help, #togetherjs-menu-help-button\").click(function () {\n      windowing.hide();\n      hideMenu();\n      require([\"walkthrough\"], function (walkthrough) {\n        windowing.hide();\n        walkthrough.start(false);\n      });\n    });\n\n    $(\"#togetherjs-menu-update-name\").click(function () {\n      var input = $(\"#togetherjs-menu .togetherjs-self-name\");\n      input.css({\n        width: $(\"#togetherjs-menu\").width() - 32 + \"px\"\n      });\n      ui.displayToggle(\"#togetherjs-menu .togetherjs-self-name\");\n      $(\"#togetherjs-menu .togetherjs-self-name\").focus();\n    });\n\n    $(\"#togetherjs-menu-update-name-button\").click(function () {\n      windowing.show(\"#togetherjs-edit-name-window\");\n      $(\"#togetherjs-edit-name-window input\").focus();\n    });\n\n    $(\"#togetherjs-menu .togetherjs-self-name\").bind(\"keyup change\", function (event) {\n      console.log(\"alrighty\", event);\n      if (event.which == 13) {\n        ui.displayToggle(\"#togetherjs-self-name-display\");\n        return;\n      }\n      var val = $(\"#togetherjs-menu .togetherjs-self-name\").val();\n      console.log(\"values!!\", val);\n      if (val) {\n        peers.Self.update({name: val});\n      }\n    });\n\n    $(\"#togetherjs-menu-update-avatar, #togetherjs-menu-update-avatar-button\").click(function () {\n      hideMenu();\n      windowing.show(\"#togetherjs-avatar-edit\");\n    });\n\n    $(\"#togetherjs-menu-end, #togetherjs-menu-end-button\").click(function () {\n      hideMenu();\n      windowing.show(\"#togetherjs-confirm-end\");\n    });\n\n    $(\"#togetherjs-end-session\").click(function () {\n      session.close();\n      //$(\".overlay\").remove();\n\n    });\n\n    $(\"#togetherjs-menu-update-color\").click(function () {\n      var picker = $(\"#togetherjs-pick-color\");\n      if (picker.is(\":visible\")) {\n        picker.hide();\n        return;\n      }\n      picker.show();\n      bindPicker();\n      picker.find(\".togetherjs-swatch-active\").removeClass(\"togetherjs-swatch-active\");\n      picker.find(\".togetherjs-swatch[data-color=\\\"\" + peers.Self.color + \"\\\"]\").addClass(\"togetherjs-swatch-active\");\n    });\n\n    $(\"#togetherjs-pick-color\").click(\".togetherjs-swatch\", function (event) {\n      var swatch = $(event.target);\n      var color = swatch.attr(\"data-color\");\n      peers.Self.update({\n        color: color\n      });\n      event.stopPropagation();\n      return false;\n    });\n\n    $(\"#togetherjs-pick-color\").click(function (event) {\n      $(\"#togetherjs-pick-color\").hide();\n      event.stopPropagation();\n      return false;\n    });\n\n    COLORS.forEach(function (color) {\n      var el = templating.sub(\"swatch\");\n      el.attr(\"data-color\", color);\n      var darkened = tinycolor.darken(color);\n      el.css({\n        backgroundColor: color,\n        borderColor: darkened\n      });\n      $(\"#togetherjs-pick-color\").append(el);\n    });\n\n    $(\"#togetherjs-chat-button\").click(function () {\n      windowing.toggle(\"#togetherjs-chat\");\n    });\n\n    session.on(\"display-window\", function (id, element) {\n      if (id == \"togetherjs-chat\") {\n        if (! $.browser.mobile) {\n          $(\"#togetherjs-chat-input\").focus();\n        }\n      } else if (id == \"togetherjs-share\") {\n        var link = element.find(\"input.togetherjs-share-link\");\n        if (link.is(\":visible\")) {\n          link.focus().select();\n        }\n      }\n    });\n\n    container.find(\"#togetherjs-chat-notifier\").click(function (event) {\n      if ($(event.target).is(\"a\") || container.is(\".togetherjs-close\")) {\n        return;\n      }\n      windowing.show(\"#togetherjs-chat\");\n    });\n\n    // FIXME: Don't think this makes sense\n    $(\".togetherjs header.togetherjs-title\").each(function (index, item) {\n      var button = $('<button class=\"togetherjs-minimize\"></button>');\n      button.click(function (event) {\n        var window = button.closest(\".togetherjs-window\");\n        windowing.hide(window);\n      });\n      $(item).append(button);\n    });\n\n    $(\"#togetherjs-avatar-done\").click(function () {\n      ui.displayToggle(\"#togetherjs-no-avatar-edit\");\n    });\n\n    $(\"#togetherjs-self-color\").css({backgroundColor: peers.Self.color});\n\n    var avatar = peers.Self.avatar;\n    if (avatar) {\n      $(\"#togetherjs-self-avatar\").attr(\"src\", avatar);\n    }\n\n    var starterButton = $(\"#togetherjs-starter button\");\n    starterButton.click(function () {\n      windowing.show(\"#togetherjs-about\");\n    }).addClass(\"togetherjs-running\");\n    if (starterButton.text() == \"Start TogetherJS\") {\n      starterButton.attr(\"data-start-text\", starterButton.text());\n      starterButton.text(\"End TogetherJS Session\");\n    }\n\n    ui.activateAvatarEdit(container, {\n      onSave: function () {\n        windowing.hide(\"#togetherjs-avatar-edit\");\n      }\n    });\n\n    TogetherJS.config.track(\"inviteFromRoom\", function (inviter, previous) {\n      if (inviter) {\n        container.find(\"#togetherjs-invite\").show();\n      } else {\n        container.find(\"#togetherjs-invite\").hide();\n      }\n    });\n\n    container.find(\"#togetherjs-menu-refresh-invite\").click(refreshInvite);\n    container.find(\"#togetherjs-menu-invite-anyone\").click(function () {\n      invite(null);\n    });\n\n    // The following lines should be at the end of this function\n    // (new code goes above)\n    session.emit(\"new-element\", ui.container);\n\n    if (finishedAt && finishedAt > Date.now()) {\n      setTimeout(function () {\n        finishedAt = null;\n        session.emit(\"ui-ready\", ui);\n      }, finishedAt - Date.now());\n    } else {\n      session.emit(\"ui-ready\", ui);\n    }\n\n  }; // End ui.activateUI()\n\n  ui.activateAvatarEdit = function (container, options) {\n    options = options || {};\n    var pendingImage = null;\n\n    container.find(\".togetherjs-avatar-save\").prop(\"disabled\", true);\n\n    container.find(\".togetherjs-avatar-save\").click(function () {\n      if (pendingImage) {\n        peers.Self.update({avatar: pendingImage});\n        container.find(\".togetherjs-avatar-save\").prop(\"disabled\", true);\n        if (options.onSave) {\n          options.onSave();\n        }\n      }\n    });\n\n    container.find(\".togetherjs-upload-avatar\").on(\"change\", function () {\n      util.readFileImage(this).then(function (url) {\n        sizeDownImage(url).then(function (smallUrl) {\n          pendingImage = smallUrl;\n          container.find(\".togetherjs-avatar-preview\").css({\n            backgroundImage: 'url(' + pendingImage + ')'\n          });\n          container.find(\".togetherjs-avatar-save\").prop(\"disabled\", false);\n          if (options.onPending) {\n            options.onPending();\n          }\n        });\n      });\n    });\n\n  };\n\n  function sizeDownImage(imageUrl) {\n    return util.Deferred(function (def) {\n      var $canvas = $(\"<canvas>\");\n      $canvas[0].height = session.AVATAR_SIZE;\n      $canvas[0].width = session.AVATAR_SIZE;\n      var context = $canvas[0].getContext(\"2d\");\n      var img = new Image();\n      img.src = imageUrl;\n      // Sometimes the DOM updates immediately to call\n      // naturalWidth/etc, and sometimes it doesn't; using setTimeout\n      // gives it a chance to catch up\n      setTimeout(function () {\n        var width = img.naturalWidth || img.width;\n        var height = img.naturalHeight || img.height;\n        width = width * (session.AVATAR_SIZE / height);\n        height = session.AVATAR_SIZE;\n        context.drawImage(img, 0, 0, width, height);\n        def.resolve($canvas[0].toDataURL(\"image/png\"));\n      });\n    });\n  }\n\n  function fixupAvatars(container) {\n    /* All <div class=\"togetherjs-person\" /> elements need an element inside,\n       so we add that element here */\n    container.find(\".togetherjs-person\").each(function () {\n      var $this = $(this);\n      var inner = $this.find(\".togetherjs-person-avatar-swatch\");\n      if (! inner.length) {\n        $this.append('<div class=\"togetherjs-person-avatar-swatch\"></div>');\n      }\n    });\n  }\n\n  ui.prepareShareLink = function (container) {\n    container.find(\"input.togetherjs-share-link\").click(function () {\n      $(this).select();\n    }).change(function () {\n      updateShareLink();\n    });\n    container.find(\"a.togetherjs-share-link\").click(function () {\n      // FIXME: this is currently opening up Bluetooth, not sharing a link\n      if (false && window.MozActivity) {\n        var activity = new MozActivity({\n          name: \"share\",\n          data: {\n            type: \"url\",\n            url: $(this).attr(\"href\")\n          }\n        });\n      }\n      // FIXME: should show some help if you actually try to follow the link\n      // like this, instead of simply suppressing it\n      return false;\n    });\n    updateShareLink();\n  };\n\n  // Menu\n\n  function showMenu(event) {\n    var el = $(\"#togetherjs-menu\");\n    assert(el.length);\n    el.show();\n    bindMenu();\n    $(document).bind(\"click\", maybeHideMenu);\n  }\n\n  function bindMenu() {\n    var el = $(\"#togetherjs-menu:visible\");\n    if (el.length) {\n      var bound = $(\"#togetherjs-profile-button\");\n      var boundOffset = bound.offset();\n      el.css({\n        top: boundOffset.top + bound.height() - $window.scrollTop() + \"px\",\n        left: (boundOffset.left + bound.width() - 10 - el.width() - $window.scrollLeft()) + \"px\"\n      });\n    }\n  }\n\n  function bindPicker() {\n    var picker = $(\"#togetherjs-pick-color:visible\");\n    if (picker.length) {\n      var menu = $(\"#togetherjs-menu-update-color\");\n      var menuOffset = menu.offset();\n      picker.css({\n        top: menuOffset.top + menu.height(),\n        left: menuOffset.left\n      });\n    }\n  }\n\n  session.on(\"resize\", function () {\n    bindMenu();\n    bindPicker();\n  });\n\n  function toggleMenu() {\n    if ($(\"#togetherjs-menu\").is(\":visible\")) {\n      hideMenu();\n    } else {\n      showMenu();\n    }\n  }\n\n  function hideMenu() {\n    var el = $(\"#togetherjs-menu\");\n    el.hide();\n    $(document).unbind(\"click\", maybeHideMenu);\n    ui.displayToggle(\"#togetherjs-self-name-display\");\n    $(\"#togetherjs-pick-color\").hide();\n  }\n\n  function maybeHideMenu(event) {\n    var t = event.target;\n    while (t) {\n      if (t.id == \"togetherjs-menu\") {\n        // Click inside the menu, ignore this\n        return;\n      }\n      t = t.parentNode;\n    }\n    hideMenu();\n  }\n\n  function adjustDockSize(buttons) {\n    /* Add or remove spots from the dock; positive number to\n       add button(s), negative number to remove button(s)\n       */\n    assert(typeof buttons == \"number\");\n    assert(buttons && Math.floor(buttons) == buttons);\n    var iface = $(\"#togetherjs-dock\");\n    var newHeight = iface.height() + (BUTTON_HEIGHT * buttons);\n    assert(newHeight >= BUTTON_HEIGHT * 3, \"Height went too low (\", newHeight,\n           \"), should never be less than 3 buttons high (\", BUTTON_HEIGHT * 3, \")\");\n    iface.css({\n      height: newHeight + \"px\"\n    });\n  }\n\n  // Misc\n\n  function updateShareLink() {\n    var input = $(\"input.togetherjs-share-link\");\n    var link = $(\"a.togetherjs-share-link\");\n    var display = $(\"#togetherjs-session-id\");\n    if (! session.shareId) {\n      input.val(\"\");\n      link.attr(\"href\", \"#\");\n      display.text(\"(none)\");\n    } else {\n      input.val(session.shareUrl());\n      link.attr(\"href\", session.shareUrl());\n      display.text(session.shareId);\n    }\n  }\n\n  session.on(\"close\", function () {\n\n    if($.browser.mobile) {\n      // remove bg overlay\n      //$(\".overlay\").remove();\n\n      //after hitting End, reset window draggin\n      $(\"body\").css({\n        \"position\": \"\",\n        top: \"\",\n        left: \"\"\n      });\n\n    }\n\n    if (ui.container) {\n      ui.container.remove();\n      ui.container = null;\n    }\n    // Clear out any other spurious elements:\n    $(\".togetherjs\").remove();\n    var starterButton = $(\"#togetherjs-starter button\");\n    starterButton.removeClass(\"togetherjs-running\");\n    if (starterButton.attr(\"data-start-text\")) {\n      starterButton.text(starterButton.attr(\"data-start-text\"));\n      starterButton.attr(\"data-start-text\", \"\");\n    }\n    if (TogetherJS.startTarget) {\n      var el = $(TogetherJS.startTarget);\n      if (el.attr(\"data-start-togetherjs-html\")) {\n        el.html(el.attr(\"data-start-togetherjs-html\"));\n      }\n      el.removeClass(\"togetherjs-started\");\n    }\n  });\n\n  ui.chat = {\n    text: function (attrs) {\n      assert(typeof attrs.text == \"string\");\n      assert(attrs.peer);\n      assert(attrs.messageId);\n      var date = attrs.date || Date.now();\n      var lastEl = ui.container.find(\"#togetherjs-chat .togetherjs-chat-message\");\n      if (lastEl.length) {\n        lastEl = $(lastEl[lastEl.length-1]);\n      }\n      var lastDate = null;\n      if (lastEl) {\n        lastDate = parseInt(lastEl.attr(\"data-date\"), 10);\n      }\n      if (lastEl && lastEl.attr(\"data-person\") == attrs.peer.id &&\n          lastDate && date < lastDate + COLLAPSE_MESSAGE_LIMIT) {\n        lastEl.attr(\"data-date\", date);\n        var content = lastEl.find(\".togetherjs-chat-content\");\n        assert(content.length);\n        attrs.text = content.text() + \"\\n\" + attrs.text;\n        attrs.messageId = lastEl.attr(\"data-message-id\");\n        lastEl.remove();\n      }\n      var el = templating.sub(\"chat-message\", {\n        peer: attrs.peer,\n        content: attrs.text,\n        date: date\n      });\n      linkify(el.find(\".togetherjs-chat-content\"));\n      el.attr(\"data-person\", attrs.peer.id)\n        .attr(\"data-date\", date)\n        .attr(\"data-message-id\", attrs.messageId);\n      ui.chat.add(el, attrs.messageId, attrs.notify);\n    },\n\n    joinedSession: function (attrs) {\n      assert(attrs.peer);\n      var date = attrs.date || Date.now();\n      var el = templating.sub(\"chat-joined\", {\n        peer: attrs.peer,\n        date: date\n      });\n      // FIXME: should bind the notification to the dock location\n      ui.chat.add(el, attrs.peer.className(\"join-message-\"), 4000);\n    },\n\n    leftSession: function (attrs) {\n      assert(attrs.peer);\n      var date = attrs.date || Date.now();\n      var el = templating.sub(\"chat-left\", {\n        peer: attrs.peer,\n        date: date,\n        declinedJoin: attrs.declinedJoin\n      });\n      // FIXME: should bind the notification to the dock location\n      ui.chat.add(el, attrs.peer.className(\"join-message-\"), 4000);\n    },\n\n    system: function (attrs) {\n      assert(! attrs.peer);\n      assert(typeof attrs.text == \"string\");\n      var date = attrs.date || Date.now();\n      var el = templating.sub(\"chat-system\", {\n        content: attrs.text,\n        date: date\n      });\n      ui.chat.add(el, undefined, true);\n    },\n\n    clear: deferForContainer(function () {\n      var container = ui.container.find(\"#togetherjs-chat-messages\");\n      container.empty();\n    }),\n\n    urlChange: function (attrs) {\n      assert(attrs.peer);\n      assert(typeof attrs.url == \"string\");\n      assert(typeof attrs.sameUrl == \"boolean\");\n      var messageId = attrs.peer.className(\"url-change-\");\n      // FIXME: duplicating functionality in .add():\n      var realId = \"togetherjs-chat-\" + messageId;\n      var date = attrs.date || Date.now();\n      var title;\n      // FIXME: strip off common domain from msg.url?  E.g., if I'm on\n      // http://example.com/foobar, and someone goes to http://example.com/baz then\n      // show only /baz\n      // FIXME: truncate long titles\n      if (attrs.title) {\n        title = attrs.title + \" (\" + attrs.url + \")\";\n      } else {\n        title = attrs.url;\n      }\n      var el = templating.sub(\"url-change\", {\n        peer: attrs.peer,\n        date: date,\n        href: attrs.url,\n        title: title,\n        sameUrl: attrs.sameUrl\n      });\n      el.find(\".togetherjs-nudge\").click(function () {\n        attrs.peer.nudge();\n        return false;\n      });\n      el.find(\".togetherjs-follow\").click(function () {\n        var url = attrs.peer.url;\n        if (attrs.peer.urlHash) {\n          url += attrs.peer.urlHash;\n        }\n        location.href = url;\n      });\n      var notify = ! attrs.sameUrl;\n      if (attrs.sameUrl && ! $(\"#\" + realId).length) {\n        // Don't bother showing a same-url notification, if no previous notification\n        // had been shown\n        return;\n      }\n      ui.chat.add(el, messageId, notify);\n    },\n\n    invite: function (attrs) {\n      assert(attrs.peer);\n      assert(typeof attrs.url == \"string\");\n      var messageId = attrs.peer.className(\"invite-\");\n      var date = attrs.date || Date.now();\n      var hrefTitle = attrs.url.replace(/\\#?&togetherjs=.*/, \"\").replace(/^\\w+:\\/\\//, \"\");\n      var el = templating.sub(\"invite\", {\n        peer: attrs.peer,\n        date: date,\n        href: attrs.url,\n        hrefTitle: hrefTitle,\n        forEveryone: attrs.forEveryone\n      });\n      if (attrs.forEveryone) {\n        el.find(\"a\").click(function () {\n          // FIXME: hacky way to do this:\n          chat.submit(\"Followed link to \" + attrs.url);\n        });\n      }\n      ui.chat.add(el, messageId, true);\n    },\n\n    hideTimeout: null,\n\n    add: deferForContainer(function (el, id, notify) {\n      if (id) {\n        el.attr(\"id\", \"togetherjs-chat-\" + util.safeClassName(id));\n      }\n      var container = ui.container.find(\"#togetherjs-chat-messages\");\n      assert(container.length);\n      var popup = ui.container.find(\"#togetherjs-chat-notifier\");\n      container.append(el);\n      ui.chat.scroll();\n      var doNotify = !! notify;\n      var section = popup.find(\"#togetherjs-chat-notifier-message\");\n      if (notify && visibilityApi.hidden()) {\n        ui.container.find(\"#togetherjs-notification\")[0].play();\n      }\n      if (id && section.data(\"message-id\") == id) {\n        doNotify = true;\n      }\n      if (container.is(\":visible\")) {\n        doNotify = false;\n      }\n      if (doNotify) {\n        section.empty();\n        section.append(el.clone(true, true));\n        if (section.data(\"message-id\") != id)  {\n          section.data(\"message-id\", id || \"\");\n          windowing.show(popup);\n        } else if (! popup.is(\":visible\")) {\n          windowing.show(popup);\n        }\n        if (typeof notify == \"number\") {\n          // This is the amount of time we're supposed to notify\n          if (this.hideTimeout) {\n            clearTimeout(this.hideTimeout);\n            this.hideTimeout = null;\n          }\n          this.hideTimeout = setTimeout((function () {\n            windowing.hide(popup);\n            this.hideTimeout = null;\n          }).bind(this), notify);\n        }\n      }\n    }),\n\n    scroll: deferForContainer(function () {\n      var container = ui.container.find(\"#togetherjs-chat-messages\")[0];\n      container.scrollTop = container.scrollHeight;\n    })\n\n  };\n\n  session.on(\"display-window\", function (id, win) {\n    if (id == \"togetherjs-chat\") {\n      ui.chat.scroll();\n      windowing.hide(\"#togetherjs-chat-notifier\");\n    }\n  });\n\n  /* This class is bound to peers.Peer instances as peer.view.\n     The .update() method is regularly called by peer objects when info changes. */\n  ui.PeerView = util.Class({\n\n    constructor: function (peer) {\n      assert(peer.isSelf !== undefined, \"PeerView instantiated with non-Peer object\");\n      this.peer = peer;\n      this.dockClick = this.dockClick.bind(this);\n    },\n\n    /* Takes an element and sets any person-related attributes on the element\n       Different from updates, which use the class names we set here: */\n    setElement: function (el) {\n      var count = 0;\n      var classes = [\"togetherjs-person\", \"togetherjs-person-status\",\n                     \"togetherjs-person-name\", \"togetherjs-person-name-abbrev\",\n                     \"togetherjs-person-bgcolor\", \"togetherjs-person-swatch\",\n                     \"togetherjs-person-status\", \"togetherjs-person-role\",\n                     \"togetherjs-person-url\", \"togetherjs-person-url-title\",\n                     \"togetherjs-person-bordercolor\"];\n      classes.forEach(function (cls) {\n        var els = el.find(\".\" + cls);\n        els.addClass(this.peer.className(cls + \"-\"));\n        count += els.length;\n      }, this);\n      if (! count) {\n        console.warn(\"setElement(\", el, \") doesn't contain any person items\");\n      }\n      this.updateDisplay(el);\n    },\n\n    updateDisplay: deferForContainer(function (container) {\n      container = container || ui.container;\n      var abbrev = this.peer.name;\n      if (this.peer.isSelf) {\n        abbrev = \"me\";\n      }\n      container.find(\".\" + this.peer.className(\"togetherjs-person-name-\")).text(this.peer.name || \"\");\n      container.find(\".\" + this.peer.className(\"togetherjs-person-name-abbrev-\")).text(abbrev);\n      var avatarEl = container.find(\".\" + this.peer.className(\"togetherjs-person-\"));\n      if (this.peer.avatar) {\n        util.assertValidUrl(this.peer.avatar);\n        avatarEl.css({\n          backgroundImage: \"url(\" + this.peer.avatar + \")\"\n        });\n      }\n      if (this.peer.idle == \"inactive\") {\n        avatarEl.addClass(\"togetherjs-person-inactive\");\n      } else {\n        avatarEl.removeClass(\"togetherjs-person-inactive\");\n      }\n      avatarEl.attr(\"title\", this.peer.name);\n      if (this.peer.color) {\n        avatarEl.css({\n          borderColor: this.peer.color\n        });\n        avatarEl.find(\".togetherjs-person-avatar-swatch\").css({\n          borderTopColor: this.peer.color,\n          borderRightColor: this.peer.color\n        });\n      }\n      if (this.peer.color) {\n        var colors = container.find(\".\" + this.peer.className(\"togetherjs-person-bgcolor-\"));\n        colors.css({\n          backgroundColor: this.peer.color\n        });\n        colors = container.find(\".\" + this.peer.className(\"togetherjs-person-bordercolor-\"));\n        colors.css({\n          borderColor: this.peer.color\n        });\n      }\n      container.find(\".\" + this.peer.className(\"togetherjs-person-role-\"))\n        .text(this.peer.isCreator ? \"Creator\" : \"Participant\");\n      var urlName = this.peer.title || \"\";\n      if (this.peer.title) {\n        urlName += \" (\";\n      }\n      urlName += util.truncateCommonDomain(this.peer.url, location.href);\n      if (this.peer.title) {\n        urlName += \")\";\n      }\n      container.find(\".\" + this.peer.className(\"togetherjs-person-url-title-\"))\n        .text(urlName);\n      var url = this.peer.url;\n      if (this.peer.urlHash) {\n        url += this.peer.urlHash;\n      }\n      container.find(\".\" + this.peer.className(\"togetherjs-person-url-\"))\n        .attr(\"href\", url);\n      // FIXME: should have richer status:\n      container.find(\".\" + this.peer.className(\"togetherjs-person-status-\"))\n        .text(this.peer.idle == \"active\" ? \"Active\" : \"Inactive\");\n      if (this.peer.isSelf) {\n        // FIXME: these could also have consistent/reliable class names:\n        var selfName = $(\".togetherjs-self-name\");\n        selfName.each((function (index, el) {\n          el = $(el);\n          if (el.val() != this.peer.name) {\n            el.val(this.peer.name);\n          }\n        }).bind(this));\n        $(\"#togetherjs-menu-avatar\").attr(\"src\", this.peer.avatar);\n        if (! this.peer.name) {\n          $(\"#togetherjs-menu .togetherjs-person-name-self\").text(this.peer.defaultName);\n        }\n      }\n      if (this.peer.url != session.currentUrl()) {\n        container.find(\".\" + this.peer.className(\"togetherjs-person-\"))\n            .addClass(\"togetherjs-person-other-url\");\n      } else {\n        container.find(\".\" + this.peer.className(\"togetherjs-person-\"))\n            .removeClass(\"togetherjs-person-other-url\");\n      }\n      if (this.peer.following) {\n        if (this.followCheckbox) {\n          this.followCheckbox.prop(\"checked\", true);\n        }\n      } else {\n        if (this.followCheckbox) {\n          this.followCheckbox.prop(\"checked\", false);\n        }\n      }\n      // FIXME: add some style based on following?\n      updateChatParticipantList();\n      this.updateFollow();\n    }),\n\n    update: function () {\n      if (! this.peer.isSelf) {\n        if (this.peer.status == \"live\") {\n          this.dock();\n        } else {\n          this.undock();\n        }\n      }\n      this.updateDisplay();\n      this.updateUrlDisplay();\n    },\n\n    updateUrlDisplay: function (force) {\n      var url = this.peer.url;\n      if ((! url) || (url == this._lastUpdateUrlDisplay && ! force)) {\n        return;\n      }\n      this._lastUpdateUrlDisplay = url;\n      var sameUrl = url == session.currentUrl();\n      ui.chat.urlChange({\n        peer: this.peer,\n        url: this.peer.url,\n        title: this.peer.title,\n        sameUrl: sameUrl\n      });\n    },\n\n    urlNudge: function () {\n      // FIXME: do something more distinct here\n      this.updateUrlDisplay(true);\n    },\n\n    notifyJoined: function () {\n      ui.chat.joinedSession({\n        peer: this.peer\n      });\n    },\n\n    // when there are too many participants in the dock, consolidate the participants to one avatar, and on mouseOver, the dock expands down to reveal the rest of the participants\n    // if there are X users in the session\n    // then hide the users in the dock\n    // and shrink the size of the dock\n    // and if you rollover the dock, it expands and reveals the rest of the participants in the dock\n\n    //if users hit X then show the participant button with the consol\n\n    dock: deferForContainer(function () {\n\n      var numberOfUsers = peers.getAllPeers().length;\n\n      // collapse the Dock if too many users\n      function CollapsedDock() {\n        // decrease/reset dock height\n        $(\"#togetherjs-dock\").css(\"height\", 260);\n        //replace participant button\n        $(\"#togetherjs-dock-participants\").replaceWith(\"<button id='togetherjs-participantlist-button' class='togetherjs-button'><div class='togetherjs-tooltip togetherjs-dock-person-tooltip'><span class='togetherjs-person-name'>Participants</span><span class='togetherjs-person-tooltip-arrow-r'></span></div><div class='togetherjs-person togetherjs-person-status-overlay' title='Participant List' style='background-image: url(\"+TogetherJS.baseUrl+\"/togetherjs/images/robot-avatar.png); border-color: rgb(255, 0, 0);'></div></button>\");\n        // new full participant window created on toggle\n        $(\"#togetherjs-participantlist-button\").click(function () {\n          windowing.toggle(\"#togetherjs-participantlist\");\n        });\n      }\n\n      // FIXME: turned off for now\n      if( numberOfUsers >= 5 && false) {\n        CollapsedDock();\n      } else {\n        // reset\n\n      }\n\n\n      if (this.dockElement) {\n        return;\n      }\n      this.dockElement = templating.sub(\"dock-person\", {\n        peer: this.peer\n      });\n      this.dockElement.attr(\"id\", this.peer.className(\"togetherjs-dock-element-\"));\n      ui.container.find(\"#togetherjs-dock-participants\").append(this.dockElement);\n      this.dockElement.find(\".togetherjs-person\").animateDockEntry();\n      adjustDockSize(1);\n      this.detailElement = templating.sub(\"participant-window\", {\n        peer: this.peer\n      });\n      var followId = this.peer.className(\"togetherjs-person-status-follow-\");\n      this.detailElement.find('[for=\"togetherjs-person-status-follow\"]').attr(\"for\", followId);\n      this.detailElement.find('#togetherjs-person-status-follow').attr(\"id\", followId);\n      this.detailElement.find(\".togetherjs-follow\").click(function () {\n        location.href = $(this).attr(\"href\");\n      });\n      this.detailElement.find(\".togetherjs-nudge\").click((function () {\n        this.peer.nudge();\n      }).bind(this));\n      this.followCheckbox = this.detailElement.find(\"#\" + followId);\n      this.followCheckbox.change(function () {\n        if (! this.checked) {\n          this.peer.unfollow();\n        }\n        // Following doesn't happen until the window is closed\n        // FIXME: should we tell the user this?\n      });\n      this.maybeHideDetailWindow = this.maybeHideDetailWindow.bind(this);\n      session.on(\"hide-window\", this.maybeHideDetailWindow);\n      ui.container.append(this.detailElement);\n      this.dockElement.click((function () {\n        if (this.detailElement.is(\":visible\")) {\n          windowing.hide(this.detailElement);\n        } else {\n          windowing.show(this.detailElement, {bind: this.dockElement});\n          this.scrollTo();\n          this.cursor().element.animate({\n            opacity:0.3\n          }).animate({\n            opacity:1\n          }).animate({\n            opacity:0.3\n          }).animate({\n            opacity:1\n          });\n        }\n      }).bind(this));\n      this.updateFollow();\n    }),\n\n    undock: function () {\n      if (! this.dockElement) {\n        return;\n      }\n      this.dockElement.animateDockExit().promise().then((function () {\n        this.dockElement.remove();\n        this.dockElement = null;\n        this.detailElement.remove();\n        this.detailElement = null;\n        adjustDockSize(-1);\n      }).bind(this));\n    },\n\n    scrollTo: function () {\n      if (this.peer.url != session.currentUrl()) {\n        return;\n      }\n      var pos = this.peer.scrollPosition;\n      if (! pos) {\n        console.warn(\"Peer has no scroll position:\", this.peer);\n        return;\n      }\n      pos = elementFinder.pixelForPosition(pos);\n      $(\"html, body\").easeTo(pos);\n    },\n\n    updateFollow: function () {\n      if (! this.peer.url) {\n        return;\n      }\n      if (! this.detailElement) {\n        return;\n      }\n      var same = this.detailElement.find(\".togetherjs-same-url\");\n      var different = this.detailElement.find(\".togetherjs-different-url\");\n      if (this.peer.url == session.currentUrl()) {\n        same.show();\n        different.hide();\n      } else {\n        same.hide();\n        different.show();\n      }\n    },\n\n    maybeHideDetailWindow: function (windows) {\n      if (this.detailElement && windows[0] && windows[0][0] === this.detailElement[0]) {\n        if (this.followCheckbox[0].checked) {\n          this.peer.follow();\n        } else {\n          this.peer.unfollow();\n        }\n      }\n    },\n\n    dockClick: function () {\n      // FIXME: scroll to person\n    },\n\n    cursor: function () {\n      return require(\"cursor\").getClient(this.peer.id);\n    },\n\n    destroy: function () {\n      // FIXME: should I get rid of the dockElement?\n      session.off(\"hide-window\", this.maybeHideDetailWindow);\n    }\n  });\n\n  function updateChatParticipantList() {\n    var live = peers.getAllPeers(true);\n    if (live.length) {\n      ui.displayToggle(\"#togetherjs-chat-participants\");\n      $(\"#togetherjs-chat-participant-list\").text(\n        live.map(function (p) {return p.name;}).join(\", \"));\n    } else {\n      ui.displayToggle(\"#togetherjs-chat-no-participants\");\n    }\n  }\n\n  function inviteHubUrl() {\n    var base = TogetherJS.config.get(\"inviteFromRoom\");\n    assert(base);\n    return util.makeUrlAbsolute(base, session.hubUrl());\n  }\n\n  var inRefresh = false;\n\n  function refreshInvite() {\n    if (inRefresh) {\n      return;\n    }\n    inRefresh = true;\n    require([\"who\"], function (who) {\n      var def = who.getList(inviteHubUrl());\n      function addUser(user, before) {\n        var item = templating.sub(\"invite-user-item\", {peer: user});\n        item.attr(\"data-clientid\", user.id);\n        if (before) {\n          item.insertBefore(before);\n        } else {\n          $(\"#togetherjs-invite-users\").append(item);\n        }\n        item.click(function() {\n          invite(user.clientId);\n        });\n      }\n      function refresh(users, finished) {\n        var sorted = [];\n        for (var id in users) {\n          if (users.hasOwnProperty(id)) {\n            sorted.push(users[id]);\n          }\n        }\n        sorted.sort(function (a, b) {\n          return a.name < b.name ? -1 : 1;\n        });\n        var pos = 0;\n        ui.container.find(\"#togetherjs-invite-users .togetherjs-menu-item\").each(function () {\n          var $this = $(this);\n          if (finished && ! users[$this.attr(\"data-clientid\")]) {\n            $this.remove();\n            return;\n          }\n          if (pos >= sorted.length) {\n            return;\n          }\n          while (pos < sorted.length && $this.attr(\"data-clientid\") !== sorted[pos].id) {\n            addUser(sorted[pos], $this);\n            pos++;\n          }\n          while (pos < sorted.length && $this.attr(\"data-clientid\") == sorted[pos].id) {\n            pos++;\n          }\n        });\n        for (var i=pos; i<sorted.length; i++) {\n          addUser(sorted[pos]);\n        }\n      }\n      def.then(function (users) {\n        refresh(users, true);\n        inRefresh = false;\n      });\n      def.progress(refresh);\n    });\n  }\n\n  session.hub.on(\"invite\", function (msg) {\n    if (msg.forClientId && msg.clientId != peers.Self.id) {\n      return;\n    }\n    require([\"who\"], function (who) {\n      var peer = who.ExternalPeer(msg.userInfo.clientId, msg.userInfo);\n      ui.chat.invite({peer: peer, url: msg.url, forEveryone: ! msg.forClientId});\n    });\n  });\n\n  function invite(clientId) {\n    require([\"who\"], function (who) {\n      // FIXME: use the return value of this to give a signal that\n      // the invite has been successfully sent:\n      who.invite(inviteHubUrl(), clientId).then(function () {\n        hideMenu();\n      });\n    });\n  }\n\n  ui.showUrlChangeMessage = deferForContainer(function (peer, url) {\n    var window = templating.sub(\"url-change\", {peer: peer});\n    ui.container.append(window);\n    windowing.show(window);\n  });\n\n  session.hub.on(\"url-change-nudge\", function (msg) {\n    if (msg.to && msg.to != session.clientId) {\n      // Not directed to us\n      return;\n    }\n    msg.peer.urlNudge();\n  });\n\n  session.on(\"new-element\", function (el) {\n    if (TogetherJS.config.get(\"toolName\")) {\n      ui.updateToolName(el);\n    }\n  });\n\n  var setToolName = false;\n  ui.updateToolName = function (container) {\n    container = container || $(document.body);\n    var name = TogetherJS.config.get(\"toolName\");\n    if (setToolName && ! name) {\n      name = \"TogetherJS\";\n    }\n    if (name) {\n      container.find(\".togetherjs-tool-name\").text(name);\n      setToolName = true;\n    }\n  };\n\n  TogetherJS.config.track(\"toolName\", function (name) {\n    ui.updateToolName(ui.container);\n  });\n\n  return ui;\n\n});\n"
  },
  {
    "path": "togetherjs/util.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"jquery\", \"jqueryPlugins\"], function ($) {\n  var util = {};\n\n  util.Deferred = $.Deferred;\n  TogetherJS.$ = $;\n\n  /* A simple class pattern, use like:\n\n    var Foo = util.Class({\n      constructor: function (a, b) {\n        init the class\n      },\n      otherMethod: ...\n    });\n\n  You can also give a superclass as the optional first argument.\n\n  Instantiation does not require \"new\"\n\n  */\n  util.Class = function (superClass, prototype) {\n    var a;\n    if (prototype === undefined) {\n      prototype = superClass;\n    } else {\n      if (superClass.prototype) {\n        superClass = superClass.prototype;\n      }\n      var newPrototype = Object.create(superClass);\n      for (a in prototype) {\n        if (prototype.hasOwnProperty(a)) {\n          newPrototype[a] = prototype[a];\n        }\n      }\n      prototype = newPrototype;\n    }\n    var ClassObject = function () {\n      var obj = Object.create(prototype);\n      obj.constructor.apply(obj, arguments);\n      obj.constructor = ClassObject;\n      return obj;\n    };\n    ClassObject.prototype = prototype;\n    if (prototype.constructor.name) {\n      ClassObject.className = prototype.constructor.name;\n      ClassObject.toString = function () {\n        return '[Class ' + this.className + ']';\n      };\n    }\n    if (prototype.classMethods) {\n      for (a in prototype.classMethods) {\n        if (prototype.classMethods.hasOwnProperty(a)) {\n          ClassObject[a] = prototype.classMethods[a];\n        }\n      }\n    }\n    return ClassObject;\n  };\n\n  /* Extends obj with other, or copies obj if no other is given. */\n  util.extend = TogetherJS._extend;\n\n  util.forEachAttr = function (obj, callback, context) {\n    context = context || obj;\n    for (var a in obj) {\n      if (obj.hasOwnProperty(a)) {\n        callback.call(context, obj[a], a);\n      }\n    }\n  };\n\n  /* Trim whitespace from a string */\n  util.trim = function trim(s) {\n    return s.replace(/^\\s+/, \"\").replace(/\\s+$/, \"\");\n  };\n\n  /* Convert a string into something safe to use as an HTML class name */\n  util.safeClassName = function safeClassName(name) {\n    return name.replace(/[^a-zA-Z0-9_\\-]/g, \"_\") || \"class\";\n  };\n\n  util.AssertionError = function (message) {\n    if (! this instanceof util.AssertionError) {\n      return new util.AssertionError(message);\n    }\n    this.message = message;\n    this.name = \"AssertionError\";\n  };\n  util.AssertionError.prototype = Error.prototype;\n\n  util.assert = function (cond) {\n    if (! cond) {\n      var args = [\"Assertion error:\"].concat(Array.prototype.slice.call(arguments, 1));\n      console.error.apply(console, args);\n      if (console.trace) {\n        console.trace();\n      }\n      throw new util.AssertionError(args.join(\" \"));\n    }\n  };\n\n  /* Generates a random ID */\n  util.generateId = function (length) {\n    length = length || 10;\n    var letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV0123456789';\n    var s = '';\n    for (var i=0; i<length; i++) {\n      s += letters.charAt(Math.floor(Math.random() * letters.length));\n    }\n    return s;\n  };\n\n  util.pickRandom = function (array) {\n    return array[Math.floor(Math.random() * array.length)];\n  };\n\n  util.mixinEvents = TogetherJS._mixinEvents;\n\n  util.Module = util.Class({\n    constructor: function (name) {\n      this._name = name;\n    },\n    toString: function () {\n      return '[Module ' + this._name + ']';\n    }\n  });\n\n  util.blobToBase64 = function (blob) {\n    // Oh this is just terrible\n    var binary = '';\n    var bytes = new Uint8Array(blob);\n    var len = bytes.byteLength;\n    for (var i=0; i<len; i++) {\n      binary += String.fromCharCode(bytes[i]);\n    }\n    return btoa(binary);\n  };\n\n  util.truncateCommonDomain = function (url, base) {\n    /* Remove the scheme and domain from url, if it matches the scheme and domain\n       of base */\n    if (! base) {\n      return url;\n    }\n    var regex = /^https?:\\/\\/[^\\/]*/i;\n    var match = regex.exec(url);\n    var matchBase = regex.exec(base);\n    if (match && matchBase && match[0] == matchBase[0]) {\n      // There is a common scheme and domain\n      return url.substr(match[0].length);\n    }\n    return url;\n  };\n\n  util.makeUrlAbsolute = function (url, base) {\n    if (url.search(/^(http|https|ws|wss):/i) === 0) {\n      // Absolute URL\n      return url;\n    }\n    if (url.search(/^\\/\\/[^\\/]/) === 0) {\n      var scheme = (/^(http|https|ws|wss):/i).exec(base);\n      util.assert(scheme, \"No scheme on base URL\", base);\n      return scheme[1] + \":\" + url;\n    }\n    if (url.search(/^\\//) === 0) {\n      var domain = (/^(http|https|ws|wss):\\/\\/[^\\/]+/i).exec(base);\n      util.assert(domain, \"No scheme/domain on base URL\", base);\n      return domain[0] + url;\n    }\n    var last = (/[^\\/]+$/).exec(base);\n    util.assert(last, \"Does not appear to be a URL?\", base);\n    var lastBase = base.substr(0, last.index);\n    return lastBase + url;\n  };\n\n  util.assertValidUrl = function (url) {\n    /* This does some simple assertions that the url is valid:\n       - it must be a string\n       - it must be http(s)://... or data:...\n       - it must not contain a space, quotation, or close paren\n    */\n    util.assert(typeof url == \"string\", \"URLs must be a string:\", url);\n    util.assert(url.search(/^(http:\\/\\/|https:\\/\\/|\\/\\/|data:)/i) === 0,\n                \"URL must have an http, https, data, or // scheme:\", url);\n    util.assert(url.search(/[\\)\\'\\\"\\ ]/) === -1,\n                \"URLs cannot contain ), ', \\\", or spaces:\", JSON.stringify(url));\n  };\n\n  util.resolver = function (deferred, func) {\n    util.assert(deferred.then, \"Bad deferred:\", deferred);\n    util.assert(typeof func == \"function\", \"Not a function:\", func);\n    return function () {\n      var result;\n      try {\n        result = func.apply(this, arguments);\n      } catch (e) {\n        deferred.reject(e);\n        throw e;\n      }\n      if (result && result.then) {\n        result.then(function () {\n          deferred.resolveWith(this, arguments);\n        }, function () {\n          deferred.rejectWith(this, arguments);\n        });\n        // FIXME: doesn't pass progress through\n      } else if (result === undefined) {\n        deferred.resolve();\n      } else {\n        deferred.resolve(result);\n      }\n      return result;\n    };\n  };\n\n  /* Detects if a value is a promise.  Right now the presence of a\n     `.then()` method is the best we can do.\n  */\n  util.isPromise = function (obj) {\n    return typeof obj == \"object\" && obj.then;\n  };\n\n  /* Makes a value into a promise, by returning an already-resolved\n     promise if a non-promise objectx is given.\n  */\n  util.makePromise = function (obj) {\n    if (util.isPromise(obj)) {\n      return obj;\n    } else {\n      return $.Deferred(function (def) {\n        def.resolve(obj);\n      });\n    }\n  };\n\n  /* Resolves several promises (the promises are the arguments to the function)\n     or the first argument may be an array of promises.\n\n     Returns a promise that will resolve with the results of all the\n     promises.  If any promise fails then the returned promise fails.\n\n     FIXME: if a promise has more than one return value (like with\n     promise.resolve(a, b)) then the latter arguments will be lost.\n     */\n  util.resolveMany = function () {\n    var args;\n    var oneArg = false;\n    if (arguments.length == 1 && Array.isArray(arguments[0])) {\n      oneArg = true;\n      args = arguments[0];\n    } else {\n      args = Array.prototype.slice.call(arguments);\n    }\n    return util.Deferred(function (def) {\n      var count = args.length;\n      if (! count) {\n        def.resolve();\n        return;\n      }\n      var allResults = [];\n      var anyError = false;\n      args.forEach(function (arg, index) {\n        arg.then(function (result) {\n          allResults[index] = result;\n          count--;\n          check();\n        }, function (error) {\n          allResults[index] = error;\n          anyError = true;\n          count--;\n          check();\n        });\n      });\n      function check() {\n        if (! count) {\n          if (anyError) {\n            if (oneArg) {\n              def.reject(allResults);\n            } else {\n              def.reject.apply(def, allResults);\n            }\n          } else {\n            if (oneArg) {\n              def.resolve(allResults);\n            } else {\n              def.resolve.apply(def, allResults);\n            }\n          }\n        }\n      }\n    });\n  };\n\n  util.readFileImage = function (el) {\n    return util.Deferred(function (def) {\n      var reader = new FileReader();\n      reader.onload = function () {\n        def.resolve(\"data:image/jpeg;base64,\" + util.blobToBase64(this.result));\n      };\n      reader.onerror = function () {\n        def.reject(this.error);\n      };\n      reader.readAsArrayBuffer(el.files[0]);\n    });\n  };\n\n  util.matchElement = function(el, selector) {\n    var res = selector;\n    if (selector === true || ! selector) {\n      return !!selector;\n    }\n    try {\n      return $(el).is(selector);\n    } catch (e) {\n      console.warn(\"Bad selector:\", selector, \"error:\", e);\n      return false;\n    }\n\n  };\n\n  util.testExpose = function (objs) {\n    if (typeof TogetherJSTestSpy == \"undefined\") {\n      return;\n    }\n    util.forEachAttr(objs, function (value, attr) {\n      TogetherJSTestSpy[attr] = value;\n    });\n  };\n\n  return util;\n});\n"
  },
  {
    "path": "togetherjs/videos.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"jquery\", \"util\", \"session\", \"elementFinder\"],\nfunction ($, util, session, elementFinder) {\n\n  var listeners = [];\n\n  var TIME_UPDATE = 'timeupdate';\n  var MIRRORED_EVENTS = ['play', 'pause'];\n\n  var TOO_FAR_APART = 3000;\n\n  session.on(\"reinitialize\", function () {\n    unsetListeners();\n    setupListeners();\n  });\n\n  session.on(\"ui-ready\", setupListeners);\n\n  function setupListeners() {\n    var videos = $('video');\n    setupMirroredEvents(videos);\n    setupTimeSync(videos);\n  }\n\n  function setupMirroredEvents(videos) {\n    var currentListener;\n    MIRRORED_EVENTS.forEach(function (eventName) {\n      currentListener = makeEventSender(eventName);\n      videos.on(eventName, currentListener);\n      listeners.push({\n        name: eventName,\n        listener: currentListener\n      });\n    });\n  }\n\n  function makeEventSender(eventName) {\n    return function (event, options) {\n      var element = event.target;\n      options = options || {};\n      if (!options.silent) {\n        session.send({\n          type: ('video-'+eventName),\n          location: elementFinder.elementLocation(element),\n          position: element.currentTime\n        });\n      }\n    };\n  }\n\n  function setupTimeSync(videos) {\n    videos.each(function(i, video) {\n      var onTimeUpdate = makeTimeUpdater();\n      $(video).on(TIME_UPDATE, onTimeUpdate);\n      listeners.push({\n        name: TIME_UPDATE,\n        listener: onTimeUpdate\n      });\n    });\n  }\n\n  function makeTimeUpdater() {\n    var last = 0;\n    return function (event) {\n      var currentTime = event.target.currentTime;\n      if(areTooFarApart(currentTime, last)){\n        makeEventSender(TIME_UPDATE)(event);\n      }\n      last = currentTime;\n    };\n  }\n\n  function areTooFarApart(currentTime, lastTime) {\n    var secDiff = Math.abs(currentTime - lastTime);\n    var milliDiff = secDiff * 1000;\n    return milliDiff > TOO_FAR_APART;\n  }\n\n  session.on(\"close\", unsetListeners);\n\n  function unsetListeners() {\n    var videos = $('video');\n    listeners.forEach(function (event) {\n        videos.off(event.name, event.listener);\n    });\n    listeners = [];\n  }\n\n\n  session.hub.on('video-timeupdate', function (msg) {\n    var element = $findElement(msg.location);\n    var oldTime = element.prop('currentTime');\n    var newTime = msg.position;\n\n    //to help throttle uneccesary position changes\n    if(areTooFarApart(oldTime, newTime)){\n      setTime(element, msg.position);\n    }\n  });\n\n  MIRRORED_EVENTS.forEach( function (eventName) {\n    session.hub.on(\"video-\"+eventName, function (msg) {\n      var element = $findElement(msg.location);\n\n      setTime(element, msg.position);\n\n      element.trigger(eventName, {silent: true});\n    });\n  });\n\n  //Currently does not discriminate between visible and invisible videos\n  function $findElement(location) {\n    return $(elementFinder.findElement(location));\n  }\n\n  function setTime(video, time) {\n    video.prop('currentTime', time);\n  }\n\n});\n"
  },
  {
    "path": "togetherjs/visibilityApi.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/* Loading this module will cause, when TogetherJS is active, the\n   session object to emit visibility-change with a `hidden` argument\n   whenever the visibility changes, on browsers where we can detect\n   it.\n   */\n\ndefine([\"util\", \"session\"], function (util, session) {\n  var visibilityApi = util.Module(\"visibilityApi\");\n  var hidden;\n  var visibilityChange;\n  if (document.hidden !== undefined) { // Opera 12.10 and Firefox 18 and later support\n    hidden = \"hidden\";\n    visibilityChange = \"visibilitychange\";\n  } else if (document.mozHidden !== undefined) {\n    hidden = \"mozHidden\";\n    visibilityChange = \"mozvisibilitychange\";\n  } else if (document.msHidden !== undefined) {\n    hidden = \"msHidden\";\n    visibilityChange = \"msvisibilitychange\";\n  } else if (document.webkitHidden !== undefined) {\n    hidden = \"webkitHidden\";\n    visibilityChange = \"webkitvisibilitychange\";\n  }\n\n  session.on(\"start\", function () {\n    document.addEventListener(visibilityChange, change, false);\n  });\n\n  session.on(\"close\", function () {\n    document.removeEventListener(visibilityChange, change, false);\n  });\n\n  function change() {\n    session.emit(\"visibility-change\", document[hidden]);\n  }\n\n  visibilityApi.hidden = function () {\n    return document[hidden];\n  };\n\n  return visibilityApi;\n});\n"
  },
  {
    "path": "togetherjs/walkabout.html",
    "content": "<div class=\"togetherjs-status\"></div>\n<!--\nThis is used to show the walkabout.js test status (in chat.js).  Right\nnow a string is just inserted into .togetherjs-status\n-->\n"
  },
  {
    "path": "togetherjs/walkthrough.html",
    "content": "<!--\n    Any elements with .togetherjs-walkthrough-firsttime will only be\n    displayed on during the first-time experience.  Any elements with\n    .togetherjs-walkthrough-not-firsttime will only be displayed when\n    the walkthrough is accessed through the Help menu.\n\n    Note you *cannot* use <section class=\"togetherjs-walkthrough-slide\n    togetherjs-walkthrough-firsttime\">: the number of sections must be the\n    same regardless.\n  -->\n<div id=\"togetherjs-walkthrough\" class=\"togetherjs-modal togetherjs-modal-wide\">\n  <header>{{ gettext( \"You're using TOOL_NAME!\" ) }}<button class=\"togetherjs-close\"></button></header>\n\n  <div id=\"togetherjs-walkthrough-previous\"></div>\n  <div id=\"togetherjs-walkthrough-next\"></div>\n\n  <section class=\"togetherjs-walkthrough-slide\">\n    <p class=\"togetherjs-walkthrough-main-image\"><img src=\"http://localhost:8080/togetherjs/images/walkthrough-images-intro.png\"></p>\n\t<p>{{ gettext( \"TOOL_NAME is a service for your website that makes it easy to collaborate in real-time on SITE_NAME\") }} </p>\n  </section>\n\n  <section class=\"togetherjs-walkthrough-slide\">\n    <div class=\"togetherjs-walkthrough-firsttime\">\n      <div class=\"togetherjs-walkthrough-main-image\">\n        <div class=\"togetherjs-walkthrough-avatar-section\">\n          <div class=\"togetherjs-avatar-preview togetherjs-person togetherjs-person-self\"></div>\n          <div class=\"togetherjs-avatar-upload-input\"><input type=\"file\" class=\"togetherjs-upload-avatar\"></div>\n        </div>\n        <input class=\"togetherjs-self-name\" type=\"text\" placeholder=\"{{ gettext( \"Enter your name\" ) }}\">\n        <div class=\"togetherjs-swatch togetherjs-person-bgcolor-self\"></div>\n        <div class=\"togetherjs-save-settings\">\n          <button class=\"togetherjs-avatar-save togetherjs-primary\">\n            <span id=\"togetherjs-avatar-when-unsaved\">\"\"{{ gettext(\"Save\") }}\"\"</span>\n            <span id=\"togetherjs-avatar-when-saved\" style=\"display: none\">{{ gettext(\"Saved!\") }}</span>\n          </button>\n        </div>\n      </div>\n      <p>{{ gettext( \"Set up your avatar, name and user color above.  If you'd like to update it later, you can click your Profile button.\") }}</p>\n    </div>\n    <div class=\"togetherjs-walkthrough-not-firsttime\">\n      <p class=\"togetherjs-walkthrough-main-image\"><img src=\"http://localhost:8080/togetherjs/images/walkthrough-images-profile.png\"></p>\n      <p>{{ gettext( \"Change your avatar, name and user color using the Profile button.\" ) }}</p>\n    </div>\n  </section>\n\n  <section class=\"togetherjs-walkthrough-slide\">\n    <p class=\"togetherjs-walkthrough-main-image togetherjs-ifnot-creator\"><img src=\"http://localhost:8080/togetherjs/images/walkthrough-images-invite.png\">\n    </p>\n    <p class=\"togetherjs-ifnot-creator\">{{ gettext( \"You can invite more friends to the session by sending the invite link in the TOOL_NAME dock.\" ) }}</p>\n    <p class=\"togetherjs-walkthrough-main-image togetherjs-if-creator\">\n      <span class=\"togetherjs-walkthrough-sendlink\">\n        {{ gettext( \"Copy and paste this link into IM or email to invite friends.\" ) }}\n      </span>\n      <input type=\"text\" class=\"togetherjs-share-link\">\n    </p>\n    <p class=\"togetherjs-if-creator\">{{ gettext(\"Send the above link to a friend so they can join your session!  You can find this invite link on the TOOL_NAME dock as well.\") }}</p>\n  </section>\n\n  <section class=\"togetherjs-walkthrough-slide\">\n    <p class=\"togetherjs-walkthrough-main-image\"><img src=\"http://localhost:8080/togetherjs/images/walkthrough-images-participant.png\"></p>\n    <p>{{ gettext( \"Friends who join your TOOL_NAME session will appear here.  You can click their avatars to see more.\" ) }}</p>\n  </section>\n\n  <section class=\"togetherjs-walkthrough-slide\">\n    <p class=\"togetherjs-walkthrough-main-image\"><img src=\"http://localhost:8080/togetherjs/images/walkthrough-images-chat.png\"></p>\n    <p>{{ gettext( \"When your friends join you in your TOOL_NAME session, you can chat with them here!\" ) }}</p>\n  </section>\n\n  <section class=\"togetherjs-walkthrough-slide\">\n    <p class=\"togetherjs-walkthrough-main-image\"><img src=\"http://localhost:8080/togetherjs/images/walkthrough-images-rtc.png\"></p>\n    <p>{{ gettext( \"If your browser supports it, click the microphone icon to begin an audio chat. Learn more about this experimental feature <a href=\\\"https://github.com/mozilla/togetherjs/wiki/About-Audio-Chat-and-WebRTC\\\" target=\\\"_blank\\\">here</a>.\" ) }}</p>\n  </section>\n\n  <section class=\"togetherjs-walkthrough-slide\">\n    <p class=\"togetherjs-walkthrough-main-image\"><img src=\"http://localhost:8080/togetherjs/images/walkthrough-images-logo.png\"></p>\n    <p>{{ gettext( \"Alright, you're ready to use TOOL_NAME. Now start collaborating on SITE_NAME!\" ) }}</p>\n  </section>\n\n  <div style=\"display: none\">\n    <!-- There is one of these created for each slide: -->\n    <span id=\"togetherjs-template-walkthrough-slide-progress\" class=\"togetherjs-walkthrough-slide-progress\">&#9679;</span>\n  </div>\n  <section id=\"togetherjs-walkthrough-progress\">\n  </section>\n\n  <section class=\"togetherjs-buttons\">\n    <button class=\"togetherjs-primary togetherjs-dismiss\">{{ gettext( \"I'm ready!\" )}}</button>\n  </section>\n\n</div><!-- /.togetherjs-modal -->\n"
  },
  {
    "path": "togetherjs/walkthrough.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\ndefine([\"util\", \"ui\", \"jquery\", \"windowing\", \"templates\", \"templating\", \"session\", \"peers\"], function (util, ui, $, windowing, templates, templating, session, peers) {\n  var assert = util.assert;\n  var walkthrough = util.Module(\"walkthrough\");\n  var onHideAll = null;\n  var container = null;\n\n  var slides = null;\n\n  walkthrough.start = function (firstTime, doneCallback) {\n    if (! container) {\n      container = $(templates(\"walkthrough\"));\n      container.hide();\n      ui.container.append(container);\n      slides = container.find(\".togetherjs-walkthrough-slide\");\n      slides.hide();\n      var progress = $(\"#togetherjs-walkthrough-progress\");\n      slides.each(function (index) {\n        var bullet = templating.sub(\"walkthrough-slide-progress\");\n        progress.append(bullet);\n        bullet.click(function () {\n          show(index);\n        });\n      });\n      container.find(\"#togetherjs-walkthrough-previous\").click(previous);\n      container.find(\"#togetherjs-walkthrough-next\").click(next);\n      ui.prepareShareLink(container);\n      container.find(\".togetherjs-self-name\").bind(\"keyup\", function (event) {\n        var val = $(event.target).val();\n        peers.Self.update({name: val});\n      });\n      container.find(\".togetherjs-swatch\").click(function () {\n        var picker = $(\"#togetherjs-pick-color\");\n        if (picker.is(\":visible\")) {\n          picker.hide();\n          return;\n        }\n        picker.show();\n        picker.find(\".togetherjs-swatch-active\").removeClass(\"togetherjs-swatch-active\");\n        picker.find(\".togetherjs-swatch[data-color=\\\"\" + peers.Self.color + \"\\\"]\").addClass(\"togetherjs-swatch-active\");\n        var location = container.find(\".togetherjs-swatch\").offset();\n        picker.css({\n          top: location.top,\n          // The -7 comes out of thin air, but puts it in the right place:\n          left: location.left-7\n        });\n      });\n      if (session.isClient) {\n        container.find(\".togetherjs-if-creator\").remove();\n        container.find(\".togetherjs-ifnot-creator\").show();\n      } else {\n        container.find(\".togetherjs-if-creator\").show();\n        container.find(\".togetherjs-ifnot-creator\").remove();\n      }\n      TogetherJS.config.track(\"siteName\", function (value) {\n        value = value || document.title;\n        container.find(\".togetherjs-site-name\").text(value);\n      });\n      ui.activateAvatarEdit(container, {\n        onSave: function () {\n          container.find(\"#togetherjs-avatar-when-saved\").show();\n          container.find(\"#togetherjs-avatar-when-unsaved\").hide();\n        },\n        onPending: function () {\n          container.find(\"#togetherjs-avatar-when-saved\").hide();\n          container.find(\"#togetherjs-avatar-when-unsaved\").show();\n        }\n      });\n      // This triggers substititions in the walkthrough:\n      peers.Self.update({});\n      session.emit(\"new-element\", container);\n    }\n    assert(typeof firstTime == \"boolean\", \"You must provide a firstTime boolean parameter\");\n    if (firstTime) {\n      container.find(\".togetherjs-walkthrough-firsttime\").show();\n      container.find(\".togetherjs-walkthrough-not-firsttime\").hide();\n    } else {\n      container.find(\".togetherjs-walkthrough-firsttime\").hide();\n      container.find(\".togetherjs-walkthrough-not-firsttime\").show();\n    }\n    onHideAll = doneCallback;\n    show(0);\n    windowing.show(container);\n  };\n\n  function show(index) {\n    slides.hide();\n    $(slides[index]).show();\n    var bullets = container.find(\"#togetherjs-walkthrough-progress .togetherjs-walkthrough-slide-progress\");\n    bullets.removeClass(\"togetherjs-active\");\n    $(bullets[index]).addClass(\"togetherjs-active\");\n    var $next = $(\"#togetherjs-walkthrough-next\").removeClass(\"togetherjs-disabled\");\n    var $previous = $(\"#togetherjs-walkthrough-previous\").removeClass(\"togetherjs-disabled\");\n    if (index == slides.length - 1) {\n      $next.addClass(\"togetherjs-disabled\");\n    } else if (index === 0) {\n      $previous.addClass(\"togetherjs-disabled\");\n    }\n  }\n\n  function previous() {\n    var index = getIndex();\n    index--;\n    if (index < 0) {\n      index = 0;\n    }\n    show(index);\n  }\n\n  function next() {\n    var index = getIndex();\n    index++;\n    if (index >= slides.length) {\n      index = slides.length-1;\n    }\n    show(index);\n  }\n\n  function getIndex() {\n    var active = slides.filter(\":visible\");\n    if (! active.length) {\n      return 0;\n    }\n    for (var i=0; i<slides.length; i++) {\n      if (slides[i] == active[0]) {\n        return i;\n      }\n    }\n    return 0;\n  }\n\n  walkthrough.stop = function () {\n    windowing.hide(container);\n    if (onHideAll) {\n      onHideAll();\n      onHideAll = null;\n    }\n  };\n\n  session.on(\"hide-window\", function () {\n    if (onHideAll) {\n      onHideAll();\n      onHideAll = null;\n    }\n  });\n\n  return walkthrough;\n});\n"
  },
  {
    "path": "togetherjs/webrtc.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// WebRTC support -- Note that this relies on parts of the interface code that usually goes in ui.js\n\ndefine([\"require\", \"jquery\", \"util\", \"session\", \"ui\", \"peers\", \"storage\", \"windowing\"], function (require, $, util, session, ui, peers, storage, windowing) {\n  var webrtc = util.Module(\"webrtc\");\n  var assert = util.assert;\n\n  session.RTCSupported = !!(window.mozRTCPeerConnection ||\n                            window.webkitRTCPeerConnection ||\n                            window.RTCPeerConnection);\n\n  if (session.RTCSupported && $.browser.mozilla && parseInt($.browser.version, 10) <= 19) {\n    // In a few versions of Firefox (18 and 19) these APIs are present but\n    // not actually usable\n    // See: https://bugzilla.mozilla.org/show_bug.cgi?id=828839\n    // Because they could be pref'd on we'll do a quick check:\n    try {\n      (function () {\n        var conn = new window.mozRTCPeerConnection();\n      })();\n    } catch (e) {\n      session.RTCSupported = false;\n    }\n  }\n\n  var mediaConstraints = {\n    mandatory: {\n      OfferToReceiveAudio: true,\n      OfferToReceiveVideo: false\n    }\n  };\n  if (window.mozRTCPeerConnection) {\n    mediaConstraints.mandatory.MozDontOfferDataChannel = true;\n  }\n\n  var URL = window.webkitURL || window.URL;\n  var RTCSessionDescription = window.mozRTCSessionDescription || window.webkitRTCSessionDescription || window.RTCSessionDescription;\n  var RTCIceCandidate = window.mozRTCIceCandidate || window.webkitRTCIceCandidate || window.RTCIceCandidate;\n\n  function makePeerConnection() {\n    // Based roughly off: https://github.com/firebase/gupshup/blob/gh-pages/js/chat.js\n    if (window.webkitRTCPeerConnection) {\n      return new webkitRTCPeerConnection({\n        \"iceServers\": [{\"url\": \"stun:stun.l.google.com:19302\"}]\n      }, {\n        \"optional\": [{\"DtlsSrtpKeyAgreement\": true}]\n      });\n    }\n    if (window.mozRTCPeerConnection) {\n      return new mozRTCPeerConnection({\n        // Or stun:124.124.124..2 ?\n        \"iceServers\": [{\"url\": \"stun:23.21.150.121\"}]\n      }, {\n        \"optional\": []\n      });\n    }\n    throw new util.AssertionError(\"Called makePeerConnection() without supported connection\");\n  }\n\n  function ensureCryptoLine(sdp) {\n    if (! window.mozRTCPeerConnection) {\n      return sdp;\n    }\n\n    var sdpLinesIn = sdp.split('\\r\\n');\n    var sdpLinesOut = [];\n\n    // Search for m line.\n    for (var i = 0; i < sdpLinesIn.length; i++) {\n      sdpLinesOut.push(sdpLinesIn[i]);\n      if (sdpLinesIn[i].search('m=') !== -1) {\n        sdpLinesOut.push(\"a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\");\n      }\n    }\n\n    sdp = sdpLinesOut.join('\\r\\n');\n    return sdp;\n  }\n\n  function getUserMedia(options, success, failure) {\n    failure = failure || function (error) {\n      console.error(\"Error in getUserMedia:\", error);\n    };\n    (navigator.getUserMedia ||\n     navigator.mozGetUserMedia ||\n     navigator.webkitGetUserMedia ||\n     navigator.msGetUserMedia).call(navigator, options, success, failure);\n  }\n\n  /****************************************\n   * getUserMedia Avatar support\n   */\n\n  session.on(\"ui-ready\", function () {\n    $(\"#togetherjs-self-avatar\").click(function () {\n      var avatar = peers.Self.avatar;\n      if (avatar) {\n        $preview.attr(\"src\", avatar);\n      }\n      ui.displayToggle(\"#togetherjs-avatar-edit\");\n    });\n    if (! session.RTCSupported) {\n      $(\"#togetherjs-avatar-edit-rtc\").hide();\n    }\n\n    var avatarData = null;\n    var $preview = $(\"#togetherjs-self-avatar-preview\");\n    var $accept = $(\"#togetherjs-self-avatar-accept\");\n    var $cancel = $(\"#togetherjs-self-avatar-cancel\");\n    var $takePic = $(\"#togetherjs-avatar-use-camera\");\n    var $video = $(\"#togetherjs-avatar-video\");\n    var $upload = $(\"#togetherjs-avatar-upload\");\n\n    $takePic.click(function () {\n      if (! streaming) {\n        startStreaming();\n        return;\n      }\n      takePicture();\n    });\n\n    function savePicture(dataUrl) {\n      avatarData = dataUrl;\n      $preview.attr(\"src\", avatarData);\n      $accept.attr(\"disabled\", null);\n    }\n\n    $accept.click(function () {\n      peers.Self.update({avatar:  avatarData});\n      ui.displayToggle(\"#togetherjs-no-avatar-edit\");\n      // FIXME: these probably shouldn't be two elements:\n      $(\"#togetherjs-participants-other\").show();\n      $accept.attr(\"disabled\", \"1\");\n    });\n\n    $cancel.click(function () {\n      ui.displayToggle(\"#togetherjs-no-avatar-edit\");\n      // FIXME: like above:\n      $(\"#togetherjs-participants-other\").show();\n    });\n\n    var streaming = false;\n    function startStreaming() {\n      getUserMedia({\n          video: true,\n          audio: false\n        },\n        function(stream) {\n          streaming = true;\n          $video[0].src = URL.createObjectURL(stream);\n          $video[0].play();\n        },\n        function(err) {\n          // FIXME: should pop up help or something in the case of a user\n          // cancel\n          console.error(\"getUserMedia error:\", err);\n        }\n      );\n    }\n\n    function takePicture() {\n      assert(streaming);\n      var height = $video[0].videoHeight;\n      var width = $video[0].videoWidth;\n      width = width * (session.AVATAR_SIZE / height);\n      height = session.AVATAR_SIZE;\n      var $canvas = $(\"<canvas>\");\n      $canvas[0].height = session.AVATAR_SIZE;\n      $canvas[0].width = session.AVATAR_SIZE;\n      var context = $canvas[0].getContext(\"2d\");\n      context.arc(session.AVATAR_SIZE/2, session.AVATAR_SIZE/2, session.AVATAR_SIZE/2, 0, Math.PI*2);\n      context.closePath();\n      context.clip();\n      context.drawImage($video[0], (session.AVATAR_SIZE - width) / 2, 0, width, height);\n      savePicture($canvas[0].toDataURL(\"image/png\"));\n    }\n\n    $upload.on(\"change\", function () {\n      var reader = new FileReader();\n      reader.onload = function () {\n        // FIXME: I don't actually know it's JPEG, but it's probably a\n        // good enough guess:\n        var url = \"data:image/jpeg;base64,\" + util.blobToBase64(this.result);\n        convertImage(url, function (result) {\n          savePicture(result);\n        });\n      };\n      reader.onerror = function () {\n        console.error(\"Error reading file:\", this.error);\n      };\n      reader.readAsArrayBuffer(this.files[0]);\n    });\n\n    function convertImage(imageUrl, callback) {\n      var $canvas = $(\"<canvas>\");\n      $canvas[0].height = session.AVATAR_SIZE;\n      $canvas[0].width = session.AVATAR_SIZE;\n      var context = $canvas[0].getContext(\"2d\");\n      var img = new Image();\n      img.src = imageUrl;\n      // Sometimes the DOM updates immediately to call\n      // naturalWidth/etc, and sometimes it doesn't; using setTimeout\n      // gives it a chance to catch up\n      setTimeout(function () {\n        var width = img.naturalWidth || img.width;\n        var height = img.naturalHeight || img.height;\n        width = width * (session.AVATAR_SIZE / height);\n        height = session.AVATAR_SIZE;\n        context.drawImage(img, 0, 0, width, height);\n        callback($canvas[0].toDataURL(\"image/png\"));\n      });\n    }\n\n  });\n\n  /****************************************\n   * RTC support\n   */\n\n  function audioButton(selector) {\n    ui.displayToggle(selector);\n    if (selector == \"#togetherjs-audio-incoming\") {\n      $(\"#togetherjs-audio-button\").addClass(\"togetherjs-animated\").addClass(\"togetherjs-color-alert\");\n    } else {\n      $(\"#togetherjs-audio-button\").removeClass(\"togetherjs-animated\").removeClass(\"togetherjs-color-alert\");\n    }\n  }\n\n  session.on(\"ui-ready\", function () {\n    $(\"#togetherjs-audio-button\").click(function () {\n      if ($(\"#togetherjs-rtc-info\").is(\":visible\")) {\n        windowing.hide();\n        return;\n      }\n      if (session.RTCSupported) {\n        enableAudio();\n      } else {\n        windowing.show(\"#togetherjs-rtc-not-supported\");\n      }\n    });\n\n    if (! session.RTCSupported) {\n      audioButton(\"#togetherjs-audio-unavailable\");\n      return;\n    }\n    audioButton(\"#togetherjs-audio-ready\");\n\n    var audioStream = null;\n    var accepted = false;\n    var connected = false;\n    var $audio = $(\"#togetherjs-audio-element\");\n    var offerSent = null;\n    var offerReceived = null;\n    var offerDescription = false;\n    var answerSent = null;\n    var answerReceived = null;\n    var answerDescription = false;\n    var _connection = null;\n    var iceCandidate = null;\n\n    function enableAudio() {\n      accepted = true;\n      storage.settings.get(\"dontShowRtcInfo\").then(function (dontShow) {\n        if (! dontShow) {\n          windowing.show(\"#togetherjs-rtc-info\");\n        }\n      });\n      if (! audioStream) {\n        startStreaming(connect);\n        return;\n      }\n      if (! connected) {\n        connect();\n      }\n      toggleMute();\n    }\n\n    ui.container.find(\"#togetherjs-rtc-info .togetherjs-dont-show-again\").change(function () {\n      storage.settings.set(\"dontShowRtcInfo\", this.checked);\n    });\n\n    function error() {\n      console.warn.apply(console, arguments);\n      var s = \"\";\n      for (var i=0; i<arguments.length; i++) {\n        if (s) {\n          s += \" \";\n        }\n        var a = arguments[i];\n        if (typeof a == \"string\") {\n          s += a;\n        } else {\n          var repl;\n          try {\n            repl = JSON.stringify(a);\n          } catch (e) {\n          }\n          if (! repl) {\n            repl = \"\" + a;\n          }\n          s += repl;\n        }\n      }\n      audioButton(\"#togetherjs-audio-error\");\n      // FIXME: this title doesn't seem to display?\n      $(\"#togetherjs-audio-error\").attr(\"title\", s);\n    }\n\n    function startStreaming(callback) {\n      getUserMedia(\n        {\n          video: false,\n          audio: true\n        },\n        function (stream) {\n          audioStream = stream;\n          attachMedia(\"#togetherjs-local-audio\", stream);\n          if (callback) {\n            callback();\n          }\n        },\n        function (err) {\n          // FIXME: handle cancel case\n          if (err && err.code == 1) {\n            // User cancel\n            return;\n          }\n          error(\"getUserMedia error:\", err);\n        }\n      );\n    }\n\n    function attachMedia(element, media) {\n      element = $(element)[0];\n      console.log(\"Attaching\", media, \"to\", element);\n      if (window.mozRTCPeerConnection) {\n        element.mozSrcObject = media;\n        element.play();\n      } else {\n        element.autoplay = true;\n        element.src = URL.createObjectURL(media);\n      }\n    }\n\n    function getConnection() {\n      assert(audioStream);\n      if (_connection) {\n        return _connection;\n      }\n      try {\n        _connection = makePeerConnection();\n      } catch (e) {\n        error(\"Error creating PeerConnection:\", e);\n        throw e;\n      }\n      _connection.onaddstream = function (event) {\n        console.log(\"got event\", event, event.type);\n        attachMedia($audio, event.stream);\n        audioButton(\"#togetherjs-audio-active\");\n      };\n      _connection.onstatechange = function () {\n        // FIXME: this doesn't seem to work:\n        // Actually just doesn't work on Firefox\n        console.log(\"state change\", _connection.readyState);\n        if (_connection.readyState == \"closed\") {\n          audioButton(\"#togetherjs-audio-ready\");\n        }\n      };\n      _connection.onicecandidate = function (event) {\n        if (event.candidate) {\n          session.send({\n            type: \"rtc-ice-candidate\",\n            candidate: {\n              sdpMLineIndex: event.candidate.sdpMLineIndex,\n              sdpMid: event.candidate.sdpMid,\n              candidate: event.candidate.candidate\n            }\n          });\n        }\n      };\n      _connection.addStream(audioStream);\n      return _connection;\n    }\n\n    function addIceCandidate() {\n      if (iceCandidate) {\n        console.log(\"adding ice\", iceCandidate);\n        _connection.addIceCandidate(new RTCIceCandidate(iceCandidate));\n      }\n    }\n\n    function connect() {\n      var connection = getConnection();\n      if (offerReceived && (! offerDescription)) {\n        connection.setRemoteDescription(\n          new RTCSessionDescription({\n            type: \"offer\",\n            sdp: offerReceived\n          }),\n          function () {\n            offerDescription = true;\n            addIceCandidate();\n            connect();\n          },\n          function (err) {\n            error(\"Error doing RTC setRemoteDescription:\", err);\n          }\n        );\n        return;\n      }\n      if (! (offerSent || offerReceived)) {\n        connection.createOffer(function (offer) {\n          console.log(\"made offer\", offer);\n          offer.sdp = ensureCryptoLine(offer.sdp);\n          connection.setLocalDescription(\n            offer,\n            function () {\n              session.send({\n                type: \"rtc-offer\",\n                offer: offer.sdp\n              });\n              offerSent = offer;\n              audioButton(\"#togetherjs-audio-outgoing\");\n            },\n            function (err) {\n              error(\"Error doing RTC setLocalDescription:\", err);\n            },\n            mediaConstraints\n          );\n        }, function (err) {\n          error(\"Error doing RTC createOffer:\", err);\n        });\n      } else if (! (answerSent || answerReceived)) {\n        // FIXME: I might have only needed this due to my own bugs, this might\n        // not actually time out\n        var timeout = setTimeout(function () {\n          if (! answerSent) {\n            error(\"createAnswer Timed out; reload or restart browser\");\n          }\n        }, 2000);\n        connection.createAnswer(function (answer) {\n          answer.sdp = ensureCryptoLine(answer.sdp);\n          clearTimeout(timeout);\n          connection.setLocalDescription(\n            answer,\n            function () {\n              session.send({\n                type: \"rtc-answer\",\n                answer: answer.sdp\n              });\n              answerSent = answer;\n            },\n            function (err) {\n              clearTimeout(timeout);\n              error(\"Error doing RTC setLocalDescription:\", err);\n            },\n            mediaConstraints\n          );\n        }, function (err) {\n          error(\"Error doing RTC createAnswer:\", err);\n        });\n      }\n    }\n\n    function toggleMute() {\n      // FIXME: implement.  Actually, wait for this to be implementable - currently\n      // muting of localStreams isn't possible\n      // FIXME: replace with hang-up?\n    }\n\n    session.hub.on(\"rtc-offer\", function (msg) {\n      if (offerReceived || answerSent || answerReceived || offerSent) {\n        abort();\n      }\n      offerReceived = msg.offer;\n      if (! accepted) {\n        audioButton(\"#togetherjs-audio-incoming\");\n        return;\n      }\n      function run() {\n        var connection = getConnection();\n        connection.setRemoteDescription(\n          new RTCSessionDescription({\n            type: \"offer\",\n            sdp: offerReceived\n          }),\n          function () {\n            offerDescription = true;\n            addIceCandidate();\n            connect();\n          },\n          function (err) {\n            error(\"Error doing RTC setRemoteDescription:\", err);\n          }\n        );\n      }\n      if (! audioStream) {\n        startStreaming(run);\n      } else {\n        run();\n      }\n    });\n\n    session.hub.on(\"rtc-answer\", function (msg) {\n      if (answerSent || answerReceived || offerReceived || (! offerSent)) {\n        abort();\n        // Basically we have to abort and try again.  We'll expect the other\n        // client to restart when appropriate\n        session.send({type: \"rtc-abort\"});\n        return;\n      }\n      answerReceived = msg.answer;\n      assert(offerSent);\n      assert(audioStream);\n      var connection = getConnection();\n      connection.setRemoteDescription(\n        new RTCSessionDescription({\n          type: \"answer\",\n          sdp: answerReceived\n        }),\n        function () {\n          answerDescription = true;\n          // FIXME: I don't think this connect is ever needed?\n          connect();\n        },\n        function (err) {\n          error(\"Error doing RTC setRemoteDescription:\", err);\n        }\n      );\n    });\n\n    session.hub.on(\"rtc-ice-candidate\", function (msg) {\n      iceCandidate = msg.candidate;\n      if (offerDescription || answerDescription) {\n        addIceCandidate();\n      }\n    });\n\n    session.hub.on(\"rtc-abort\", function (msg) {\n      abort();\n      if (! accepted) {\n        return;\n      }\n      if (! audioStream) {\n        startStreaming(function () {\n          connect();\n        });\n      } else {\n        connect();\n      }\n    });\n\n    session.hub.on(\"hello\", function (msg) {\n      // FIXME: displayToggle should be set due to\n      // _connection.onstatechange, but that's not working, so\n      // instead:\n      audioButton(\"#togetherjs-audio-ready\");\n      if (accepted && (offerSent || answerSent)) {\n        abort();\n        connect();\n      }\n    });\n\n    function abort() {\n      answerSent = answerReceived = offerSent = offerReceived = null;\n      answerDescription = offerDescription = false;\n      _connection = null;\n      $audio[0].removeAttribute(\"src\");\n    }\n\n  });\n\n  return webrtc;\n\n});\n"
  },
  {
    "path": "togetherjs/who.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\ndefine([\"util\", \"channels\", \"session\", \"ui\"], function (util, channels, session, ui) {\n  var assert = util.assert;\n  var who = util.Module(\"who\");\n  var MAX_RESPONSE_TIME = 5000;\n  var MAX_LATE_RESPONSE = 2000;\n\n  who.getList = function (hubUrl) {\n    return util.Deferred(function (def) {\n      var expected;\n      var channel = channels.WebSocketChannel(hubUrl);\n      var users = {};\n      var responded = 0;\n      var firstResponse = 0;\n      var lateResponseTimeout;\n      channel.onmessage = function (msg) {\n        if (msg.type == \"init-connection\") {\n          expected = msg.peerCount;\n        }\n        if (msg.type == \"who\") {\n          // Our message back to ourselves probably\n          firstResponse = setTimeout(function () {\n            close();\n          }, MAX_LATE_RESPONSE);\n        }\n        if (msg.type == \"hello-back\") {\n          if (! users[msg.clientId]) {\n            users[msg.clientId] = who.ExternalPeer(msg.clientId, msg);\n            responded++;\n            if (expected && responded >= expected) {\n              close();\n            } else {\n              def.notify(users);\n            }\n          }\n        }\n        console.log(\"users\", users);\n      };\n      channel.send({\n        type: \"who\",\n        \"server-echo\": true,\n        clientId: null\n      });\n      var timeout = setTimeout(function () {\n        close();\n      }, MAX_RESPONSE_TIME);\n      function close() {\n        if (timeout) {\n          clearTimeout(timeout);\n        }\n        if (lateResponseTimeout) {\n          clearTimeout(lateResponseTimeout);\n        }\n        channel.close();\n        def.resolve(users);\n      }\n    });\n  };\n\n  who.invite = function (hubUrl, clientId) {\n    return util.Deferred(function (def) {\n      var channel = channels.WebSocketChannel(hubUrl);\n      var id = util.generateId();\n      channel.onmessage = function (msg) {\n        if (msg.type == \"invite\" && msg.inviteId == id) {\n          channel.close();\n          def.resolve();\n        }\n      };\n      var userInfo = session.makeHelloMessage(false);\n      delete userInfo.type;\n      userInfo.clientId = session.clientId;\n      channel.send({\n        type: \"invite\",\n        inviteId: id,\n        url: session.shareUrl(),\n        userInfo: userInfo,\n        forClientId: clientId,\n        clientId: null,\n        \"server-echo\": true\n      });\n    });\n  };\n\n  who.ExternalPeer = util.Class({\n    isSelf: false,\n    isExternal: true,\n    constructor: function (id, attrs) {\n      attrs = attrs || {};\n      assert(id);\n      this.id = id;\n      this.identityId = attrs.identityId || null;\n      this.status = attrs.status || \"live\";\n      this.idle = attrs.status || \"active\";\n      this.name = attrs.name || null;\n      this.avatar = attrs.avatar || null;\n      this.color = attrs.color || \"#00FF00\";\n      this.lastMessageDate = 0;\n      this.view = ui.PeerView(this);\n    },\n\n    className: function (prefix) {\n      prefix = prefix || \"\";\n      return prefix + util.safeClassName(this.id);\n    }\n\n  });\n\n  return who;\n});\n"
  },
  {
    "path": "togetherjs/windowing.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */\ndefine([\"jquery\", \"util\", \"peers\", \"session\"], function ($, util, peers, session) {\n  var assert = util.assert;\n  var windowing = util.Module(\"windowing\");\n  var $window = $(window);\n  // This is also in togetherjs.less, under .togetherjs-animated\n  var ANIMATION_DURATION = 1000;\n\n  /* Displays one window.  A window must already exist.  This hides other windows, and\n     positions the window according to its data-bound-to attributes */\n  windowing.show = function (element, options) {\n    element = $(element);\n    options = options || {};\n    options.bind = options.bind || element.attr(\"data-bind-to\");\n    var notification = element.hasClass(\"togetherjs-notification\");\n    var modal = element.hasClass(\"togetherjs-modal\");\n    if (options.bind) {\n      options.bind = $(options.bind);\n    }\n    windowing.hide();\n    element.stop();\n    element.show();\n    // In addition to being hidden, the window can be faded out, which we want to undo:\n    element.css({opacity: \"1\"});\n    if (options.bind) {\n      assert(! modal, \"Binding does not currently work with modals\");\n      bind(element, options.bind);\n    }\n    if (notification) {\n      element.slideIn();\n    } else if (! modal) {\n      element.popinWindow();\n    }\n    if (modal) {\n      getModalBackground().show();\n      modalEscape.bind();\n    }\n    onClose = options.onClose || null;\n    session.emit(\"display-window\", element.attr(\"id\"), element);\n  };\n\n  var onClose = null;\n\n  /* Moves a window to be attached to data-bind-to, e.g., the button\n     that opened the window. Or you can provide an element that it should bind to. */\n  function bind(win, bound) {\n    if ($.browser.mobile) {\n      return;\n    }\n    win = $(win);\n    assert(bound.length, \"Cannot find binding:\", bound.selector, \"from:\", win.selector);\n    // FIXME: hardcoding\n    var ifacePos = \"right\";\n    //var ifacePos = panelPosition();\n    var boundPos = bound.offset();\n    boundPos.height = bound.height();\n    boundPos.width = bound.width();\n    var windowHeight = $window.height();\n    boundPos.top -= $window.scrollTop();\n    boundPos.left -= $window.scrollLeft();\n    // FIXME: I appear to have to add the padding to the width to get a \"true\"\n    // width.  But it's still not entirely consistent.\n    var height = win.height() + 5;\n    var width = win.width() + 20;\n    var left, top;\n    if (ifacePos == \"right\") {\n      left = boundPos.left - 11 - width;\n      top = boundPos.top + (boundPos.height / 2) - (height / 2);\n    } else if (ifacePos == \"left\") {\n      left = boundPos.left + boundPos.width + 15;\n      top = boundPos.top + (boundPos.height / 2) - (height / 2);\n    } else if (ifacePos == \"bottom\") {\n      left = (boundPos.left + boundPos.width / 2) - (width / 2);\n      top = boundPos.top - 10 - height;\n    }\n    top = Math.min(windowHeight - 10 - height, Math.max(10, top));\n    win.css({\n      top: top + \"px\",\n      left: left + \"px\"\n    });\n    if (win.hasClass(\"togetherjs-window\")) {\n      $(\"#togetherjs-window-pointer-right, #togetherjs-window-pointer-left\").hide();\n      var pointer = $(\"#togetherjs-window-pointer-\" + ifacePos);\n      pointer.show();\n      if (ifacePos == \"right\") {\n        pointer.css({\n          top: boundPos.top + Math.floor(boundPos.height / 2) + \"px\",\n          left: left + win.width() + 9 + \"px\"\n        });\n      } else if (ifacePos == \"left\") {\n        pointer.css({\n          top: boundPos.top + Math.floor(boundPos.height / 2) + \"px\",\n          left: (left - 5) + \"px\"\n        });\n      } else {\n        console.warn(\"don't know how to deal with position:\", ifacePos);\n      }\n    }\n    win.data(\"boundTo\", bound.selector || \"#\" + bound.attr(\"id\"));\n    bound.addClass(\"togetherjs-active\");\n  }\n\n  session.on(\"resize\", function () {\n    var win = $(\".togetherjs-modal:visible, .togetherjs-window:visible\");\n    if (! win.length) {\n      return;\n    }\n    var boundTo = win.data(\"boundTo\");\n    if (! boundTo) {\n      return;\n    }\n    boundTo = $(boundTo);\n    bind(win, boundTo);\n  });\n\n  windowing.hide = function (els) {\n    // FIXME: also hide modals?\n    els = els || \".togetherjs-window, .togetherjs-modal, .togetherjs-notification\";\n    els = $(els);\n    els = els.filter(\":visible\");\n    els.filter(\":not(.togetherjs-notification)\").hide();\n    getModalBackground().hide();\n    var windows = [];\n    els.each(function (index, element) {\n      element = $(element);\n      windows.push(element);\n      var bound = element.data(\"boundTo\");\n      if (! bound) {\n        return;\n      }\n      bound = $(bound);\n      bound.addClass(\"togetherjs-animated\").addClass(\"togetherjs-color-pulse\");\n      setTimeout(function () {\n        bound.removeClass(\"togetherjs-color-pulse\").removeClass(\"togetherjs-animated\");\n      }, ANIMATION_DURATION+10);\n      element.data(\"boundTo\", null);\n      bound.removeClass(\"togetherjs-active\");\n      if (element.hasClass(\"togetherjs-notification\")) {\n        element.fadeOut().promise().then(function () {\n          this.hide();\n        });\n      }\n    });\n    $(\"#togetherjs-window-pointer-right, #togetherjs-window-pointer-left\").hide();\n    if (onClose) {\n      onClose();\n      onClose = null;\n    }\n    if (windows.length) {\n      session.emit(\"hide-window\", windows);\n    }\n  };\n\n  windowing.showNotification = function (element, options) {\n    element = $(element);\n    options = options || {};\n    assert(false);\n  };\n\n  windowing.toggle = function (el) {\n    el = $(el);\n    if (el.is(\":visible\")) {\n      windowing.hide(el);\n    } else {\n      windowing.show(el);\n    }\n  };\n\n  function bindEvents(el) {\n    el.find(\".togetherjs-close, .togetherjs-dismiss\").click(function (event) {\n      var w = $(event.target).closest(\".togetherjs-window, .togetherjs-modal, .togetherjs-notification\");\n      windowing.hide(w);\n      event.stopPropagation();\n      return false;\n    });\n  }\n\n  function getModalBackground() {\n    if (getModalBackground.element) {\n      return getModalBackground.element;\n    }\n    var background = $(\"#togetherjs-modal-background\");\n    assert(background.length);\n    getModalBackground.element = background;\n    background.click(function () {\n      windowing.hide();\n    });\n    return background;\n  }\n\n  var modalEscape = {\n    bind: function () {\n      $(document).keydown(modalEscape.onKeydown);\n    },\n    unbind: function () {\n      $(document).unbind(\"keydown\", modalEscape.onKeydown);\n    },\n    onKeydown: function (event) {\n      if (event.which == 27) {\n        windowing.hide();\n      }\n    }\n  };\n\n  session.on(\"close\", function () {\n    modalEscape.unbind();\n  });\n\n  session.on(\"new-element\", function (el) {\n    bindEvents(el);\n  });\n\n  return windowing;\n});\n"
  },
  {
    "path": "togetherjs/youtubeVideos.js",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http:// mozilla.org/MPL/2.0/. */\n\ndefine([\"jquery\", \"util\", \"session\", \"elementFinder\"],\nfunction ($, util, session, elementFinder) {\n\n  // constant var to indicate whether two players are too far apart in sync\n  var TOO_FAR_APART = 3000;\n  // embedded youtube iframes\n  var youTubeIframes = [];\n  // youtube API load delay\n  var API_LOADING_DELAY = 2000;\n\n  session.on(\"reinitialize\", function () {\n    if (TogetherJS.config.get(\"youtube\")) {\n      prepareYouTube();\n    }\n  });\n\n  session.on(\"close\", function () {\n    $(youTubeIframes).each(function (i, iframe) {\n      // detach players from iframes\n      $(iframe).removeData(\"togetherjs-player\");\n      $(iframe).removeData(\"dontPublish\");\n      $(iframe).removeData(\"currentVideoId\");\n      // disable iframeAPI\n      $(iframe).removeAttr(\"enablejsapi\");\n      // remove unique youtube iframe indicators\n      var id = $(iframe).attr(\"id\") || \"\";\n      if (id.indexOf(\"youtube-player\") === 0) {\n        // An id we added\n        $(iframe).removeAttr(\"id\");\n      }\n      youTubeIframes = [];\n    });\n  });\n\n  $(function() {\n    TogetherJS.config.track(\"youtube\", function (track, previous) {\n      if (track && ! previous) {\n        prepareYouTube();\n        // You can enable youtube dynamically, but can't turn it off:\n        TogetherJS.config.close(\"youtube\");\n      }\n    });\n  });\n\n  var youtubeHooked = false;\n\n  function prepareYouTube() {\n    // setup iframes first\n    setupYouTubeIframes();\n\n    // this function should be global so it can be called when API is loaded\n    if (!youtubeHooked) {\n      youtubeHooked = true;\n      window.onYouTubeIframeAPIReady = (function(oldf) {\n        return function() {\n          // YouTube API is ready\n          $(youTubeIframes).each(function (i, iframe) {\n            var player = new YT.Player(iframe.id, { // get the reference to the already existing iframe\n              events: {\n                'onReady': insertPlayer,\n                'onStateChange': publishPlayerStateChange\n              }\n            });\n          });\n          if (oldf) {\n            return oldf();\n          }\n        };\n      })(window.onYouTubeIframeAPIReady);\n    }\n\n    if (window.YT === undefined) {\n      // load necessary API\n      // it calls onYouTubeIframeAPIReady automatically when the API finishes loading\n      var tag = document.createElement('script');\n      tag.src = \"https://www.youtube.com/iframe_api\";\n      var firstScriptTag = document.getElementsByTagName('script')[0];\n      firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n    } else {\n      // manually invoke APIReady function when the API was already loaded by user\n      onYouTubeIframeAPIReady();\n    }\n\n    // give each youtube iframe a unique id and set its enablejsapi param to true\n    function setupYouTubeIframes() {\n      var iframes = $('iframe');\n      iframes.each(function (i, iframe) {\n        // if the iframe's unique id is already set, skip it\n        // FIXME: what if the user manually sets an iframe's id (i.e. \"#my-youtube\")?\n        // maybe we should set iframes everytime togetherjs is reinitialized?\n        var osrc = $(iframe).attr(\"src\"), src = osrc;\n        if ((src || \"\").indexOf(\"youtube\") != -1 && !$(iframe).attr(\"id\")) {\n          $(iframe).attr(\"id\", \"youtube-player\"+i);\n          $(iframe).attr(\"enablejsapi\", 1);\n          // we also need to add ?enablejsapi to the iframe src.\n          if (!/[?&]enablejsapi=1(&|$)/.test(src)) {\n            src += (/[?]/.test(src)) ? '&' : '?';\n            src += 'enablejsapi=1';\n          }\n          // the youtube API seems to be unhappy unless the URL starts\n          // with https\n          if (!/^https[:]\\/\\//.test(src)) {\n            src = 'https://' + src.replace(/^(\\w+[:])?\\/\\//, '');\n          }\n          if (src !== osrc) {\n            $(iframe).attr(\"src\", src);\n          }\n          youTubeIframes[i] = iframe;\n        }\n      });\n    } // iframes are ready\n\n    function insertPlayer(event) {\n      // only when it is READY, attach a player to its iframe\n      var currentPlayer = event.target;\n      var currentIframe = currentPlayer.getIframe();\n      // check if a player is already attached in case of being reinitialized\n      if (!$(currentIframe).data(\"togetherjs-player\")) {\n        $(currentIframe).data(\"togetherjs-player\", currentPlayer);\n        // initialize its dontPublish flag as well\n        $(currentIframe).data(\"dontPublish\", false);\n        // store its current video's id\n        var currentVideoId = getVideoIdFromUrl(currentPlayer.getVideoUrl());\n        $(currentIframe).data(\"currentVideoId\", currentVideoId);\n      }\n    }\n  } // end of prepareYouTube\n\n  function publishPlayerStateChange(event) {\n    var target = event.target;\n    var currentIframe = target.getIframe();\n    //var currentPlayer = $(currentIframe).data(\"togetherjs-player\");\n    var currentPlayer = target;\n    var currentTime = currentPlayer.getCurrentTime();\n    //var currentTime = target.k.currentTime;\n    var iframeLocation = elementFinder.elementLocation(currentIframe);\n\n    if ($(currentPlayer).data(\"seek\")) {\n      $(currentPlayer).removeData(\"seek\");\n      return;\n    }\n\n    // do not publish if playerState was changed by other users\n    if ($(currentIframe).data(\"dontPublish\")) {\n      // make it false again so it can start publishing events of its own state changes\n      $(currentIframe).data(\"dontPublish\", false);\n      return;\n    }\n\n    // notify other people that I changed the player state\n    if (event.data == YT.PlayerState.PLAYING) {\n\n      var currentVideoId = isDifferentVideoLoaded(currentIframe);\n      if (currentVideoId) {\n        // notify that I just loaded another video\n        publishDifferentVideoLoaded(iframeLocation, currentVideoId);\n        // update current video id\n        $(currentIframe).data(\"currentVideoId\", currentVideoId);\n      } else {\n        session.send({\n          type: \"playerStateChange\",\n          element: iframeLocation,\n          playerState: 1,\n          playerTime: currentTime\n        });\n      }\n    } else if (event.data == YT.PlayerState.PAUSED) {\n      session.send({\n        type: \"playerStateChange\",\n        element: iframeLocation,\n        playerState: 2,\n        playerTime: currentTime\n      });\n    } else {\n      // do nothing when the state is buffering, cued, or ended\n      return;\n    }\n  }\n\n  function publishDifferentVideoLoaded(iframeLocation, videoId) {\n    session.send({\n      type: \"differentVideoLoaded\",\n      videoId: videoId,\n      element: iframeLocation\n    });\n  }\n\n  session.hub.on('playerStateChange', function (msg) {\n    var iframe = elementFinder.findElement(msg.element);\n    var player = $(iframe).data(\"togetherjs-player\");\n    var currentTime = player.getCurrentTime();\n    var currentState = player.getPlayerState();\n\n    if (currentState != msg.playerState) {\n      $(iframe).data(\"dontPublish\", true);\n    }\n\n    if (msg.playerState == 1) {\n      player.playVideo();\n      // seekTo() updates the video's time and plays it if it was already playing\n      // and pauses it if it was already paused\n      if (areTooFarApart(currentTime, msg.playerTime)) {\n        player.seekTo(msg.playerTime, true);\n      }\n    } else if (msg.playerState == 2) {\n      // When YouTube videos are advanced while playing,\n      // Chrome: pause -> pause -> play (onStateChange is called even when it is from pause to pause)\n      // FireFox: buffering -> play -> buffering -> play\n      // We must prevent advanced videos from going out of sync\n      player.pauseVideo();\n      if (areTooFarApart(currentTime, msg.playerTime)) {\n        // \"seek\" flag will help supress publishing unwanted state changes\n        $(player).data(\"seek\", true);\n        player.seekTo(msg.playerTime, true);\n      }\n    }\n  });\n\n  // if a late user joins a channel, synchronize his videos\n  session.hub.on('hello', function () {\n    // wait a couple seconds to make sure the late user has finished loading API\n    setTimeout(synchronizeVideosOfLateGuest, API_LOADING_DELAY);\n  });\n\n  session.hub.on('synchronizeVideosOfLateGuest', function (msg) {\n    // XXX can this message arrive before we're initialized?\n    var iframe = elementFinder.findElement(msg.element);\n    var player = $(iframe).data(\"togetherjs-player\");\n    // check if another video had been loaded to an existing iframe before I joined\n    var currentVideoId = getVideoIdFromUrl(player.getVideoUrl());\n    if (msg.videoId != currentVideoId) {\n      $(iframe).data(\"currentVideoId\", msg.videoId);\n      player.loadVideoById(msg.videoId, msg.playerTime, 'default');\n    } else {\n      // if the video is only cued, I do not have to do anything to sync\n      if (msg.playerState != 5) {\n        player.seekTo(msg.playerTime, true).playVideo();\n      }\n    }\n  });\n\n  session.hub.on('differentVideoLoaded', function (msg) {\n    // load a new video if the host has loaded one\n    var iframe = elementFinder.findElement(msg.element);\n    var player = $(iframe).data(\"togetherjs-player\");\n    player.loadVideoById(msg.videoId, 0, 'default');\n    $(iframe).data(\"currentVideoId\", msg.videoId);\n\n  });\n\n  function synchronizeVideosOfLateGuest() {\n    youTubeIframes.forEach(function (iframe) {\n      var currentPlayer = $(iframe).data(\"togetherjs-player\");\n      var currentVideoId = getVideoIdFromUrl(currentPlayer.getVideoUrl());\n      var currentState = currentPlayer.getPlayerState();\n      var currentTime = currentPlayer.getCurrentTime();\n      var iframeLocation = elementFinder.elementLocation(iframe);\n      session.send({\n        type: \"synchronizeVideosOfLateGuest\",\n        element: iframeLocation,\n        videoId: currentVideoId,\n        playerState: currentState, //this might be necessary later\n        playerTime: currentTime\n      });\n    });\n  }\n\n  function isDifferentVideoLoaded(iframe) {\n    var lastVideoId = $(iframe).data(\"currentVideoId\");\n    var currentPlayer = $(iframe).data(\"togetherjs-player\");\n    var currentVideoId = getVideoIdFromUrl(currentPlayer.getVideoUrl());\n\n    // since url forms of iframe src and player's video url are different,\n    // I have to compare the video ids\n    if (currentVideoId != lastVideoId) {\n      return currentVideoId;\n    } else {\n      return false;\n    }\n  }\n\n  // parses videoId from the url returned by getVideoUrl function\n  function getVideoIdFromUrl(videoUrl) {\n    var videoId = videoUrl.split('v=')[1];\n    //Chrome and Firefox have different positions for parameters\n    var ampersandIndex = videoId.indexOf('&');\n    if (ampersandIndex != -1) {\n      videoId = videoId.substring(0, ampersandIndex);\n    }\n    return videoId;\n  }\n\n  function areTooFarApart(myTime, theirTime) {\n    var secDiff = Math.abs(myTime - theirTime);\n    var milliDiff = secDiff * 1000;\n    return milliDiff > TOO_FAR_APART;\n  }\n});\n"
  }
]